Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRACOLoader: Update to v1.3.1, support typed attributes. #14002

Merged
merged 4 commits into from
May 5, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
DRACOLoader: Support attribute type map.
  • Loading branch information
donmccurdy committed May 5, 2018
commit 0bf37822f3c693ed5f700845666cf2886c065b11
97 changes: 82 additions & 15 deletions examples/js/loaders/DRACOLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,18 @@ THREE.DRACOLoader.prototype = {
* The format is:
* attributeUniqueIdMap[attributeName] = attributeId
*/
decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap) {
decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap,
attributeTypeMap) {
var scope = this;
THREE.DRACOLoader.getDecoderModule()
.then( function ( module ) {
scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback,
attributeUniqueIdMap || {});
attributeUniqueIdMap || {}, attributeTypeMap || {});
});
},

decodeDracoFileInternal: function(rawBuffer, dracoDecoder, callback,
attributeUniqueIdMap) {
attributeUniqueIdMap, attributeTypeMap) {
/*
* Here is how to use Draco Javascript decoder and get the geometry.
*/
Expand All @@ -136,38 +137,103 @@ THREE.DRACOLoader.prototype = {
throw new Error(errorMsg);
}
callback(this.convertDracoGeometryTo3JS(dracoDecoder, decoder,
geometryType, buffer, attributeUniqueIdMap));
geometryType, buffer, attributeUniqueIdMap, attributeTypeMap));
},

addAttributeToGeometry: function(dracoDecoder, decoder, dracoGeometry,
attributeName, attribute, geometry,
geometryBuffer) {
attributeName, attributeType, attribute,
geometry, geometryBuffer) {
if (attribute.ptr === 0) {
var errorMsg = 'THREE.DRACOLoader: No attribute ' + attributeName;
console.error(errorMsg);
throw new Error(errorMsg);
}

var numComponents = attribute.num_components();
var attributeData = new dracoDecoder.DracoFloat32Array();
decoder.GetAttributeFloatForAllPoints(
dracoGeometry, attribute, attributeData);
var numPoints = dracoGeometry.num_points();
var numValues = numPoints * numComponents;
// Allocate space for attribute.
geometryBuffer[attributeName] = new Float32Array(numValues);
var attributeData;
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.
for (var i = 0; i < numValues; i++) {
geometryBuffer[attributeName][i] = attributeData.GetValue(i);
}
// Add attribute to THREEJS geometry for rendering.
geometry.addAttribute(attributeName,
new THREE.Float32BufferAttribute(geometryBuffer[attributeName],
new TypedBufferAttribute(geometryBuffer[attributeName],
numComponents));
dracoDecoder.destroy(attributeData);
},

convertDracoGeometryTo3JS: function(dracoDecoder, decoder, geometryType,
buffer, attributeUniqueIdMap) {
buffer, attributeUniqueIdMap,
attributeTypeMap) {
if (this.getAttributeOptions('position').skipDequantization === true) {
decoder.SkipAttributeTransform(dracoDecoder.POSITION);
}
Expand Down Expand Up @@ -244,18 +310,19 @@ THREE.DRACOLoader.prototype = {
}
var attribute = decoder.GetAttribute(dracoGeometry, attId);
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.
for (var attributeName in attributeUniqueIdMap) {
var attributeType = attributeTypeMap[attributeName] || Float32Array;
var attributeId = attributeUniqueIdMap[attributeName];
var attribute = decoder.GetAttributeByUniqueId(dracoGeometry,
attributeId);
this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry,
attributeName, attribute, geometry, geometryBuffer);
attributeName, attributeType, attribute, geometry, geometryBuffer);
}

// For mesh, we need to generate the faces.
Expand Down
30 changes: 17 additions & 13 deletions examples/js/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ THREE.GLTFLoader = ( function () {
var bufferViewIndex = primitive.extensions[ this.name ].bufferView;
var gltfAttributeMap = primitive.extensions[ this.name ].attributes;
var threeAttributeMap = {};
var attributeNormalizedMap = {};
var attributeTypeMap = {};

for ( var attributeName in gltfAttributeMap ) {

Expand All @@ -485,33 +487,35 @@ THREE.GLTFLoader = ( function () {

}

return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
for ( attributeName in primitive.attributes ) {

return new Promise( function ( resolve ) {
if ( ATTRIBUTES[ attributeName ] !== undefined && gltfAttributeMap[ attributeName ] !== undefined ) {

dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {
var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
var componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];

for ( var attributeName in primitive.attributes ) {
attributeTypeMap[ ATTRIBUTES[ attributeName ] ] = componentType;
attributeNormalizedMap[ ATTRIBUTES[ attributeName ] ] = accessorDef.normalized === true;

if ( ATTRIBUTES[ attributeName ] && geometry.attributes[ ATTRIBUTES[ attributeName ] ] ) {
}

var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
}

if ( accessorDef.normalized === true ) {
return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {

var attribute = geometry.attributes[ ATTRIBUTES[ attributeName ] ];
geometry.attributes[ ATTRIBUTES[ attributeName ] ].normalized = true;
geometry.attributes[ ATTRIBUTES[ attributeName ] ].needsUpdate = true;
return new Promise( function ( resolve ) {

}
dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {

}
for ( var attributeName in geometry.attributes ) {

geometry.attributes[ attributeName ].normalized = attributeNormalizedMap[ attributeName ];

}

resolve( geometry );

}, threeAttributeMap );
}, threeAttributeMap, attributeTypeMap );

} );

Expand Down