Merge pull request #385 from donmccurdy/feat-dracoloader-typed-attributes

THREE.DRACOLoader: Support attribute type map.
This commit is contained in:
FrankGalligan 2018-05-11 16:55:11 -07:00 committed by GitHub
commit bd79625ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -100,17 +100,18 @@ THREE.DRACOLoader.prototype = {
* The format is: * The format is:
* attributeUniqueIdMap[attributeName] = attributeId * attributeUniqueIdMap[attributeName] = attributeId
*/ */
decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap) { decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap,
attributeTypeMap) {
var scope = this; var scope = this;
THREE.DRACOLoader.getDecoderModule() THREE.DRACOLoader.getDecoderModule()
.then( function ( module ) { .then( function ( module ) {
scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback, scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback,
attributeUniqueIdMap || {}); attributeUniqueIdMap || {}, attributeTypeMap || {});
}); });
}, },
decodeDracoFileInternal: function(rawBuffer, dracoDecoder, callback, decodeDracoFileInternal: function(rawBuffer, dracoDecoder, callback,
attributeUniqueIdMap) { attributeUniqueIdMap, attributeTypeMap) {
/* /*
* Here is how to use Draco Javascript decoder and get the geometry. * Here is how to use Draco Javascript decoder and get the geometry.
*/ */
@ -136,38 +137,103 @@ THREE.DRACOLoader.prototype = {
throw new Error(errorMsg); throw new Error(errorMsg);
} }
callback(this.convertDracoGeometryTo3JS(dracoDecoder, decoder, callback(this.convertDracoGeometryTo3JS(dracoDecoder, decoder,
geometryType, buffer, attributeUniqueIdMap)); geometryType, buffer, attributeUniqueIdMap, attributeTypeMap));
}, },
addAttributeToGeometry: function(dracoDecoder, decoder, dracoGeometry, addAttributeToGeometry: function(dracoDecoder, decoder, dracoGeometry,
attributeName, attribute, geometry, attributeName, attributeType, attribute,
geometryBuffer) { geometry, geometryBuffer) {
if (attribute.ptr === 0) { if (attribute.ptr === 0) {
var errorMsg = 'THREE.DRACOLoader: No attribute ' + attributeName; var errorMsg = 'THREE.DRACOLoader: No attribute ' + attributeName;
console.error(errorMsg); console.error(errorMsg);
throw new Error(errorMsg); throw new Error(errorMsg);
} }
var numComponents = attribute.num_components(); var numComponents = attribute.num_components();
var attributeData = new dracoDecoder.DracoFloat32Array();
decoder.GetAttributeFloatForAllPoints(
dracoGeometry, attribute, attributeData);
var numPoints = dracoGeometry.num_points(); var numPoints = dracoGeometry.num_points();
var numValues = numPoints * numComponents; var numValues = numPoints * numComponents;
// Allocate space for attribute. var attributeData;
geometryBuffer[attributeName] = new Float32Array(numValues); var TypedBufferAttribute;
switch ( attributeType ) {
case Float32Array:
attributeData = new dracoDecoder.DracoFloat32Array();
decoder.GetAttributeFloatForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Float32Array( numValues );
TypedBufferAttribute = THREE.Float32BufferAttribute;
break;
case Int8Array:
attributeData = new dracoDecoder.DracoInt8Array();
decoder.GetAttributeInt8ForAllPoints(
dracoGeometry, attribute, attributeData );
geometryBuffer[ attributeName ] = new Int8Array( numValues );
TypedBufferAttribute = THREE.Int8BufferAttribute;
break;
case Int16Array:
attributeData = new dracoDecoder.DracoInt16Array();
decoder.GetAttributeInt16ForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Int16Array( numValues );
TypedBufferAttribute = THREE.Int16BufferAttribute;
break;
case Int32Array:
attributeData = new dracoDecoder.DracoInt32Array();
decoder.GetAttributeInt32ForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Int32Array( numValues );
TypedBufferAttribute = THREE.Int32BufferAttribute;
break;
case Uint8Array:
attributeData = new dracoDecoder.DracoUInt8Array();
decoder.GetAttributeUInt8ForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Uint8Array( numValues );
TypedBufferAttribute = THREE.Uint8BufferAttribute;
break;
case Uint16Array:
attributeData = new dracoDecoder.DracoUInt16Array();
decoder.GetAttributeUInt16ForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Uint16Array( numValues );
TypedBufferAttribute = THREE.Uint16BufferAttribute;
break;
case Uint32Array:
attributeData = new dracoDecoder.DracoUInt32Array();
decoder.GetAttributeUInt32ForAllPoints(
dracoGeometry, attribute, attributeData);
geometryBuffer[ attributeName ] = new Uint32Array( numValues );
TypedBufferAttribute = THREE.Uint32BufferAttribute;
break;
default:
var errorMsg = 'THREE.DRACOLoader: Unexpected attribute type.';
console.error( errorMsg );
throw new Error( errorMsg );
}
// Copy data from decoder. // Copy data from decoder.
for (var i = 0; i < numValues; i++) { for (var i = 0; i < numValues; i++) {
geometryBuffer[attributeName][i] = attributeData.GetValue(i); geometryBuffer[attributeName][i] = attributeData.GetValue(i);
} }
// Add attribute to THREEJS geometry for rendering. // Add attribute to THREEJS geometry for rendering.
geometry.addAttribute(attributeName, geometry.addAttribute(attributeName,
new THREE.Float32BufferAttribute(geometryBuffer[attributeName], new TypedBufferAttribute(geometryBuffer[attributeName],
numComponents)); numComponents));
dracoDecoder.destroy(attributeData); dracoDecoder.destroy(attributeData);
}, },
convertDracoGeometryTo3JS: function(dracoDecoder, decoder, geometryType, convertDracoGeometryTo3JS: function(dracoDecoder, decoder, geometryType,
buffer, attributeUniqueIdMap) { buffer, attributeUniqueIdMap,
attributeTypeMap) {
if (this.getAttributeOptions('position').skipDequantization === true) { if (this.getAttributeOptions('position').skipDequantization === true) {
decoder.SkipAttributeTransform(dracoDecoder.POSITION); decoder.SkipAttributeTransform(dracoDecoder.POSITION);
} }
@ -244,18 +310,19 @@ THREE.DRACOLoader.prototype = {
} }
var attribute = decoder.GetAttribute(dracoGeometry, attId); var attribute = decoder.GetAttribute(dracoGeometry, attId);
this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry, this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry,
attributeName, attribute, geometry, geometryBuffer); attributeName, Float32Array, attribute, geometry, geometryBuffer);
} }
} }
} }
// Add attributes of user specified unique id. E.g. GLTF models. // Add attributes of user specified unique id. E.g. GLTF models.
for (var attributeName in attributeUniqueIdMap) { for (var attributeName in attributeUniqueIdMap) {
var attributeType = attributeTypeMap[attributeName] || Float32Array;
var attributeId = attributeUniqueIdMap[attributeName]; var attributeId = attributeUniqueIdMap[attributeName];
var attribute = decoder.GetAttributeByUniqueId(dracoGeometry, var attribute = decoder.GetAttributeByUniqueId(dracoGeometry,
attributeId); attributeId);
this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry, this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry,
attributeName, attribute, geometry, geometryBuffer); attributeName, attributeType, attribute, geometry, geometryBuffer);
} }
// For mesh, we need to generate the faces. // For mesh, we need to generate the faces.