浏览代码

Merge pull request #11814 from Mugen87/dev

ColladaLoader2: Fix geometry parsing with different primitives
Mr.doob 8 年之前
父节点
当前提交
f63f29b28e
共有 1 个文件被更改,包括 153 次插入45 次删除
  1. 153 45
      examples/js/loaders/ColladaLoader2.js

+ 153 - 45
examples/js/loaders/ColladaLoader2.js

@@ -1885,6 +1885,24 @@ THREE.ColladaLoader.prototype = {
 
 		}
 
+		function groupPrimitives( primitives ) {
+
+			var build = {};
+
+			for ( var i = 0; i < primitives.length; i ++ ) {
+
+				var primitive = primitives[ i ];
+
+				if ( build[ primitive.type ] === undefined ) build[ primitive.type ] = [];
+
+				build[ primitive.type ].push( primitive );
+
+			}
+
+			return build;
+
+		}
+
 		function buildGeometry( data ) {
 
 			var build = {};
@@ -1895,6 +1913,27 @@ THREE.ColladaLoader.prototype = {
 
 			if ( primitives.length === 0 ) return {};
 
+			// our goal is to create one buffer geoemtry for a single type of primitives
+			// first, we group all primitives by their type
+
+			var groupedPrimitives = groupPrimitives( primitives );
+
+			for ( var type in groupedPrimitives ) {
+
+				// second, we create for each type of primitives (polylist,triangles or lines) a buffer geometry
+
+				build[ type ] = buildGeometryType( groupedPrimitives[ type ], sources, vertices );
+
+			}
+
+			return build;
+
+		}
+
+		function buildGeometryType( primitives, sources, vertices ) {
+
+			var build = {};
+
 			var position = { array: [], stride: 0 };
 			var normal = { array: [], stride: 0 };
 			var uv = { array: [], stride: 0 };
@@ -1904,7 +1943,6 @@ THREE.ColladaLoader.prototype = {
 			var skinWeight = { array: [], stride: 4 };
 
 			var geometry = new THREE.BufferGeometry();
-			geometry.name = data.name || '';
 
 			var materialKeys = [];
 
@@ -1925,7 +1963,16 @@ THREE.ColladaLoader.prototype = {
 
 				// groups
 
-				count = primitive.count * 3 * triangleCount;
+				if ( primitive.type === 'lines' || primitive.type === 'linestrips' ) {
+
+					count = primitive.count * 2;
+
+				} else {
+
+					count = primitive.count * 3 * triangleCount;
+
+				}
+
 				geometry.addGroup( start, count, p );
 				start += count;
 
@@ -1944,17 +1991,39 @@ THREE.ColladaLoader.prototype = {
 						case 'VERTEX':
 							for ( var key in vertices ) {
 
-								if ( key === 'POSITION' ) {
+								var id =  vertices[ key ];
 
-									buildGeometryData( primitive, sources[ vertices[ key ] ], input.offset, position.array );
-									position.stride = sources[ vertices[ key ] ].stride;
+								switch ( key ) {
 
-									if ( sources.skinWeights && sources.skinIndices ) {
+									case 'POSITION':
+										buildGeometryData( primitive, sources[ id ], input.offset, position.array );
+										position.stride = sources[ id ].stride;
 
-										buildGeometryData( primitive, sources.skinIndices, input.offset, skinIndex.array );
-										buildGeometryData( primitive, sources.skinWeights, input.offset, skinWeight.array );
+										if ( sources.skinWeights && sources.skinIndices ) {
 
-									}
+											buildGeometryData( primitive, sources.skinIndices, input.offset, skinIndex.array );
+											buildGeometryData( primitive, sources.skinWeights, input.offset, skinWeight.array );
+
+										}
+										break;
+
+									case 'NORMAL':
+										buildGeometryData( primitive, sources[ id ], input.offset, normal.array );
+										normal.stride = sources[ id ].stride;
+										break;
+
+									case 'COLOR':
+										buildGeometryData( primitive, sources[ id ], input.offset, color.array );
+										color.stride = sources[ id ].stride;
+										break;
+
+									case 'TEXCOORD':
+										buildGeometryData( primitive, sources[ id ], input.offset, uv.array );
+										uv.stride = sources[ id ].stride;
+										break;
+
+									default:
+										console.warn( 'THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key );
 
 								}
 
@@ -2785,7 +2854,7 @@ THREE.ColladaLoader.prototype = {
 
 		}
 
-		function getSkeleton( skeletons, joints ) {
+		function buildSkeleton( skeletons, joints ) {
 
 			var boneData = [];
 			var sortedBoneData = [];
@@ -2917,54 +2986,83 @@ THREE.ColladaLoader.prototype = {
 			var instanceGeometries = data.instanceGeometries;
 			var instanceNodes = data.instanceNodes;
 
+			// nodes
+
 			for ( var i = 0, l = nodes.length; i < l; i ++ ) {
 
 				objects.push( getNode( nodes[ i ] ) );
 
 			}
 
+			// instance cameras
+
 			for ( var i = 0, l = instanceCameras.length; i < l; i ++ ) {
 
 				objects.push( getCamera( instanceCameras[ i ] ).clone() );
 
 			}
 
+			// instance controllers
+
 			for ( var i = 0, l = instanceControllers.length; i < l; i ++ ) {
 
 				var instance = instanceControllers[ i ];
 				var controller = getController( instance.id );
-				var geometry = getGeometry( controller.id );
-				var materials = resolveMaterialBinding( geometry.materialKeys, instance.materials );
-				var object = getObject( geometry, materials );
+				var geometries = getGeometry( controller.id );
+				var newObjects = buildObjects( geometries, instance.materials );
 
 				var skeletons = instance.skeletons;
 				var joints = controller.skin.joints;
 
-				var skeleton = getSkeleton( skeletons, joints );
+				var skeleton = buildSkeleton( skeletons, joints );
 
-				object.bind( skeleton, controller.skin.bindMatrix );
-				object.normalizeSkinWeights();
+				for ( var j = 0, jl = newObjects.length; j < jl; j ++ ) {
 
-				objects.push( object );
+					var object = newObjects[ j ];
+
+					if ( object.isSkinnedMesh ) {
+
+						object.bind( skeleton, controller.skin.bindMatrix );
+						object.normalizeSkinWeights();
+
+					}
+
+					objects.push( object );
+
+				}
 
 			}
 
+			// instance lights
+
 			for ( var i = 0, l = instanceLights.length; i < l; i ++ ) {
 
 				objects.push( getLight( instanceLights[ i ] ).clone() );
 
 			}
 
+			// instance geometries
+
 			for ( var i = 0, l = instanceGeometries.length; i < l; i ++ ) {
 
 				var instance = instanceGeometries[ i ];
-				var geometry = getGeometry( instance.id );
-				var materials = resolveMaterialBinding( geometry.materialKeys, instance.materials );
-				var object = getObject( geometry, materials );
-				objects.push( object );
+
+				// a single geometry instance in collada can lead to multiple object3Ds.
+				// this is the case when primitives are combined like triangles and lines
+
+				var geometries = getGeometry( instance.id );
+				var newObjects = buildObjects( geometries, instance.materials );
+
+				for ( var j = 0, jl = newObjects.length; j < jl; j ++ ) {
+
+					objects.push( newObjects[ j ] );
+
+				}
 
 			}
 
+			// instance nodes
+
 			for ( var i = 0, l = instanceNodes.length; i < l; i ++ ) {
 
 				objects.push( getNode( instanceNodes[ i ] ).clone() );
@@ -3012,50 +3110,60 @@ THREE.ColladaLoader.prototype = {
 
 		}
 
-		function getObject( geometry, materials ) {
+		function buildObjects( geometries, instanceMaterials ) {
 
-			var object;
+			var objects = [];
+
+			for ( var type in geometries ) {
+
+				var geometry = geometries[ type ];
+
+				var materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials );
 
-			var skinning = ( geometry.data.attributes.skinIndex !== undefined );
+				var skinning = ( geometry.data.attributes.skinIndex !== undefined );
 
-			if ( skinning ) {
+				if ( skinning ) {
 
-				for ( var i = 0, l = materials.length; i < l; i ++ ) {
+					for ( var i = 0, l = materials.length; i < l; i ++ ) {
 
-					materials[ i ].skinning = true;
+						materials[ i ].skinning = true;
+
+					}
 
 				}
 
-			}
+				var material = ( materials.length === 1 ) ? materials[ 0 ] : materials;
 
-			var material = ( materials.length === 1 ) ? materials[ 0 ] : materials;
+				switch ( type ) {
 
-			switch ( geometry.type ) {
+					case 'lines':
+						object = new THREE.LineSegments( geometry.data, material );
+						break;
 
-				case 'lines':
-					object = new THREE.LineSegments( geometry.data, material );
-					break;
+					case 'linestrips':
+						object = new THREE.Line( geometry.data, material );
+						break;
 
-				case 'linestrips':
-					object = new THREE.Line( geometry.data, material );
-					break;
+					case 'triangles':
+					case 'polylist':
+						if ( skinning ) {
 
-				case 'triangles':
-				case 'polylist':
-					if ( skinning ) {
+							object = new THREE.SkinnedMesh( geometry.data, material );
 
-						object = new THREE.SkinnedMesh( geometry.data, material );
+						} else {
 
-					} else {
+							object = new THREE.Mesh( geometry.data, material );
 
-						object = new THREE.Mesh( geometry.data, material );
+						}
+						break;
 
-					}
-					break;
+				}
+
+				objects.push( object );
 
 			}
 
-			return object;
+			return objects;
 
 		}