浏览代码

GLTFLoader: Fix race condition with different Draco attribute maps in a single asset.

Don McCurdy 7 年之前
父节点
当前提交
2bcdb447a4
共有 2 个文件被更改,包括 43 次插入84 次删除
  1. 34 74
      examples/js/loaders/GLTFLoader.js
  2. 9 10
      examples/js/loaders/draco/DRACOLoader.js

+ 34 - 74
examples/js/loaders/GLTFLoader.js

@@ -391,36 +391,29 @@ THREE.GLTFLoader = ( function () {
 
 		this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
 		this.dracoLoader = dracoLoader;
-		this.glTFNameToThreeJSName = {
-			'POSITION' : 'position',
-			'NORMAL' : 'normal',
-			'TEXCOORD_0' : 'uv',
-			'TEXCOORD0' : 'uv',
-			'TEXCOORD' : 'uv',
-			'TEXCOORD_1' : 'uv2',
-			'COLOR_0' : 'color',
-			'COLOR0' : 'color',
-			'COLOR' : 'color',
-			'WEIGHTS_0' : 'skinWeight',
-			'JOINTS_0' : 'skinIndex'
-		};
+
 	}
 
 	GLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) {
 
 		var dracoLoader = this.dracoLoader;
 		var bufferViewIndex = primitive.extensions[ this.name ].bufferView;
-		var attributesIdMap = primitive.extensions[ this.name ].attributes;
-		var attributeMap = {};
-		for (var attributeName in attributesIdMap) {
-			attributeMap[this.glTFNameToThreeJSName[attributeName]] = attributesIdMap[attributeName];
+		var gltfAttributeMap = primitive.extensions[ this.name ].attributes;
+		var threeAttributeMap = {};
+
+		for ( var attributeName in gltfAttributeMap ) {
+
+			if ( !( attributeName in ATTRIBUTES ) ) continue;
+
+			threeAttributeMap[ ATTRIBUTES[ attributeName ] ] = gltfAttributeMap[ attributeName ];
+
 		}
 
 		return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
 
 			return new Promise( function ( resolve ) {
 
-				dracoLoader.decodeDracoFile( bufferView, resolve, attributeMap );
+				dracoLoader.decodeDracoFile( bufferView, resolve, threeAttributeMap );
 
 			} );
 
@@ -1012,6 +1005,22 @@ THREE.GLTFLoader = ( function () {
 		'MAT4': 16
 	};
 
+	var ATTRIBUTES = {
+		POSITION: 'position',
+		NORMAL: 'normal',
+		TEXCOORD_0: 'uv',
+		TEXCOORD0: 'uv', // deprecated
+		TEXCOORD: 'uv', // deprecated
+		TEXCOORD_1: 'uv2',
+		COLOR_0: 'color',
+		COLOR0: 'color', // deprecated
+		COLOR: 'color', // deprecated
+		WEIGHTS_0: 'skinWeight',
+		WEIGHT: 'skinWeight', // deprecated
+		JOINTS_0: 'skinIndex',
+		JOINT: 'skinIndex' // deprecated
+	}
+
 	var PATH_PROPERTIES = {
 		scale: 'scale',
 		translation: 'position',
@@ -1962,65 +1971,16 @@ THREE.GLTFLoader = ( function () {
 
 		var attributes = primitiveDef.attributes;
 
-		for ( var attributeId in attributes ) {
-
-			var attributeEntry = attributes[ attributeId ];
-
-			var bufferAttribute = accessors[ attributeEntry ];
-
-			// TODO(donmccurdy): Clean this up and try to break early.
-
-			switch ( attributeId ) {
-
-				case 'POSITION':
-
-					if ( 'position' in geometry.attributes ) break;
-					geometry.addAttribute( 'position', bufferAttribute );
-					break;
-
-				case 'NORMAL':
+		for ( var gltfAttributeName in attributes ) {
 
-					if ( 'normal' in geometry.attributes ) break;
-					geometry.addAttribute( 'normal', bufferAttribute );
-					break;
-
-				case 'TEXCOORD_0':
-				case 'TEXCOORD0':
-				case 'TEXCOORD':
-
-					if ( 'uv' in geometry.attributes ) break;
-					geometry.addAttribute( 'uv', bufferAttribute );
-					break;
-
-				case 'TEXCOORD_1':
-
-					if ( 'uv2' in geometry.attributes ) break;
-					geometry.addAttribute( 'uv2', bufferAttribute );
-					break;
-
-				case 'COLOR_0':
-				case 'COLOR0':
-				case 'COLOR':
+			var threeAttributeName = ATTRIBUTES[ gltfAttributeName ];
+			var bufferAttribute = accessors[ attributes[ gltfAttributeName ] ];
 
-					if ( 'color' in geometry.attributes ) break;
-					geometry.addAttribute( 'color', bufferAttribute );
-					break;
-
-				case 'WEIGHTS_0':
-				case 'WEIGHT': // WEIGHT semantic deprecated.
-
-					if ( 'skinWeight' in geometry.attributes ) break;
-					geometry.addAttribute( 'skinWeight', bufferAttribute );
-					break;
+			// Skip attributes already provided by e.g. Draco extension.
+			if ( !threeAttributeName ) continue;
+			if ( threeAttributeName in geometry.attributes ) continue;
 
-				case 'JOINTS_0':
-				case 'JOINT': // JOINT semantic deprecated.
-
-					if ( 'skinIndex' in geometry.attributes ) break;
-					geometry.addAttribute( 'skinIndex', bufferAttribute );
-					break;
-
-			}
+			geometry.addAttribute( threeAttributeName, bufferAttribute );
 
 		}
 

+ 9 - 10
examples/js/loaders/draco/DRACOLoader.js

@@ -24,8 +24,6 @@ THREE.DRACOLoader = function(manager) {
     this.verbosity = 0;
     this.attributeOptions = {};
     this.drawMode = THREE.TrianglesDrawMode;
-    // User defined unique id for attributes.
-    this.attributeUniqueIdMap = {};
     // Native Draco attribute type to Three.JS attribute type.
     this.nativeAttributeMap = {
       'position' : 'POSITION',
@@ -104,14 +102,15 @@ THREE.DRACOLoader.prototype = {
      */
     decodeDracoFile: function(rawBuffer, callback, attributeUniqueIdMap) {
       var scope = this;
-      this.attributeUniqueIdMap = attributeUniqueIdMap || {};
       THREE.DRACOLoader.getDecoderModule()
           .then( function ( module ) {
-            scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback );
+            scope.decodeDracoFileInternal( rawBuffer, module.decoder, callback,
+              attributeUniqueIdMap );
           });
     },
 
-    decodeDracoFileInternal: function(rawBuffer, dracoDecoder, callback) {
+    decodeDracoFileInternal: function(rawBuffer, dracoDecoder, callback,
+                                      attributeUniqueIdMap) {
       /*
        * Here is how to use Draco Javascript decoder and get the geometry.
        */
@@ -137,7 +136,7 @@ THREE.DRACOLoader.prototype = {
         throw new Error(errorMsg);
       }
       callback(this.convertDracoGeometryTo3JS(dracoDecoder, decoder,
-          geometryType, buffer));
+          geometryType, buffer, attributeUniqueIdMap));
     },
 
     addAttributeToGeometry: function(dracoDecoder, decoder, dracoGeometry,
@@ -168,7 +167,7 @@ THREE.DRACOLoader.prototype = {
     },
 
     convertDracoGeometryTo3JS: function(dracoDecoder, decoder, geometryType,
-                                        buffer) {
+                                        buffer, attributeUniqueIdMap) {
         if (this.getAttributeOptions('position').skipDequantization === true) {
           decoder.SkipAttributeTransform(dracoDecoder.POSITION);
         }
@@ -236,7 +235,7 @@ THREE.DRACOLoader.prototype = {
         for (var attributeName in this.nativeAttributeMap) {
           // The native attribute type is only used when no unique Id is
           // provided. For example, loading .drc files.
-          if (this.attributeUniqueIdMap[attributeName] === undefined) {
+          if (attributeUniqueIdMap[attributeName] === undefined) {
             var attId = decoder.GetAttributeId(dracoGeometry,
                 dracoDecoder[this.nativeAttributeMap[attributeName]]);
             if (attId !== -1) {
@@ -251,8 +250,8 @@ THREE.DRACOLoader.prototype = {
         }
 
         // Add attributes of user specified unique id. E.g. GLTF models.
-        for (var attributeName in this.attributeUniqueIdMap) {
-          var attributeId = this.attributeUniqueIdMap[attributeName];
+        for (var attributeName in attributeUniqueIdMap) {
+          var attributeId = attributeUniqueIdMap[attributeName];
           var attribute = decoder.GetAttributeByUniqueId(dracoGeometry,
                                                          attributeId);
           this.addAttributeToGeometry(dracoDecoder, decoder, dracoGeometry,