UNPKG

gltf-pipeline

Version:
119 lines (103 loc) 3.8 kB
'use strict'; const Cesium = require('cesium'); const addPipelineExtras = require('./addPipelineExtras'); const removeExtensionsUsed = require('./removeExtensionsUsed'); const defaultValue = Cesium.defaultValue; const defined = Cesium.defined; const getMagic = Cesium.getMagic; const getStringFromTypedArray = Cesium.getStringFromTypedArray; const RuntimeError = Cesium.RuntimeError; const sizeOfUint32 = 4; module.exports = parseGlb; /** * Convert a binary glTF to glTF. * * The returned glTF has pipeline extras included. The embedded binary data is stored in gltf.buffers[0].extras._pipeline.source. * * @param {Buffer} glb The glb data to parse. * @returns {Object} A javascript object containing a glTF asset with pipeline extras included. * * @private */ function parseGlb(glb) { // Check that the magic string is present const magic = getMagic(glb); if (magic !== 'glTF') { throw new RuntimeError('File is not valid binary glTF'); } const header = readHeader(glb, 0, 5); const version = header[1]; if (version !== 1 && version !== 2) { throw new RuntimeError('Binary glTF version is not 1 or 2'); } if (version === 1) { return parseGlbVersion1(glb, header); } return parseGlbVersion2(glb, header); } function readHeader(glb, byteOffset, count) { const dataView = new DataView(glb.buffer); const header = new Array(count); for (let i = 0; i < count; ++i) { header[i] = dataView.getUint32(glb.byteOffset + byteOffset + i * sizeOfUint32, true); } return header; } function parseGlbVersion1(glb, header) { const length = header[2]; const contentLength = header[3]; const contentFormat = header[4]; // Check that the content format is 0, indicating that it is JSON if (contentFormat !== 0) { throw new RuntimeError('Binary glTF scene format is not JSON'); } const jsonStart = 20; const binaryStart = jsonStart + contentLength; const contentString = getStringFromTypedArray(glb, jsonStart, contentLength); const gltf = JSON.parse(contentString); addPipelineExtras(gltf); const binaryBuffer = glb.subarray(binaryStart, length); const buffers = gltf.buffers; if (defined(buffers) && Object.keys(buffers).length > 0) { // In some older models, the binary glTF buffer is named KHR_binary_glTF const binaryGltfBuffer = defaultValue(buffers.binary_glTF, buffers.KHR_binary_glTF); if (defined(binaryGltfBuffer)) { binaryGltfBuffer.extras._pipeline.source = binaryBuffer; } } // Remove the KHR_binary_glTF extension removeExtensionsUsed(gltf, 'KHR_binary_glTF'); return gltf; } function parseGlbVersion2(glb, header) { const length = header[2]; let byteOffset = 12; let gltf; let binaryBuffer; while (byteOffset < length) { const chunkHeader = readHeader(glb, byteOffset, 2); const chunkLength = chunkHeader[0]; const chunkType = chunkHeader[1]; byteOffset += 8; const chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength); byteOffset += chunkLength; // Load JSON chunk if (chunkType === 0x4E4F534A) { const jsonString = getStringFromTypedArray(chunkBuffer); gltf = JSON.parse(jsonString); addPipelineExtras(gltf); } // Load Binary chunk else if (chunkType === 0x004E4942) { binaryBuffer = chunkBuffer; } } if (defined(gltf) && defined(binaryBuffer)) { const buffers = gltf.buffers; if (defined(buffers) && buffers.length > 0) { const buffer = buffers[0]; buffer.extras._pipeline.source = binaryBuffer; } } return gltf; }