瀏覽代碼

Minor optimizations and tweaks to make it a better example. Removed extraneous work in setting up the animation loop. Added support for array-style target addressing according to COLLADA spec. Added support for matrix transform updates. Added support for hierarchical animations as defined in COLLADA spec (Credit to ekitson).

John Pywtorak 13 年之前
父節點
當前提交
1dacb71d88
共有 2 個文件被更改,包括 175 次插入42 次删除
  1. 36 36
      examples/webgl_loader_collada_keyframe.html
  2. 139 6
      src/extras/loaders/ColladaLoader.js

+ 36 - 36
examples/webgl_loader_collada_keyframe.html

@@ -44,27 +44,24 @@
 
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 
-			var container,
-				stats,
-				camera,
-				scene,
-				renderer,
-				pointLight,
-				model,
-				animations,
-				kfAnimations = [ ],
-				loader = new THREE.ColladaLoader(),
-				lastTimestamp,
-				startTime,
-				progress = 0;
+			var stats;
+			var scene;
+			var camera;
+			var renderer;
+			var model;
+			var animations;
+			var kfAnimations = [ ];
+			var kfAnimationsLength = 0;
+			var loader = new THREE.ColladaLoader();
+			var lastTimestamp;
+			var progress = 0;
 
 			loader.load( './models/collada/pump/pump.dae', function ( collada ) {
 
 				model = collada.scene;
 				animations = collada.animations;
-
-				model.scale.x = model.scale.y = model.scale.z = 0.125;
-				model.updateMatrix();
+				kfAnimationsLength = animations.length;
+				model.scale.x = model.scale.y = model.scale.z = 0.125; // 1/8 scale, modeled in cm
 
 				init();
 				start();
@@ -74,14 +71,15 @@
 
 			function init() {
 
-				container = document.createElement( 'div' );
+				var container = document.createElement( 'div' );
 				document.body.appendChild( container );
 
-				model.getChildByName( 'camEye_camera', true ).visible = false;
-				model.getChildByName( 'camTarget_camera', true ).visible = false;
+				// Scene
 
 				scene = new THREE.Scene();
 
+				// Camera
+
 				camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.01, 1000 );
 				camera.position.set( -5.00181875, 3.42631375, 11.3102925 );
 				camera.lookAt( new THREE.Vector3( -1.224774125, 2.18410625, 4.57969125 ) );
@@ -90,21 +88,17 @@
 
 				// KeyFrame Animations
 
-				var animHandler = THREE.AnimationHandler,
-					toConvert = { };
+				var animHandler = THREE.AnimationHandler;
 
-				for ( var i = 0, il = animations.length; i < il; ++i ) {
-					var node = animations[ i ].node;
-					toConvert[ node.id ] = node;
-				}
+				for ( var i = 0; i < kfAnimationsLength; ++i ) {
 
-				for ( var i = 0, il = animations.length; i < il; ++i ) {
 					var animation = animations[ i ];
 					animHandler.add( animation );
 
-					var kfAnimation = new THREE.KeyFrameAnimation( toConvert[ animation.node.id ], animation.name );
+					var kfAnimation = new THREE.KeyFrameAnimation( animation.node, animation.name );
 					kfAnimation.timeScale = 1;
 					kfAnimations.push( kfAnimation );
+
 				}
 
 				// Grid
@@ -127,20 +121,25 @@
 
 				// Add the COLLADA
 
+				model.getChildByName( 'camEye_camera', true ).visible = false;
+				model.getChildByName( 'camTarget_camera', true ).visible = false;
+
 				scene.add( model );
 
 				// Lights
 
-				pointLight = new THREE.PointLight( 0xffffff, 1.5 );
+				pointLight = new THREE.PointLight( 0xffffff, 1.75 );
 				pointLight.position = camera.position;
 				pointLight.rotation = camera.rotation;
 				pointLight.scale = camera.scale;
+
 				scene.add( pointLight );
 
 				// Renderer
 
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+
 				container.appendChild( renderer.domElement );
 
 				// Stats
@@ -148,28 +147,29 @@
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.top = '0px';
+
 				container.appendChild( stats.domElement );
 
 			}
 
 			function start() {
 
-				for ( var i = 0, il = kfAnimations.length; i < il; ++i ) {
+				for ( var i = 0; i < kfAnimationsLength; ++i ) {
 
 					var animation = kfAnimations[i];
 
 					for ( var h = 0, hl = animation.hierarchy.length; h < hl; h++ ) {
 
-						var keys = animation.data.hierarchy[ h ].keys,
-						sids = animation.data.hierarchy[ h ].sids,
-						obj = animation.hierarchy[ h ];
+						var keys = animation.data.hierarchy[ h ].keys;
+						var sids = animation.data.hierarchy[ h ].sids;
+						var obj = animation.hierarchy[ h ];
 
 						if ( keys.length && sids ) {
 
 							for ( var s = 0; s < sids.length; s++ ) {
 
-								var sid = sids[ s ],
-								next = animation.getNextKeyWith( sid, h, 0 );
+								var sid = sids[ s ];
+								var next = animation.getNextKeyWith( sid, h, 0 );
 
 								if ( next ) next.apply( sid );
 
@@ -196,7 +196,7 @@
 
 				if ( progress >= 0 && progress < 48 ) {
 
-					for ( var i = 0, il = kfAnimations.length; i < il; ++i ) {
+					for ( var i = 0; i < kfAnimationsLength; ++i ) {
 
 						kfAnimations[ i ].update( frameTime );
 
@@ -204,7 +204,7 @@
 
 				} else if ( progress >= 48 ) {
 
-					for ( var i = 0, il = kfAnimations.length; i < il; ++i ) {
+					for ( var i = 0; i < kfAnimationsLength; ++i ) {
 
 						kfAnimations[ i ].stop();
 

+ 139 - 6
src/extras/loaders/ColladaLoader.js

@@ -1003,10 +1003,26 @@ THREE.ColladaLoader = function () {
 
 				var channel = node.channels[i],
 					fullSid = channel.fullSid,
-					member = getConvertedMember( channel.member ),
 					sampler = channel.sampler,
 					input = sampler.input,
-					transform = node.getTransformBySid( channel.sid );
+					transform = node.getTransformBySid( channel.sid ),
+					member;
+
+				if ( channel.arrIndices ) {
+
+					member = [];
+
+					for ( var j = 0, jl = channel.arrIndices.length; j < jl; j++ ) {
+
+						member[ j ] = getConvertedIndex( channel.arrIndices[ j ] );
+
+					}
+
+				} else {
+
+					member = getConvertedMember( channel.member );
+
+				}
 
 				if ( transform ) {
 
@@ -1125,7 +1141,11 @@ THREE.ColladaLoader = function () {
 				prevData = prevTarget.data,
 				data;
 
-			if ( prevData.length ) {
+			if ( prevTarget.type === 'matrix' ) {
+
+				data = prevData;
+
+			} else if ( prevData.length ) {
 
 				data = [];
 
@@ -1927,16 +1947,80 @@ THREE.ColladaLoader = function () {
 
 	Transform.prototype.update = function ( data, member ) {
 
+		var members = [ 'X', 'Y', 'Z', 'ANGLE' ];
+
 		switch ( this.type ) {
 
 			case 'matrix':
 
-				console.log( 'Currently not handling matrix transform updates' );
+				if ( ! member ) {
+
+					this.obj.copy( data );
+
+				} else if ( member.length === 1 ) {
+
+					switch ( member[ 0 ] ) {
+
+						case 0:
+
+							this.obj.n11 = data[ 0 ];
+							this.obj.n21 = data[ 1 ];
+							this.obj.n31 = data[ 2 ];
+							this.obj.n41 = data[ 3 ];
+
+							break;
+
+						case 1:
+
+							this.obj.n12 = data[ 0 ];
+							this.obj.n22 = data[ 1 ];
+							this.obj.n32 = data[ 2 ];
+							this.obj.n42 = data[ 3 ];
+
+							break;
+
+						case 2:
+
+							this.obj.n13 = data[ 0 ];
+							this.obj.n23 = data[ 1 ];
+							this.obj.n33 = data[ 2 ];
+							this.obj.n43 = data[ 3 ];
+
+							break;
+
+						case 3:
+
+							this.obj.n14 = data[ 0 ];
+							this.obj.n24 = data[ 1 ];
+							this.obj.n34 = data[ 2 ];
+							this.obj.n44 = data[ 3 ];
+
+							break;
+
+					}
+
+				} else if ( member.length === 2 ) {
+
+					var propName = 'n' + ( member[ 0 ] + 1 ) + ( member[ 1 ] + 1 );
+					this.obj[ propName ] = data;
+					
+				} else {
+
+					console.log('Incorrect addressing of matrix in transform.');
+
+				}
+
 				break;
 
 			case 'translate':
 			case 'scale':
 
+				if ( Object.prototype.toString.call( member ) === '[object Array]' ) {
+
+					member = members[ member[ 0 ] ];
+
+				}
+
 				switch ( member ) {
 
 					case 'X':
@@ -1967,6 +2051,12 @@ THREE.ColladaLoader = function () {
 
 			case 'rotate':
 
+				if ( Object.prototype.toString.call( member ) === '[object Array]' ) {
+
+					member = members[ member[ 0 ] ];
+
+				}
+
 				switch ( member ) {
 
 					case 'X':
@@ -3329,6 +3419,25 @@ THREE.ColladaLoader = function () {
 
 			switch ( child.nodeName ) {
 
+				case 'animation':
+
+					var anim = ( new Animation() ).parse( child );
+
+					for ( var src in anim.source ) {
+
+						this.source[ src ] = anim.source[ src ];
+
+					}
+
+					for ( var j = 0; j < anim.channel.length; j ++ ) {
+
+						this.channel.push( anim.channel[ j ] );
+						this.sampler.push( anim.sampler[ j ] );
+
+					}
+
+					break;
+
 				case 'source':
 
 					var src = ( new Source() ).parse( child );
@@ -3527,7 +3636,11 @@ THREE.ColladaLoader = function () {
 
 		var data;
 
-		if ( this.strideOut > 1 ) {
+		if ( type === 'matrix' && this.strideOut === 16 ) {
+
+			data = this.output[ ndx ];
+
+		} else if ( this.strideOut > 1 ) {
 
 			data = [];
 			ndx *= this.strideOut;
@@ -3555,6 +3668,10 @@ THREE.ColladaLoader = function () {
 
 				}
 
+			} else if ( this.strideOut === 4 && type === 'matrix' ) {
+
+				fixCoords( data, -1 );
+
 			}
 
 		} else {
@@ -3642,7 +3759,7 @@ THREE.ColladaLoader = function () {
 				nextTarget = nextKey.getTarget( target.sid ),
 				data;
 
-			if ( nextTarget ) {
+			if ( target.transform.type !== 'matrix' && nextTarget ) {
 
 				var scale = ( time - this.time ) / ( nextKey.time - this.time ),
 					nextData = nextTarget.data,
@@ -4150,6 +4267,22 @@ THREE.ColladaLoader = function () {
 
 	};
 
+	function getConvertedIndex( index ) {
+
+		if ( index > -1 && index < 3 ) {
+
+			var members = ['X', 'Y', 'Z'],
+				indices = { X: 0, Y: 1, Z: 2 };
+
+			index = getConvertedMember( members[ index ] );
+			index = indices[ index ];
+
+		}
+
+		return index;
+		
+	};
+
 	function getConvertedMember( member ) {
 
 		if ( options.convertUpAxis ) {