Browse Source

ColladaLoader2: Separated parse and build steps.

Mr.doob 9 years ago
parent
commit
a9c17b5212
1 changed files with 252 additions and 116 deletions
  1. 252 116
      examples/js/loaders/ColladaLoader2.js

+ 252 - 116
examples/js/loaders/ColladaLoader2.js

@@ -84,7 +84,7 @@ THREE.ColladaLoader.prototype = {
 
 
 		// library
 		// library
 
 
-		function buildLibrary( data, libraryName, nodeName, parser ) {
+		function parseLibrary( data, libraryName, nodeName, parser ) {
 
 
 			var library = xml.getElementsByTagName( libraryName )[ 0 ];
 			var library = xml.getElementsByTagName( libraryName )[ 0 ];
 
 
@@ -94,8 +94,7 @@ THREE.ColladaLoader.prototype = {
 
 
 				for ( var i = 0; i < elements.length; i ++ ) {
 				for ( var i = 0; i < elements.length; i ++ ) {
 
 
-					var element = elements[ i ];
-					data[ element.getAttribute( 'id' ) ] = parser( element );
+					parser( elements[ i ] );
 
 
 				}
 				}
 
 
@@ -103,13 +102,48 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
+		function buildLibrary( data, builder ) {
+
+			for ( var name in data ) {
+
+				var object = data[ name ];
+				object.build = builder( data[ name ] );
+
+			}
+
+		}
+
+		// get
+
+		function getBuild( data, builder ) {
+
+			if ( data.build !== undefined ) return data.build;
+
+			data.build = builder( data );
+
+			return data.build;
+
+		}
+
 		// image
 		// image
 
 
 		var imageLoader = new THREE.ImageLoader();
 		var imageLoader = new THREE.ImageLoader();
 
 
 		function parseImage( xml ) {
 		function parseImage( xml ) {
 
 
-			var url = xml.getElementsByTagName( 'init_from' )[ 0 ].textContent;
+			var data = {
+				url: xml.getElementsByTagName( 'init_from' )[ 0 ].textContent
+			};
+
+			library.images[ xml.getAttribute( 'id' ) ] = data;
+
+		}
+
+		function buildImage( data ) {
+
+			if ( data.build !== undefined ) return data.build;
+
+			var url = data.url;
 
 
 			if ( baseUrl !== undefined ) url = baseUrl + url;
 			if ( baseUrl !== undefined ) url = baseUrl + url;
 
 
@@ -117,11 +151,25 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
+		function getImage( id ) {
+
+			return getBuild( library.images[ id ], buildImage );
+
+		}
+
 		// effect
 		// effect
 
 
 		function parseEffect( xml ) {
 		function parseEffect( xml ) {
 
 
-			// console.log( xml );
+		}
+
+		function buildEffect( data ) {
+
+		}
+
+		function getEffect( id ) {
+
+			return getBuild( library.effects[ id ], buildEffect );
 
 
 		}
 		}
 
 
@@ -129,14 +177,29 @@ THREE.ColladaLoader.prototype = {
 
 
 		function parseCamera( xml ) {
 		function parseCamera( xml ) {
 
 
-			console.log( 'ColladaLoader.parseCamera: TODO')
+			var data = {
+				name: xml.getAttribute( 'name' )
+			};
+
+			library.cameras[ xml.getAttribute( 'id' ) ] = {};
+
+		}
+
+		function buildCamera( data ) {
 
 
 			var camera = new THREE.PerspectiveCamera();
 			var camera = new THREE.PerspectiveCamera();
-			camera.name = xml.getAttribute( 'name' );
+			camera.name = data.name;
+
 			return camera;
 			return camera;
 
 
 		}
 		}
 
 
+		function getCamera( id ) {
+
+			return getBuild( library.cameras[ id ], buildCamera );
+
+		}
+
 		// light
 		// light
 
 
 		function parseLight( xml ) {
 		function parseLight( xml ) {
@@ -159,34 +222,7 @@ THREE.ColladaLoader.prototype = {
 
 
 			}
 			}
 
 
-			//
-
-			var light;
-
-			switch ( data.technique ) {
-
-				case 'directional':
-					light = new THREE.DirectionalLight();
-					break;
-
-				case 'point':
-					light = new THREE.PointLight();
-					break;
-
-				case 'spot':
-					light = new THREE.SpotLight();
-					break;
-
-				case 'ambient':
-					light = new THREE.AmbientLight();
-					break;
-
-			}
-
-			if ( data.parameters.color ) light.color.copy( data.parameters.color );
-			if ( data.parameters.distance ) light.distance = data.parameters.distance;
-
-			return light;
+			library.lights[ xml.getAttribute( 'id' ) ] = data;
 
 
 		}
 		}
 
 
@@ -252,15 +288,48 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
-		// geometry
+		function buildLight( data ) {
+
+			var light;
+
+			switch ( data.technique ) {
+
+				case 'directional':
+					light = new THREE.DirectionalLight();
+					break;
+
+				case 'point':
+					light = new THREE.PointLight();
+					break;
+
+				case 'spot':
+					light = new THREE.SpotLight();
+					break;
+
+				case 'ambient':
+					light = new THREE.AmbientLight();
+					break;
+
+			}
+
+			if ( data.parameters.color ) light.color.copy( data.parameters.color );
+			if ( data.parameters.distance ) light.distance = data.parameters.distance;
+
+			return light;
+
+		}
+
+		function getLight( id ) {
 
 
-		var lineMaterial = new THREE.LineBasicMaterial();
-		var meshMaterial = new THREE.MeshPhongMaterial();
+			return getBuild( library.lights[ id ], buildLight );
+
+		}
+
+		// geometry
 
 
 		function parseGeometry( xml ) {
 		function parseGeometry( xml ) {
 
 
 			var data = {
 			var data = {
-				id: xml.getAttribute( 'id' ),
 				name: xml.getAttribute( 'name' ),
 				name: xml.getAttribute( 'name' ),
 				sources: {},
 				sources: {},
 				primitives: []
 				primitives: []
@@ -302,7 +371,51 @@ THREE.ColladaLoader.prototype = {
 
 
 			}
 			}
 
 
-			//
+			library.geometries[ xml.getAttribute( 'id' ) ] = data;
+
+		}
+
+		function parseGeometryPrimitive( xml ) {
+
+			var primitive = {
+				type: xml.nodeName,
+				inputs: {},
+				stride: 0
+			};
+
+			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'input':
+						var id = parseId( child.getAttribute( 'source' ) );
+						var semantic = child.getAttribute( 'semantic' );
+						var offset = parseInt( child.getAttribute( 'offset' ) );
+						primitive.inputs[ semantic ] = { id: id, offset: offset };
+						primitive.stride = Math.max( primitive.stride, offset + 1 );
+						break;
+
+					case 'vcount':
+						primitive.vcount = parseInts( child.textContent );
+						break;
+
+					case 'p':
+						primitive.p = parseInts( child.textContent );
+						break;
+
+				}
+
+			}
+
+			return primitive;
+
+		}
+
+		function buildGeometry( data ) {
 
 
 			var group = new THREE.Group();
 			var group = new THREE.Group();
 
 
@@ -412,16 +525,16 @@ THREE.ColladaLoader.prototype = {
 				switch ( primitive.type ) {
 				switch ( primitive.type ) {
 
 
 					case 'lines':
 					case 'lines':
-						group.add( new THREE.LineSegments( geometry, lineMaterial ) );
+						group.add( new THREE.LineSegments( geometry ) );
 						break;
 						break;
 
 
 					case 'linestrips':
 					case 'linestrips':
-						group.add( new THREE.Line( geometry, lineMaterial ) );
+						group.add( new THREE.Line( geometry ) );
 						break;
 						break;
 
 
 					case 'triangles':
 					case 'triangles':
 					case 'polylist':
 					case 'polylist':
-						group.add( new THREE.Mesh( geometry, meshMaterial ) );
+						group.add( new THREE.Mesh( geometry ) );
 						break;
 						break;
 
 
 				}
 				}
@@ -440,43 +553,9 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
-		function parseGeometryPrimitive( xml ) {
-
-			var primitive = {
-				type: xml.nodeName,
-				inputs: {},
-				stride: 0
-			};
-
-			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
-
-				var child = xml.childNodes[ i ];
-
-				if ( child.nodeType !== 1 ) continue;
-
-				switch ( child.nodeName ) {
-
-					case 'input':
-						var id = parseId( child.getAttribute( 'source' ) );
-						var semantic = child.getAttribute( 'semantic' );
-						var offset = parseInt( child.getAttribute( 'offset' ) );
-						primitive.inputs[ semantic ] = { id: id, offset: offset };
-						primitive.stride = Math.max( primitive.stride, offset + 1 );
-						break;
-
-					case 'vcount':
-						primitive.vcount = parseInts( child.textContent );
-						break;
-
-					case 'p':
-						primitive.p = parseInts( child.textContent );
-						break;
-
-				}
-
-			}
+		function getGeometry( id ) {
 
 
-			return primitive;
+			return getBuild( library.geometries[ id ], buildGeometry );
 
 
 		}
 		}
 
 
@@ -487,10 +566,10 @@ THREE.ColladaLoader.prototype = {
 
 
 		function parseNode( xml ) {
 		function parseNode( xml ) {
 
 
-			var node = {
+			var data = {
 				name: xml.getAttribute( 'name' ),
 				name: xml.getAttribute( 'name' ),
 				matrix: new THREE.Matrix4(),
 				matrix: new THREE.Matrix4(),
-				children: []
+				nodes: []
 			};
 			};
 
 
 			for ( var i = 0; i < xml.childNodes.length; i ++ ) {
 			for ( var i = 0; i < xml.childNodes.length; i ++ ) {
@@ -502,45 +581,46 @@ THREE.ColladaLoader.prototype = {
 				switch ( child.nodeName ) {
 				switch ( child.nodeName ) {
 
 
 					case 'instance_camera':
 					case 'instance_camera':
-						node.camera = library.cameras[ parseId( child.getAttribute( 'url' ) ) ];
+						data.camera = parseId( child.getAttribute( 'url' ) );
 						break;
 						break;
 
 
 					case 'instance_light':
 					case 'instance_light':
-						node.light = library.lights[ parseId( child.getAttribute( 'url' ) ) ];
+						data.light = parseId( child.getAttribute( 'url' ) );
 						break;
 						break;
 
 
 					case 'instance_geometry':
 					case 'instance_geometry':
-						node.geometry = library.geometries[ parseId( child.getAttribute( 'url' ) ) ];
+						data.geometry = parseId( child.getAttribute( 'url' ) );
 						break;
 						break;
 
 
 					case 'instance_node':
 					case 'instance_node':
-						node.children.push( library.nodes[ parseId( child.getAttribute( 'url' ) ) ] );
+						data.nodes.push( parseId( child.getAttribute( 'url' ) ) );
 						break;
 						break;
 
 
 					case 'matrix':
 					case 'matrix':
 						var array = parseFloats( child.textContent );
 						var array = parseFloats( child.textContent );
-						node.matrix.multiply( matrix.fromArray( array ).transpose() ); // .transpose() when Z_UP?
+						data.matrix.multiply( matrix.fromArray( array ).transpose() ); // .transpose() when Z_UP?
 						break;
 						break;
 
 
 					case 'node':
 					case 'node':
-						node.children.push( parseNode( child ) );
+						parseNode( child );
+						data.nodes.push( child.getAttribute( 'id' ) );
 						break;
 						break;
 
 
 					case 'translate':
 					case 'translate':
 						var array = parseFloats( child.textContent );
 						var array = parseFloats( child.textContent );
 						vector.fromArray( array );
 						vector.fromArray( array );
-						node.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) );
+						data.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) );
 						break;
 						break;
 
 
 					case 'rotate':
 					case 'rotate':
 						var array = parseFloats( child.textContent );
 						var array = parseFloats( child.textContent );
 						var angle = THREE.Math.degToRad( array[ 3 ] );
 						var angle = THREE.Math.degToRad( array[ 3 ] );
-						node.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) );
+						data.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) );
 						break;
 						break;
 
 
 					case 'scale':
 					case 'scale':
 						var array = parseFloats( child.textContent );
 						var array = parseFloats( child.textContent );
-						node.matrix.scale( vector.fromArray( array ) );
+						data.matrix.scale( vector.fromArray( array ) );
 						break;
 						break;
 
 
 					case 'extra':
 					case 'extra':
@@ -554,21 +634,31 @@ THREE.ColladaLoader.prototype = {
 
 
 			}
 			}
 
 
-			//
+			if ( xml.getAttribute( 'id' ) !== null ) {
+
+				library.nodes[ xml.getAttribute( 'id' ) ] = data;
+
+			}
+
+			return data;
+
+		}
+
+		function buildNode( data ) {
 
 
 			var object;
 			var object;
 
 
-			if ( node.camera !== undefined ) {
+			if ( data.camera !== undefined ) {
 
 
-				object = node.camera.clone();
+				object = getCamera( data.camera ).clone();
 
 
-			} else if ( node.light !== undefined) {
+			} else if ( data.light !== undefined) {
 
 
-				object = node.light.clone();
+				object = getLight( data.light ).clone();
 
 
-			} else if ( node.geometry !== undefined ) {
+			} else if ( data.geometry !== undefined ) {
 
 
-				object = node.geometry.clone();
+				object = getGeometry( data.geometry ).clone();
 
 
 			} else {
 			} else {
 
 
@@ -576,14 +666,12 @@ THREE.ColladaLoader.prototype = {
 
 
 			}
 			}
 
 
-			object.name = node.name;
-			node.matrix.decompose( object.position, object.quaternion, object.scale );
+			object.name = data.name;
+			data.matrix.decompose( object.position, object.quaternion, object.scale );
 
 
-			var children = node.children;
+			for ( var i = 0, l = data.nodes.length; i < l; i ++ ) {
 
 
-			for ( var i = 0, l = children.length; i < l; i ++ ) {
-
-				object.add( children[ i ] );
+				object.add( getNode( data.nodes[ i ] ).clone() );
 
 
 			}
 			}
 
 
@@ -591,19 +679,43 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
+		function getNode( id ) {
+
+			return getBuild( library.nodes[ id ], buildNode );
+
+		}
+
 		// visual scenes
 		// visual scenes
 
 
 		function parseVisualScene( xml ) {
 		function parseVisualScene( xml ) {
 
 
-			var group = new THREE.Group();
-			group.name = xml.getAttribute( 'name' );
+			var data = {
+				name: xml.getAttribute( 'name' ),
+				children: []
+			};
 
 
 			var elements = xml.getElementsByTagName( 'node' );
 			var elements = xml.getElementsByTagName( 'node' );
 
 
 			for ( var i = 0; i < elements.length; i ++ ) {
 			for ( var i = 0; i < elements.length; i ++ ) {
 
 
-				var element = elements[ i ];
-				group.add( parseNode( element ) );
+				data.children.push( parseNode( elements[ i ] ) );
+
+			}
+
+			library.visualScenes[ xml.getAttribute( 'id' ) ] = data;
+
+		}
+
+		function buildVisualScene( data ) {
+
+			var group = new THREE.Group();
+			group.name = data.name;
+
+			var children = data.children;
+
+			for ( var i = 0; i < children.length; i ++ ) {
+
+				group.add( buildNode( children[ i ] ) );
 
 
 			}
 			}
 
 
@@ -611,13 +723,19 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
+		function getVisualScene( id ) {
+
+			return getBuild( library.visualScenes[ id ], buildVisualScene );
+
+		}
+
 		// scenes
 		// scenes
 
 
 		function parseScene( xml ) {
 		function parseScene( xml ) {
 
 
 			var scene = xml.getElementsByTagName( 'scene' )[ 0 ];
 			var scene = xml.getElementsByTagName( 'scene' )[ 0 ];
 			var instance = scene.getElementsByTagName( 'instance_visual_scene' )[ 0 ];
 			var instance = scene.getElementsByTagName( 'instance_visual_scene' )[ 0 ];
-			return library.visualScenes[ parseId( instance.getAttribute( 'url' ) ) ];
+			return getVisualScene( parseId( instance.getAttribute( 'url' ) ) );
 
 
 		}
 		}
 
 
@@ -631,7 +749,7 @@ THREE.ColladaLoader.prototype = {
 
 
 		var library = {
 		var library = {
 			images: {},
 			images: {},
-			effects: {},
+			// effects: {},
 			cameras: {},
 			cameras: {},
 			lights: {},
 			lights: {},
 			geometries: {},
 			geometries: {},
@@ -639,13 +757,31 @@ THREE.ColladaLoader.prototype = {
 			visualScenes: {}
 			visualScenes: {}
 		};
 		};
 
 
-		buildLibrary( library.images, 'library_images', 'image', parseImage );
-		buildLibrary( library.effects, 'library_effects', 'effect', parseEffect );
-		buildLibrary( library.cameras, 'library_cameras', 'camera', parseCamera );
-		buildLibrary( library.lights, 'library_lights', 'light', parseLight );
-		buildLibrary( library.geometries, 'library_geometries', 'geometry', parseGeometry );
-		buildLibrary( library.nodes, 'library_nodes', 'node', parseNode );
-		buildLibrary( library.visualScenes, 'library_visual_scenes', 'visual_scene', parseVisualScene );
+		console.time( 'ColladaLoader: Parse' );
+
+		parseLibrary( library.images, 'library_images', 'image', parseImage );
+		// parseLibrary( library.effects, 'library_effects', 'effect', parseEffect );
+		parseLibrary( library.cameras, 'library_cameras', 'camera', parseCamera );
+		parseLibrary( library.lights, 'library_lights', 'light', parseLight );
+		parseLibrary( library.geometries, 'library_geometries', 'geometry', parseGeometry );
+		parseLibrary( library.nodes, 'library_nodes', 'node', parseNode );
+		parseLibrary( library.visualScenes, 'library_visual_scenes', 'visual_scene', parseVisualScene );
+
+		console.timeEnd( 'ColladaLoader: Parse' );
+
+		console.time( 'ColladaLoader: Build' );
+
+		buildLibrary( library.images, buildImage );
+		// buildLibrary( library.effects, buildEffect );
+		buildLibrary( library.cameras, buildCamera );
+		buildLibrary( library.lights, buildLight );
+		buildLibrary( library.geometries, buildGeometry );
+		buildLibrary( library.nodes, buildNode );
+		buildLibrary( library.visualScenes, buildVisualScene );
+
+		console.timeEnd( 'ColladaLoader: Build' );
+
+		// console.log( library );
 
 
 		var scene = parseScene( xml );
 		var scene = parseScene( xml );