Search code examples
cblendergltf

Is this a correct glTF file? There are duplicate vertices


I am working with blender 3.6 and I have exported a simple cube under the glTF format:

{
    "asset":{
        "generator":"Khronos glTF Blender I/O v3.6.27",
        "version":"2.0"
    },
    "scene":0,
    "scenes":[
        {
            "name":"Scene",
            "nodes":[
                0
            ]
        }
    ],
    "nodes":[
        {
            "mesh":0,
            "name":"Cube"
        }
    ],
    "materials":[
        {
            "doubleSided":true,
            "name":"Material",
            "pbrMetallicRoughness":{
                "baseColorFactor":[
                    0.800000011920929,
                    0.800000011920929,
                    0.800000011920929,
                    1
                ],
                "metallicFactor":0,
                "roughnessFactor":0.5
            }
        }
    ],
    "meshes":[
        {
            "name":"Cube",
            "primitives":[
                {
                    "attributes":{
                        "POSITION":0,
                        "NORMAL":1,
                        "TEXCOORD_0":2
                    },
                    "indices":3,
                    "material":0
                }
            ]
        }
    ],
    "accessors":[
        {
            "bufferView":0,
            "componentType":5126,
            "count":24,
            "max":[
                1,
                1,
                1
            ],
            "min":[
                -1,
                -1,
                -1
            ],
            "type":"VEC3"
        },
        {
            "bufferView":1,
            "componentType":5126,
            "count":24,
            "type":"VEC3"
        },
        {
            "bufferView":2,
            "componentType":5126,
            "count":24,
            "type":"VEC2"
        },
        {
            "bufferView":3,
            "componentType":5123,
            "count":36,
            "type":"SCALAR"
        }
    ],
    "bufferViews":[
        {
            "buffer":0,
            "byteLength":288,
            "byteOffset":0,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":288,
            "byteOffset":288,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":192,
            "byteOffset":576,
            "target":34962
        },
        {
            "buffer":0,
            "byteLength":72,
            "byteOffset":768,
            "target":34963
        }
    ],
    "buffers":[
        {
            "byteLength":840,
            "uri":"data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAQAOABQAAQAUAAcACgAGABMACgATABcAFQASAAwAFQAMAA8AEAADAAkAEAAJABYABQACAAgABQAIAAsAEQANAAAAEQAAAAQA"
        }
    ]
}

The mesh itself is a simple cube (the first object Blender gives you when you create a new project), which should have 8 vertices, one for each corner of the cube, right?

I would like to draw your attention to the first buffer view and the first accessor, they refer to the position values (the vertices). The accessor says there are 24 elements, the component type is 5126, which stands for float 32bit, i.e., 4 bytes. Given the the data type is VEC3, there should be 12 bytes (3 * 4) per element right? This means that there should be 8 * 12 = 96 bytes in the buffer view. Then why does the buffer view have 288 = 3 * 96 bytes in it, and why, when I print the data in the buffer view, do I get triple the same output:

1.000000, 1.000000, -1.000000

1.000000, 1.000000, -1.000000

1.000000, 1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, -1.000000, -1.000000

1.000000, 1.000000, 1.000000

1.000000, 1.000000, 1.000000

1.000000, 1.000000, 1.000000

1.000000, -1.000000, 1.000000

1.000000, -1.000000, 1.000000

1.000000, -1.000000, 1.000000

-1.000000, 1.000000, -1.000000

-1.000000, 1.000000, -1.000000

-1.000000, 1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, -1.000000, -1.000000

-1.000000, 1.000000, 1.000000

-1.000000, 1.000000, 1.000000

-1.000000, 1.000000, 1.000000

-1.000000, -1.000000, 1.000000

-1.000000, -1.000000, 1.000000

-1.000000, -1.000000, 1.000000

Notice how there are always three vectors that are the same, and notice how there are indeed 24 vectors. The following is a .obj file which is exported from the exact same blender mesh (i.e., no operations were performed during both exports):

# Blender v3.6.0 OBJ File: ''
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6

There should indeed be 8 vertices, which is always displayed inside blender with the statistics option enabled.

The code (C) used to print the vectors is the following:

vec3* positions = bin + position_view->byte_offset;

for (int i = 0; i < position_accessor->count; i++) {
    printf("%f, %f, %f\n", positions[i][0], positions[i][1], positions[i][2]);
    printf("\n");
}

where bin is a void* containing the entire contents of the buffer, vec3 is a cglm type, it is actually a float[3], position_view->byte_offset is 0 and position_accessor->count 24 as in the .gltf file above.

My intuition says that the "count":24 property in the first accessor should be 8, and that the buffer view should indeed have a length of 96, as such the other accessors and buffers are also wrong as they are the normals and texture coordinates (the indices seem to be correct).

What puzzles me the most is that if I upload the .gltf file an onliner gltf viewer, the mesh is in fact rendered correctly, for example on this website https://gltf-viewer.donmccurdy.com/ If the file is correct, then why is each vertex tripled? Maybe I am interpreting the positions array (vec3*, i.e., 'float[3]*') wrong?

Thanks.


Solution

  • A cube with hard edges cannot have only 8 vertices in a GPU-ready vertex stream – which is what the glTF format provides. Each vertex stores a normal vector, each face has different normals, and so you need 6 * 4 = 24 vertices. If you disable vertex normals (and perhaps also UVs) in Blender's export options, you will likely see 8 vertices as you'd expect.

    This response from the Blender Stack Exchange may also be helpful — https://blender.stackexchange.com/a/167383/43930.