parseGlb.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import addPipelineExtras from './addPipelineExtras.js'
  2. import removeExtensionsUsed from './removeExtensionsUsed.js'
  3. import defaultValue from '../../Core/defaultValue.js'
  4. import defined from '../../Core/defined.js'
  5. import getMagic from '../../Core/getMagic.js'
  6. import getStringFromTypedArray from '../../Core/getStringFromTypedArray.js'
  7. import RuntimeError from '../../Core/RuntimeError.js'
  8. var sizeOfUint32 = 4;
  9. /**
  10. * Convert a binary glTF to glTF.
  11. *
  12. * The returned glTF has pipeline extras included. The embedded binary data is stored in gltf.buffers[0].extras._pipeline.source.
  13. *
  14. * @param {Buffer} glb The glb data to parse.
  15. * @returns {Object} A javascript object containing a glTF asset with pipeline extras included.
  16. *
  17. * @private
  18. */
  19. function parseGlb(glb) {
  20. // Check that the magic string is present
  21. var magic = getMagic(glb);
  22. if (magic !== 'glTF') {
  23. throw new RuntimeError('File is not valid binary glTF');
  24. }
  25. var header = readHeader(glb, 0, 5);
  26. var version = header[1];
  27. if (version !== 1 && version !== 2) {
  28. throw new RuntimeError('Binary glTF version is not 1 or 2');
  29. }
  30. if (version === 1) {
  31. return parseGlbVersion1(glb, header);
  32. }
  33. return parseGlbVersion2(glb, header);
  34. }
  35. function readHeader(glb, byteOffset, count) {
  36. var dataView = new DataView(glb.buffer);
  37. var header = new Array(count);
  38. for (var i = 0; i < count; ++i) {
  39. header[i] = dataView.getUint32(glb.byteOffset + byteOffset + i * sizeOfUint32, true);
  40. }
  41. return header;
  42. }
  43. function parseGlbVersion1(glb, header) {
  44. var length = header[2];
  45. var contentLength = header[3];
  46. var contentFormat = header[4];
  47. // Check that the content format is 0, indicating that it is JSON
  48. if (contentFormat !== 0) {
  49. throw new RuntimeError('Binary glTF scene format is not JSON');
  50. }
  51. var jsonStart = 20;
  52. var binaryStart = jsonStart + contentLength;
  53. var contentString = getStringFromTypedArray(glb, jsonStart, contentLength);
  54. var gltf = JSON.parse(contentString);
  55. addPipelineExtras(gltf);
  56. var binaryBuffer = glb.subarray(binaryStart, length);
  57. var buffers = gltf.buffers;
  58. if (defined(buffers) && Object.keys(buffers).length > 0) {
  59. // In some older models, the binary glTF buffer is named KHR_binary_glTF
  60. var binaryGltfBuffer = defaultValue(buffers.binary_glTF, buffers.KHR_binary_glTF);
  61. if (defined(binaryGltfBuffer)) {
  62. binaryGltfBuffer.extras._pipeline.source = binaryBuffer;
  63. }
  64. }
  65. // Remove the KHR_binary_glTF extension
  66. removeExtensionsUsed(gltf, 'KHR_binary_glTF');
  67. return gltf;
  68. }
  69. function parseGlbVersion2(glb, header) {
  70. var length = header[2];
  71. var byteOffset = 12;
  72. var gltf;
  73. var binaryBuffer;
  74. while (byteOffset < length) {
  75. var chunkHeader = readHeader(glb, byteOffset, 2);
  76. var chunkLength = chunkHeader[0];
  77. var chunkType = chunkHeader[1];
  78. byteOffset += 8;
  79. var chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);
  80. byteOffset += chunkLength;
  81. // Load JSON chunk
  82. if (chunkType === 0x4E4F534A) {
  83. var jsonString = getStringFromTypedArray(chunkBuffer);
  84. gltf = JSON.parse(jsonString);
  85. addPipelineExtras(gltf);
  86. }
  87. // Load Binary chunk
  88. else if (chunkType === 0x004E4942) {
  89. binaryBuffer = chunkBuffer;
  90. }
  91. }
  92. if (defined(gltf) && defined(binaryBuffer)) {
  93. var buffers = gltf.buffers;
  94. if (defined(buffers) && buffers.length > 0) {
  95. var buffer = buffers[0];
  96. buffer.extras._pipeline.source = binaryBuffer;
  97. }
  98. }
  99. return gltf;
  100. }
  101. export default parseGlb;