loaders.gl
Version:
Framework-independent loaders for 3D graphics formats
325 lines (266 loc) • 12.3 kB
JavaScript
"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