Let us assume that we have a cube, such as the one below generated by Blender and exported with GLTF embedded option.
{
"asset" : {
"generator" : "Khronos glTF Blender I/O v3.3.27",
"version" : "2.0"
},
"scene" : 0,
"scenes" : [
{
"name" : "Scene",
"nodes" : [
0
]
}
],
"nodes" : [
{
"mesh" : 0,
"name" : "Cube"
}
],
"meshes" : [
{
"name" : "Cube",
"primitives" : [
{
"attributes" : {
"POSITION" : 0
},
"indices" : 1
}
]
}
],
"accessors" : [
{
"bufferView" : 0,
"componentType" : 5126,
"count" : 8,
"max" : [
1,
1,
1
],
"min" : [
-1,
-1,
-1
],
"type" : "VEC3"
},
{
"bufferView" : 1,
"componentType" : 5123,
"count" : 36,
"type" : "SCALAR"
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 96,
"byteOffset" : 0,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 72,
"byteOffset" : 96,
"target" : 34963
}
],
"buffers" : [
{
"byteLength" : 168,
"uri" : "data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AAABAAMAAAADAAIAAgADAAcAAgAHAAYABgAHAAUABgAFAAQABAAFAAEABAABAAAAAgAGAAQAAgAEAAAABwADAAEABwABAAUA"
}
]
}
The vertices are only 8
V[0] = [0.0,-1.0,0.0]
V[1] = [0.0, 1.0,0.0]
V[2] = [0.0, 1.0,1.0]
…
V[8] = [1.0,1.0,1.0]
Indices point to the vertices
(BufferView 1 contains the indices of the points of the 12 triangles so it is 36 indices)
Triangle 1
indice[0] = 0
indice[1] = 1
indice[2] = 2
Triangle 2
indice[3] = 2
indice[4] = 3
indice[5] = 0
…
Triangle 12
indice[33] = 6
indice[34] = 7
indice[35] = 5
Let’s go high now.
Imagine now that we have 100000 vertices , and a complicated mesh out of these 100 000
How an index can point out to vertex 70 000 since an index is stored in Uint16 format ? Simply it will restart from zero after 65535 and this will cause the bug, i.e.
Command: Get the indice 50 that points to vertex 70000, i.e.
indice[50] = 70000
The CPU says: Hey you store it in Uint16, you can not do that, I will clip it for you so that it can fit to Uint16, so I give you back:
indice[50] = 70000 - 65535 = 4465
which will cause the mesh to be scrambled for the triangles that involve vertices that are in position 65536 and afterwards.
In conclusion:
Your Thee.js GLTF importer should recognize if a single buffer contains more than 65536 vertices. For the cube case the number 8 is below the Uint16 limit (namely below 65535) and it is ok to use the Uint16 format. If the number of vertices were more than 65536 points, then the Uint32 should be used instead.
if (MaxNumberOfVerticesAcrossBuffers < 65535){
const WEBGL_COMPONENT_TYPES = {
5120: Int8Array,
5121: Uint8Array,
5122: Int16Array,
5123: Uint16Array,
5125: Uint32Array,
5126: Float32Array
};
} else {
const WEBGL_COMPONENT_TYPES = {
5120: Int8Array,
5121: Uint8Array,
5122: Int16Array,
5123: Uint32Array,
5125: Uint32Array,
5126: Float32Array
};
}