UNPKG

loaders.gl

Version:

Framework-independent loaders for 3D graphics formats

325 lines (266 loc) 12.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; 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; } // DRACO decompressor var draco3d = require('draco3d'); // const assert = require('assert'); var GEOMETRY_TYPE = { TRIANGULAR_MESH: 0, POINT_CLOUD: 1 }; // Native Draco attribute names to GLTF attribute names. var ATTRIBUTE_MAP = { position: 'POSITION', normal: 'NORMAL', color: 'COLOR_0', uv: 'TEXCOORD_0' }; var DRACODecoder = /*#__PURE__*/ function () { function DRACODecoder() { _classCallCheck(this, DRACODecoder); this.decoderModule = draco3d.createDecoderModule({}); } // isVersionSupported(version, callback) { // DRACOLoader.getDecoderModule() // .then(function (module) { // callback(module.decoder.isVersionSupported(version)); // }); // } // getAttributeOptions(attributeName) { // if (typeof this.attributeOptions[attributeName] === 'undefined') // this.attributeOptions[attributeName] = {}; // return this.attributeOptions[attributeName]; // } _createClass(DRACODecoder, [{ key: "destroy", value: function destroy() {// this.decoderModule.destroy(); } }, { key: "destroyGeometry", value: function destroyGeometry(dracoGeometry) { if (dracoGeometry) { this.decoderModule.destroy(dracoGeometry.dracoGeometry); } } // NOTE: caller must call `destroyGeometry` on the return value after using it }, { key: "decode", value: function decode(arrayBuffer) { var buffer = new this.decoderModule.DecoderBuffer(); buffer.Init(new Int8Array(arrayBuffer), arrayBuffer.byteLength); var decoder = new this.decoderModule.Decoder(); var data = {}; var dracoStatus; var dracoGeometry; try { var geometryType = decoder.GetEncodedGeometryType(buffer); switch (geometryType) { case this.decoderModule.TRIANGULAR_MESH: dracoGeometry = new this.decoderModule.Mesh(); dracoStatus = decoder.DecodeBufferToMesh(buffer, dracoGeometry); data.header = { type: GEOMETRY_TYPE.TRIANGULAR_MESH, faceCount: dracoGeometry.num_faces(), attributeCount: dracoGeometry.num_attributes(), vertexCount: dracoGeometry.num_points() }; break; case this.decoderModule.POINT_CLOUD: dracoGeometry = new this.decoderModule.PointCloud(); dracoStatus = decoder.DecodeBufferToPointCloud(buffer, dracoGeometry); data.header = { type: GEOMETRY_TYPE.POINT_CLOUD, attributeCount: dracoGeometry.num_attributes(), vertexCount: dracoGeometry.num_points() }; break; default: throw new Error('Unknown DRACO geometry type.'); } if (!dracoStatus.ok() || !dracoGeometry.ptr) { var message = "DRACO decompression failed: ".concat(dracoStatus.error_msg()); // console.error(message); if (dracoGeometry) { this.decoderModule.destroy(dracoGeometry); } throw new Error(message); } this.extractDRACOGeometry(decoder, dracoGeometry, data); } finally { this.decoderModule.destroy(decoder); this.decoderModule.destroy(buffer); } return data; } }, { key: "extractDRACOGeometry", value: function extractDRACOGeometry(decoder, dracoGeometry, geometry, geometryType) { // const numPoints = dracoGeometry.num_points(); // const numAttributes = dracoGeometry.num_attributes(); // Structure for converting to WebGL framework specific attributes later var attributes = this.getAttributes(decoder, dracoGeometry); var positionAttribute = this.getPositionAttribute(decoder, dracoGeometry); this.getPositionAttributeMetadata(positionAttribute); attributes.POSITION = positionAttribute; // For meshes, we need indices to define the faces. if (geometryType === this.decoderModule.TRIANGULAR_MESH) { attributes.indices = this.drawMode === 'TRIANGLE_STRIP' ? this.getMeshStripIndices() : this.getMeshFaceIndices(); } attributes.drawMode = this.drawMode; geometry.attributes = attributes; return geometry; } }, { key: "getPositionAttribute", value: function getPositionAttribute(decoder, dracoGeometry) { // Ensure we at least have position attribute. var positionAttributeId = decoder.GetAttributeId(dracoGeometry, this.decoderModule.POSITION); if (positionAttributeId === -1) { throw new Error('DRACO decompressor: No position attribute found.'); } var dracoAttribute = decoder.GetAttribute(dracoGeometry, positionAttributeId); var _this$getAttributeTyp = this.getAttributeTypedArray(decoder, dracoGeometry, dracoAttribute, Float32Array, 'position'), typedArray = _this$getAttributeTyp.typedArray; return typedArray; } }, { key: "getPositionAttributeMetadata", value: function getPositionAttributeMetadata(positionAttribute) { this.metadata = this.metadata || {}; this.metadata.attributes = this.metadata.attributes || {}; var posTransform = new this.decoderModule.AttributeQuantizationTransform(); if (posTransform.InitFromAttribute(positionAttribute)) { // Quantized attribute. Store the quantization parameters into the // THREE.js attribute. this.metadata.attributes.position.isQuantized = true; this.metadata.attributes.position.maxRange = posTransform.range(); this.metadata.attributes.position.numQuantizationBits = posTransform.quantization_bits(); this.metadata.attributes.position.minValues = new Float32Array(3); for (var i = 0; i < 3; ++i) { this.metadata.attributes.position.minValues[i] = posTransform.min_value(i); } } this.decoderModule.destroy(posTransform); } }, { key: "getAttributes", value: function getAttributes(decoder, dracoGeometry) { var attributes = {}; // const attributeUniqueIdMap = {}; // Add native Draco attribute type to geometry. for (var attributeName in ATTRIBUTE_MAP) { // The native attribute type is only used when no unique Id is provided. // For example, loading .drc files. // if (attributeUniqueIdMap[attributeName] === undefined) { var attributeType = this.decoderModule[attributeName]; var attributeId = decoder.GetAttributeId(dracoGeometry, attributeType); if (attributeId !== -1) { var dracoAttribute = decoder.GetAttribute(dracoGeometry, attributeId); this.getAttributeTypedArray(decoder, dracoGeometry, dracoAttribute, Float32Array, attributeName); } // } } // // Add attributes of user specified unique id. E.g. GLTF models. // for (const attributeName in attributeUniqueIdMap) { // const attributeType = attributeTypeMap[attributeName] || Float32Array; // const attributeId = attributeUniqueIdMap[attributeName]; // const attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeId); // this.getAttributeTypedArray(decoder, dracoGeometry, attribute,attributeName,attributeType); // } return attributes; } // For meshes, we need indices to define the faces. }, { key: "getMeshFaceIndices", value: function getMeshFaceIndices(decoder, dracoGeometry) { // Example on how to retrieve mesh and attributes. var numFaces = dracoGeometry.num_faces(); var numIndices = numFaces * 3; var indices = new Uint32Array(numIndices); var dracoArray = new this.decoderModule.DracoInt32Array(); for (var i = 0; i < numFaces; ++i) { decoder.GetFaceFromMesh(dracoGeometry, i, dracoArray); var index = i * 3; indices[index] = dracoArray.GetValue(0); indices[index + 1] = dracoArray.GetValue(1); indices[index + 2] = dracoArray.GetValue(2); } this.decoderModule.destroy(dracoArray); return indices; } // For meshes, we need indices to define the faces. }, { key: "getMeshStripIndices", value: function getMeshStripIndices(decoder, dracoGeometry) { var dracoArray = new this.decoderModule.DracoInt32Array(); /* const numStrips = */ decoder.GetTriangleStripsFromMesh(dracoGeometry, dracoArray); var indices = new Uint32Array(dracoArray.size()); for (var i = 0; i < dracoArray.size(); ++i) { indices[i] = dracoArray.GetValue(i); } this.decoderModule.destroy(dracoArray); return indices; } }, { key: "getAttributeTypedArray", value: function getAttributeTypedArray(decoder, dracoGeometry, dracoAttribute, attributeType, attributeName) { if (dracoAttribute.ptr === 0) { var message = "DRACO decode bad attribute ".concat(attributeName); // console.error(message); throw new Error(message); } var numComponents = dracoAttribute.num_components(); var numPoints = dracoGeometry.num_points(); var numValues = numPoints * numComponents; var dracoArray; var typedArray; switch (attributeType) { case Float32Array: dracoArray = new this.decoderModule.DracoFloat32Array(); decoder.GetAttributeFloatForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Float32Array(numValues); break; case Int8Array: dracoArray = new this.decoderModule.DracoInt8Array(); decoder.GetAttributeInt8ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Int8Array(numValues); break; case Int16Array: dracoArray = new this.decoderModule.DracoInt16Array(); decoder.GetAttributeInt16ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Int16Array(numValues); break; case Int32Array: dracoArray = new this.decoderModule.DracoInt32Array(); decoder.GetAttributeInt32ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Int32Array(numValues); break; case Uint8Array: dracoArray = new this.decoderModule.DracoUInt8Array(); decoder.GetAttributeUInt8ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Uint8Array(numValues); break; case Uint16Array: dracoArray = new this.decoderModule.DracoUInt16Array(); decoder.GetAttributeUInt16ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Uint16Array(numValues); break; case Uint32Array: dracoArray = new this.decoderModule.DracoUInt32Array(); decoder.GetAttributeUInt32ForAllPoints(dracoGeometry, dracoAttribute, dracoArray); typedArray = new Uint32Array(numValues); break; default: var errorMsg = 'DRACO decoder: unexpected attribute type.'; // console.error(errorMsg); throw new Error(errorMsg); } // Copy data from decoder. for (var i = 0; i < numValues; i++) { typedArray[i] = dracoArray.GetValue(i); } this.decoderModule.destroy(dracoArray); return { typedArray: typedArray, components: numComponents }; } }]); return DRACODecoder; }(); exports.default = DRACODecoder; //# sourceMappingURL=draco-decoder.js.map