webgpu-app/gltf.js

191 lines
5.1 KiB
JavaScript

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 };