UNPKG

threepipe

Version:

A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.

73 lines 3.08 kB
/** * Returns a buffer aligned to 4-byte boundary. * https://github.com/mrdoob/three.js/blob/4dbd0065f2ec29b89c250d8582f61e9f4792e077/examples/jsm/exporters/GLTFExporter.js#L381 * @param arrayBuffer Buffer to pad * @param paddingByte (Optional) * @returns The same buffer if it's already aligned to 4-byte boundary or a new buffer */ function getPaddedArrayBuffer(arrayBuffer, paddingByte = 0) { const paddedLength = getPaddedBufferSize(arrayBuffer.byteLength); if (paddedLength !== arrayBuffer.byteLength) { const array = new Uint8Array(paddedLength); array.set(new Uint8Array(arrayBuffer)); if (paddingByte !== 0) { for (let i = arrayBuffer.byteLength; i < paddedLength; i++) { array[i] = paddingByte; } } return array.buffer; } return arrayBuffer.buffer; } /** * Get the required size + padding for a buffer, rounded to the next 4-byte boundary. * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment * * @param bufferSize The size the original buffer. * @returns new buffer size with required padding. * */ function getPaddedBufferSize(bufferSize) { return Math.ceil(bufferSize / 4) * 4; } // GLB constants // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification const GLB_HEADER_BYTES = 12; const GLB_HEADER_MAGIC = 0x46546C67; const GLB_VERSION = 2; const GLB_CHUNK_PREFIX_BYTES = 8; const GLB_CHUNK_TYPE_JSON = 0x4E4F534A; const GLB_CHUNK_TYPE_BIN = 0x004E4942; // https://github.com/mrdoob/three.js/blob/4dbd0065f2ec29b89c250d8582f61e9f4792e077/examples/jsm/exporters/GLTFExporter.js#L558 export function makeGLBFile(buffers, json) { // Binary chunk. const binaryChunk = getPaddedArrayBuffer(buffers); const binaryChunkPrefix = new DataView(new ArrayBuffer(GLB_CHUNK_PREFIX_BYTES)); binaryChunkPrefix.setUint32(0, binaryChunk.byteLength, true); binaryChunkPrefix.setUint32(4, GLB_CHUNK_TYPE_BIN, true); // JSON chunk. const buffer1 = new TextEncoder().encode(JSON.stringify(json || {})); const jsonChunk = getPaddedArrayBuffer(buffer1, 0x20); const jsonChunkPrefix = new DataView(new ArrayBuffer(GLB_CHUNK_PREFIX_BYTES)); jsonChunkPrefix.setUint32(0, jsonChunk.byteLength, true); jsonChunkPrefix.setUint32(4, GLB_CHUNK_TYPE_JSON, true); // GLB header. const header = new ArrayBuffer(GLB_HEADER_BYTES); const headerView = new DataView(header); headerView.setUint32(0, GLB_HEADER_MAGIC, true); headerView.setUint32(4, GLB_VERSION, true); const totalByteLength = GLB_HEADER_BYTES + jsonChunkPrefix.byteLength + jsonChunk.byteLength + binaryChunkPrefix.byteLength + binaryChunk.byteLength; headerView.setUint32(8, totalByteLength, true); const glbBlob = new Blob([ header, jsonChunkPrefix, jsonChunk, binaryChunkPrefix, binaryChunk, ], { type: 'model/gltf+binary' }); glbBlob.ext = 'glb'; return glbBlob; } //# sourceMappingURL=gltf.js.map