163 lines
4.6 KiB
JavaScript
163 lines
4.6 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;
|
|
}
|
|
|
|
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 };
|