loaders.gl
Version:
Framework-independent loaders for 3D graphics formats
230 lines (181 loc) • 8.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _unpackGlbBuffers = _interopRequireDefault(require("./unpack-glb-buffers"));
var _unpackBinaryJson = _interopRequireDefault(require("./unpack-binary-json"));
var _arrayUtils = require("../common/loader-utils/array-utils");
var _textDecoder = _interopRequireDefault(require("../common/loader-utils/text-decoder"));
var _assert = _interopRequireDefault(require("../common/loader-utils/assert"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
// glTF CONSTANTS
var MAGIC_glTF = 0x676c5446; // glTF in Big-Endian ASCII
var GLB_FILE_HEADER_SIZE = 12;
var GLB_CHUNK_HEADER_SIZE = 8;
var GLB_CHUNK_TYPE_JSON = 0x4E4F534A;
var GLB_CHUNK_TYPE_BIN = 0x004E4942;
var LE = true; // Binary GLTF is little endian.
var BE = false; // Magic needs to be written as BE
// glTF ACCESSOR CONSTANTS
/*
const TYPE_COMPONENTS = {
SCALAR: 1,
VEC2: 2,
VEC3: 3,
VEC4: 4,
MAT2: 4,
MAT3: 9,
MAT4: 16
};
const COMPONENT_TYPE_BYTE_SIZE = {
5120: 1,
5121: 1,
5122: 2,
5123: 2,
5125: 4,
5126: 4
};
const COMPONENT_TYPE_ARRAY = {
5120: Int8Array,
5121: Uint8Array,
5122: Int16Array,
5123: Uint16Array,
5125: Uint32Array,
5126: Float32Array
};
*/
function getMagicString(dataView) {
return "".concat(String.fromCharCode(dataView.getUint8(0))).concat(String.fromCharCode(dataView.getUint8(1))).concat(String.fromCharCode(dataView.getUint8(2))).concat(String.fromCharCode(dataView.getUint8(3)));
} // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#glb-file-format-specification
var GLBParser =
/*#__PURE__*/
function () {
function GLBParser(glbArrayBuffer) {
_classCallCheck(this, GLBParser);
this.glbArrayBuffer = glbArrayBuffer;
} // Only returns application JSON
_createClass(GLBParser, [{
key: "parse",
value: function parse() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this$_parseBinary = this._parseBinary(this.glbArrayBuffer, options),
json = _this$_parseBinary.json,
binaryByteOffset = _this$_parseBinary.binaryByteOffset;
var unpackedBuffers = (0, _unpackGlbBuffers.default)(this.glbArrayBuffer, json, binaryByteOffset);
var unpackedJson = (0, _unpackBinaryJson.default)(json, unpackedBuffers);
return this._getApplicationJSON(unpackedJson, options);
} // Returns both application JSON and glTF JSON, separated
}, {
key: "parseWithMetadata",
value: function parseWithMetadata() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this$_parseBinary2 = this._parseBinary(this.glbArrayBuffer, options),
json = _this$_parseBinary2.json,
binaryByteOffset = _this$_parseBinary2.binaryByteOffset;
var unpackedBuffers = (0, _unpackGlbBuffers.default)(this.glbArrayBuffer, json, binaryByteOffset);
var unpackedJson = (0, _unpackBinaryJson.default)(json, unpackedBuffers);
return unpackedJson;
} // PRIVATE
// Get JSON from json key
}, {
key: "_getApplicationJSON",
value: function _getApplicationJSON(json, options) {
var jsonKey = options.jsonKey || 'json'; // Create glTF metadata object, with deleted application json key
var glTF = Object.assign({}, json);
delete glTF[jsonKey];
return {
json: json[jsonKey],
glTF: glTF
};
}
}, {
key: "_parseBinary",
value: function _parseBinary() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _options$magic = options.magic,
magic = _options$magic === void 0 ? MAGIC_glTF : _options$magic; // GLB Header
var dataView = new DataView(this.glbArrayBuffer);
var magic1 = dataView.getUint32(0, BE); // Magic number (the ASCII string 'glTF').
var version = dataView.getUint32(4, LE); // Version 2 of binary glTF container format
var fileLength = dataView.getUint32(8, LE); // Total byte length of generated file
var valid = magic1 === MAGIC_glTF || magic1 === magic;
if (!valid) {
console.warn("Invalid GLB magic string ".concat(getMagicString(dataView))); // eslint-disable-line
}
(0, _assert.default)(version === 2, "Invalid GLB version ".concat(version, ". Only .glb v2 supported"));
(0, _assert.default)(fileLength > 20); // Write the JSON chunk
var jsonChunkLength = dataView.getUint32(12, LE); // Byte length of json chunk
var jsonChunkFormat = dataView.getUint32(16, LE); // Chunk format as uint32
valid = jsonChunkFormat === GLB_CHUNK_TYPE_JSON || jsonChunkFormat === 0; // Back compat
(0, _assert.default)(valid, "JSON chunk format ".concat(jsonChunkFormat)); // Create a "view" of the binary encoded JSON data
var jsonChunkOffset = GLB_FILE_HEADER_SIZE + GLB_CHUNK_HEADER_SIZE; // First headers: 20 bytes
var jsonChunk = new Uint8Array(this.glbArrayBuffer, jsonChunkOffset, jsonChunkLength); // Decode the JSON binary array into clear text
var textDecoder = new _textDecoder.default('utf8');
var jsonText = textDecoder.decode(jsonChunk); // Parse the JSON text into a JavaScript data structure
var json = JSON.parse(jsonText); // TODO - BIN chunk can be optional
var binaryChunkStart = jsonChunkOffset + (0, _arrayUtils.padTo4Bytes)(jsonChunkLength);
var binaryByteOffset = binaryChunkStart + GLB_CHUNK_HEADER_SIZE;
var binChunkFormat = dataView.getUint32(binaryChunkStart + 4, LE); // Chunk format as uint32
valid = binChunkFormat === GLB_CHUNK_TYPE_BIN || binChunkFormat === 1; // Back compat
(0, _assert.default)(valid, "BIN chunk format ".concat(binChunkFormat));
return {
arrayBuffer: this.glbArrayBuffer,
binaryByteOffset: binaryByteOffset,
json: json
};
}
/*
unpackBinaryObjects() {
const unpackedBinaryObjects = {
images: [],
accessors: []
};
const images = this.json.images || [];
for (const glTFImage of images) {
unpackedBinaryObjects.images.push(this.unpackImage(glTFImage));
}
const accessors = this.json.accessors || [];
for (const glTFAccessor of accessors) {
unpackedBinaryObjects.accessors.push(this.unpackAccessor(glTFAccessor));
}
return unpackedBinaryObjects;
}
unpackImage(glTFImage) {
/* global window, Blob, Image *
const arrayBufferView = this.unpackBufferView(glTFImage.bufferView);
const mimeType = glTFImage.mimeType || 'image/jpeg';
const blob = new Blob([arrayBufferView], {type: mimeType});
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL(blob);
const img = new Image();
img.src = imageUrl;
return img;
}
unpackAccessor(glTFAccessor) {
// Decode the glTF accessor format
const ArrayType = COMPONENT_TYPE_ARRAY[glTFAccessor.componentType];
const components = TYPE_COMPONENTS[glTFAccessor.type];
const bytesPerComponent = COMPONENT_TYPE_BYTE_SIZE[glTFAccessor.componentType];
const length = glTFAccessor.count * components;
const byteLength = glTFAccessor.count * components * bytesPerComponent;
// Get the boundaries of the binary sub-chunk for this bufferView
const glTFBufferView = this.json.bufferViews[glTFAccessor.bufferView];
assert(byteLength >= 0 && byteLength <= glTFBufferView.byteLength);
const byteOffset = glTFBufferView.byteOffset + this.binaryByteOffset;
return new ArrayType(this.arrayBuffer, byteOffset, length);
}
// Create a new typed array as a view into the binary chunk
unpackBufferView(glTFBufferView) {
const byteOffset = glTFBufferView.byteOffset + this.binaryByteOffset;
return new Uint8Array(byteOffset, glTFBufferView.byteLength);
}
*/
}]);
return GLBParser;
}();
exports.default = GLBParser;
//# sourceMappingURL=glb-parser.js.map