ソースを参照

DRACOLoader: Support attribute type map.

Don McCurdy 7 年 前
コミット
0bf37822f3
2 ファイル変更99 行追加28 行削除
  1. 82 15
      examples/js/loaders/DRACOLoader.js
  2. 17 13
      examples/js/loaders/GLTFLoader.js

+ 82 - 15
examples/js/loaders/DRACOLoader.js

@@ -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.
        */
@@ -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);
         }
@@ -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.

+ 17 - 13
examples/js/loaders/GLTFLoader.js

@@ -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 ) {
 
@@ -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 );
 
 			} );