All files / Sources/IO/Geometry/GLTFImporter Decoder.js

0% Statements 0/36
0% Branches 0/14
0% Functions 0/6
0% Lines 0/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                                                                                                                                                             
import BinaryHelper from 'vtk.js/Sources/IO/Core/BinaryHelper';
import {
  BINARY_CHUNK_TYPES,
  BINARY_CHUNK_HEADER_INTS,
  BINARY_HEADER_INTS,
  BINARY_HEADER_LENGTH,
  BINARY_HEADER_MAGIC,
} from 'vtk.js/Sources/IO/Geometry/GLTFImporter/Constants';
 
function getChunkInfo(headerStart, data) {
  const header = new Uint32Array(data, headerStart, BINARY_CHUNK_HEADER_INTS);
  const chunkStart = headerStart + BINARY_CHUNK_HEADER_INTS * 4;
  const chunkLength = header[0];
  const chunkType = header[1];
  return { start: chunkStart, length: chunkLength, type: chunkType };
}
 
function getAllChunkInfos(data) {
  const infos = [];
  let chunkStart = BINARY_HEADER_INTS * 4;
  while (chunkStart < data.byteLength) {
    const chunkInfo = getChunkInfo(chunkStart, data);
    infos.push(chunkInfo);
    chunkStart += chunkInfo.length + BINARY_CHUNK_HEADER_INTS * 4;
  }
  return infos;
}
 
function getJsonFromChunk(chunkInfo, data) {
  const chunkLength = chunkInfo.length;
  const jsonStart = (BINARY_HEADER_INTS + BINARY_CHUNK_HEADER_INTS) * 4;
  const jsonSlice = new Uint8Array(data, jsonStart, chunkLength);
  const stringBuffer = BinaryHelper.arrayBufferToString(jsonSlice);
  return JSON.parse(stringBuffer);
}
 
function getBufferFromChunk(chunkInfo, data) {
  return data.slice(chunkInfo.start, chunkInfo.start + chunkInfo.length);
}
 
function parseGLB(data) {
  let json;
  const buffers = [];
 
  const headerView = new DataView(data, 0, BINARY_HEADER_LENGTH);
 
  const header = {
    magic: BinaryHelper.arrayBufferToString(new Uint8Array(data, 0, 4)),
    version: headerView.getUint32(4, true),
    length: headerView.getUint32(8, true),
  };
 
  if (header.magic !== BINARY_HEADER_MAGIC) {
    throw new Error('Unsupported glTF-Binary header.');
  } else if (header.version < 2.0) {
    throw new Error('Unsupported legacy binary file detected.');
  }
 
  const chunkInfos = getAllChunkInfos(data);
 
  chunkInfos.forEach((chunkInfo) => {
    if (chunkInfo.type === BINARY_CHUNK_TYPES.JSON && !json) {
      json = getJsonFromChunk(chunkInfo, data);
    } else if (chunkInfo.type === BINARY_CHUNK_TYPES.BIN) {
      buffers.push(getBufferFromChunk(chunkInfo, data));
    }
  });
 
  if (!json) {
    throw new Error('glTF-Binary: JSON content not found.');
  }
  if (!buffers) {
    throw new Error('glTF-Binary: Binary chunk not found.');
  }
  return { json, buffers };
}
 
export default parseGLB;