function jsonChunk(buffer, offset, length) { const decoder = new TextDecoder(); const array = new Uint8Array(buffer); const object = JSON.parse(decoder.decode(array.subarray(offset, offset + length))); //console.log(object); return object; } function parseGltfChunks(buffer) { const view = new DataView(buffer); const magic = view.getUint32(0, true); const version = view.getUint32(4, true); const length = view.getUint32(8, true); console.assert(magic === 0x46546C67); console.assert(version === 2); const gltf = {}; var offset = 12; while ((length - offset) > 0) { const chunkLength = view.getUint32(offset + 0, true); const chunkType = view.getUint32(offset + 4, true); console.log("chunkLength", chunkLength); console.log("chunkType", chunkType); offset += 8; console.assert(chunkType === 0x4E4F534A || chunkType === 0x004E4942); if (chunkType === 0x4E4F534A) { const object = jsonChunk(buffer, offset, chunkLength); console.assert(!("json" in gltf)); gltf.json = object; } if (chunkType === 0x004E4942) { console.assert(!("bin" in gltf)); gltf.bin = {buffer: buffer, offset: offset, length: chunkLength}; } offset += chunkLength; } console.assert(offset == length); return gltf; } function componentCount(componentType) { switch (componentType) { case "SCALAR": return 1; case "VEC2": return 2; case "VEC3": return 3; case "VEC4": return 4; default: console.assert(false, componentType); break; } } function typeStride(type) { switch (type) { case 5120: // signed byte return 1; case 5121: // unsigned byte return 1; case 5122: // signed short return 2; case 5123: // unsigned short return 2; case 5125: // unsigned int return 4; case 5126: // float return 4; default: console.assert(false, type); break; } } function attributeStride(componentType, type) { const t = typeStride(componentType); const c = componentCount(type); return c * t; } function vertexFormat(componentType, type) { switch (componentType) { case 5120: // signed byte if (type === "SCALAR") return "sint8"; else if (type === "VEC2") return "sint8x2"; else if (type === "VEC4") return "sint8x4"; else console.assert(false, [componentType, type]); case 5121: // unsigned byte if (type === "SCALAR") return "uint8"; else if (type === "VEC2") return "uint8x2"; else if (type === "VEC4") return "uint8x4"; else console.assert(false, [componentType, type]); case 5122: // signed short if (type === "SCALAR") return "sint16"; else if (type === "VEC2") return "sint16x2"; else if (type === "VEC4") return "sint16x4"; else console.assert(false, [componentType, type]); case 5123: // unsigned short if (type === "SCALAR") return "uint16"; else if (type === "VEC2") return "uint16x2"; else if (type === "VEC4") return "uint16x4"; else console.assert(false, [componentType, type]); case 5125: // unsigned int if (type === "SCALAR") return "uint32"; else if (type === "VEC2") return "uint32x2"; else if (type === "VEC3") return "uint32x3"; else if (type === "VEC4") return "uint32x4"; else console.assert(false, [componentType, type]); case 5126: // float if (type === "SCALAR") return "float32"; else if (type === "VEC2") return "float32x2"; else if (type === "VEC3") return "float32x3"; else if (type === "VEC4") return "float32x4"; else console.assert(false, [componentType, type]); default: console.assert(false, [componentType, type]); break; } } function primitiveVertexBufferLayouts(gltf, primitive) { const accessors = [ gltf.json.accessors[primitive.attributes["POSITION"]], gltf.json.accessors[primitive.attributes["NORMAL"]], gltf.json.accessors[primitive.attributes["TEXCOORD_0"]], ]; const layouts = []; for (let i = 0; i < accessors.length; i++) { const componentType = accessors[i].componentType; const type = accessors[i].type; const bufferView = gltf.json.bufferViews[accessors[i].bufferView]; const arrayStride = "byteStride" in bufferView ? bufferView.byteStride : attributeStride(componentType, type); const offset = "byteOffset" in accessors[i] ? accessors[i].byteOffset : 0; const layout = { arrayStride: arrayStride, attributes: [{ format: vertexFormat(componentType, type), offset: offset, shaderLocation: i, }], stepMode: "vertex", }; layouts.push(layout); } return layouts; } export { parseGltfChunks, primitiveVertexBufferLayouts };