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; } async function splitGltf(jsonPath, binPath) { const jsonResponse = await fetch(jsonPath); const jsonBuffer = await jsonResponse.arrayBuffer(); const json = jsonChunk(jsonBuffer, 0, jsonBuffer.byteLength); const binResponse = await fetch(binPath); const binBuffer = await binResponse.arrayBuffer(); return { json: json, bin: [{ buffer: binBuffer, offset: 0, length: binBuffer.byteLength }], }; } function transformMatrix() { } function buildTransfomMatrices(json) { } 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 = { bin: [], }; 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) { gltf.bin.push({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 primitiveAccessors(primitive) { return [ primitive.attributes["POSITION"], primitive.attributes["NORMAL"], primitive.attributes["TEXCOORD_0"], primitive.attributes["TANGENT"], ]; } function vertexBufferLayouts(gltf, accessors) { const layouts = []; for (let i = 0; i < accessors.length; i++) { const accessor = gltf.json.accessors[accessors[i]]; const componentType = accessor.componentType; const type = accessor.type; const bufferView = gltf.json.bufferViews[accessor.bufferView]; const arrayStride = "byteStride" in bufferView ? bufferView.byteStride : attributeStride(componentType, type); const offset = "byteOffset" in accessor ? accessor.byteOffset : 0; const layout = { arrayStride: arrayStride, attributes: [{ format: vertexFormat(componentType, type), offset: offset, shaderLocation: i, }], stepMode: "vertex", }; layouts.push(layout); } return layouts; } export { parseGltfChunks, vertexBufferLayouts, primitiveAccessors, splitGltf };