Jelajahi Sumber

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 tahun lalu
induk
melakukan
1dacb71d88
2 mengubah file dengan 175 tambahan dan 42 penghapusan
  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 ) {