18 lines
1.3 KiB
JavaScript
18 lines
1.3 KiB
JavaScript
/** Minimal glTF 2.0 container I/O, independent of either rendering backend. */
|
|
export function parseGLB(bytes){
|
|
if(!(bytes instanceof Uint8Array)||bytes.byteLength<28)throw Error('Invalid GLB length');
|
|
const v=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength);
|
|
if(v.getUint32(0,true)!==0x46546c67||v.getUint32(4,true)!==2)throw Error('Expected glTF 2.0');
|
|
if(v.getUint32(8,true)!==bytes.byteLength)throw Error('GLB length mismatch');
|
|
let gltf=null,binary=null,off=12;
|
|
while(off<bytes.length){if(off+8>bytes.length)throw Error('Invalid GLB chunk');const size=v.getUint32(off,true),type=v.getUint32(off+4,true);if(size%4||off+8+size>bytes.length)throw Error('Invalid GLB chunk bounds');
|
|
const part=bytes.subarray(off+8,off+8+size);if(type===0x4e4f534a)gltf=JSON.parse(new TextDecoder().decode(part));else if(type===0x004e4942)binary=part;off+=8+size;}
|
|
if(!gltf||!binary)throw Error('Missing GLB data');return {gltf,binary};
|
|
}
|
|
export function encodeGLB(gltf,binary){
|
|
const text=new TextEncoder().encode(JSON.stringify(gltf)),jl=(text.length+3)&~3,bl=(binary.length+3)&~3;
|
|
const out=new Uint8Array(28+jl+bl),v=new DataView(out.buffer);
|
|
[0x46546c67,2,out.length,jl,0x4e4f534a].forEach((n,i)=>v.setUint32(4*i,n,true));out.fill(32,20,20+jl);out.set(text,20);
|
|
v.setUint32(20+jl,bl,true);v.setUint32(24+jl,0x004e4942,true);out.set(binary,28+jl);return out;
|
|
}
|