Browse Source

Implemented simple forward facing animation type for Catmull-Rom splines.

Gah, that was painful. Obvious solution with object.lookAt doesn't work, forward facing direction (heading and attitude) is fine, but banking gets messed up:( Tried many fixes, none worked, so I just resorted to simple rotation around Y-axis based on direction vector.
alteredq 14 years ago
parent
commit
e7ab9e58a2
4 changed files with 40 additions and 15 deletions
  1. 7 5
      build/Three.js
  2. 31 9
      src/animation/Animation.js
  3. 1 1
      src/animation/AnimationHandler.js
  4. 1 0
      src/core/Matrix4.js

+ 7 - 5
build/Three.js

@@ -66,14 +66,16 @@ THREE.Spline=function(){function a(u,t,y,A,F,v,E){u=(y-u)*0.5;A=(A-t)*0.5;return
 THREE.AnimationHandler=function(){var a=[],c={},b={};b.update=function(e){for(var g=0;g<a.length;g++)a[g].update(e)};b.addToUpdate=function(e){a.indexOf(e)===-1&&a.push(e)};b.removeFromUpdate=function(e){e=a.indexOf(e);e!==-1&&a.splice(e,1)};b.add=function(e){c[e.name]!==undefined&&console.log("THREE.AnimationHandler.add: Warning! "+e.name+" already exists in library. Overwriting.");c[e.name]=e;if(e.initialized!==!0){for(var g=0;g<e.hierarchy.length;g++){for(var h=0;h<e.hierarchy[g].keys.length;h++){if(e.hierarchy[g].keys[h].time<
 0)e.hierarchy[g].keys[h].time=0;if(e.hierarchy[g].keys[h].rot!==undefined&&!(e.hierarchy[g].keys[h].rot instanceof THREE.Quaternion)){var j=e.hierarchy[g].keys[h].rot;e.hierarchy[g].keys[h].rot=new THREE.Quaternion(j[0],j[1],j[2],j[3])}}for(h=1;h<e.hierarchy[g].keys.length;h++)if(e.hierarchy[g].keys[h].time===e.hierarchy[g].keys[h-1].time){e.hierarchy[g].keys.splice(h,1);h--}for(h=1;h<e.hierarchy[g].keys.length;h++)e.hierarchy[g].keys[h].index=h}h=parseInt(e.length*e.fps,10);e.JIT={};e.JIT.hierarchy=
 [];for(g=0;g<e.hierarchy.length;g++)e.JIT.hierarchy.push(Array(h));e.initialized=!0}};b.get=function(e){if(typeof e==="string")if(c[e])return c[e];else{console.log("THREE.AnimationHandler.get: Couldn't find animation "+e);return null}};b.parse=function(e){var g=[];if(e instanceof THREE.SkinnedMesh)for(var h=0;h<e.bones.length;h++)g.push(e.bones[h]);else d(e,g);return g};var d=function(e,g){g.push(e);for(var h=0;h<e.children.length;h++)d(e.children[h],g)};b.LINEAR=0;b.CATMULLROM=1;b.CATMULLROM_FORWARD=
-2;return b}();THREE.Animation=function(a,c,b,d){this.root=a;this.data=THREE.AnimationHandler.get(c);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.isPlaying=!1;this.isPaused=!0;this.loop=!0;this.interpolationType=b!==undefined?b:THREE.AnimationHandler.LINEAR;this.JITCompile=d!==undefined?d:!0;this.points=[]};
-THREE.Animation.prototype.play=function(a,c){if(!this.isPlaying){this.isPlaying=!0;this.loop=a!==undefined?a:!0;this.currentTime=c!==undefined?c:0;var b,d=this.hierarchy.length,e;for(b=0;b<d;b++){e=this.hierarchy[b];e.useQuaternion=!0;e.matrixAutoUpdate=!0;if(e.animationCache===undefined){e.animationCache={};e.animationCache.prevKey={pos:0,rot:0,scl:0};e.animationCache.nextKey={pos:0,rot:0,scl:0};e.animationCache.originalMatrix=e instanceof THREE.Bone?e.skinMatrix:e.matrix}var g=e.animationCache.prevKey;
-e=e.animationCache.nextKey;g.pos=this.data.hierarchy[b].keys[0];g.rot=this.data.hierarchy[b].keys[0];g.scl=this.data.hierarchy[b].keys[0];e.pos=this.getNextKeyWith("pos",b,1);e.rot=this.getNextKeyWith("rot",b,1);e.scl=this.getNextKeyWith("scl",b,1)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};THREE.Animation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
+2;return b}();THREE.Animation=function(a,c,b,d){this.root=a;this.data=THREE.AnimationHandler.get(c);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.isPlaying=!1;this.isPaused=!0;this.loop=!0;this.interpolationType=b!==undefined?b:THREE.AnimationHandler.LINEAR;this.JITCompile=d!==undefined?d:!0;this.points=[];this.target=new THREE.Vector3};
+THREE.Animation.prototype.play=function(a,c){if(!this.isPlaying){this.isPlaying=!0;this.loop=a!==undefined?a:!0;this.currentTime=c!==undefined?c:0;var b,d=this.hierarchy.length,e;for(b=0;b<d;b++){e=this.hierarchy[b];if(this.interpolationType!==THREE.AnimationHandler.CATMULLROM_FORWARD)e.useQuaternion=!0;e.matrixAutoUpdate=!0;if(e.animationCache===undefined){e.animationCache={};e.animationCache.prevKey={pos:0,rot:0,scl:0};e.animationCache.nextKey={pos:0,rot:0,scl:0};e.animationCache.originalMatrix=
+e instanceof THREE.Bone?e.skinMatrix:e.matrix}var g=e.animationCache.prevKey;e=e.animationCache.nextKey;g.pos=this.data.hierarchy[b].keys[0];g.rot=this.data.hierarchy[b].keys[0];g.scl=this.data.hierarchy[b].keys[0];e.pos=this.getNextKeyWith("pos",b,1);e.rot=this.getNextKeyWith("rot",b,1);e.scl=this.getNextKeyWith("scl",b,1)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};
+THREE.Animation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
 THREE.Animation.prototype.stop=function(){this.isPlaying=!1;THREE.AnimationHandler.removeFromUpdate(this);for(var a=0;a<this.hierarchy.length;a++)if(this.hierarchy[a].animationCache!==undefined){if(this.hierarchy[a]instanceof THREE.Bone)this.hierarchy[a].skinMatrix=this.hierarchy[a].animationCache.originalMatrix;else this.hierarchy[a].matrix=this.hierarchy[a].animationCache.originalMatrix;delete this.hierarchy[a].animationCache}};
 THREE.Animation.prototype.update=function(a){if(this.isPlaying){var c=["pos","rot","scl"],b,d,e,g,h,j,k,n,q=this.data.JIT.hierarchy,x,u;this.currentTime+=a;u=this.currentTime;x=this.currentTime%=this.data.length;n=parseInt(Math.min(x*this.data.fps,this.data.length*this.data.fps),10);for(var t=0,y=this.hierarchy.length;t<y;t++){a=this.hierarchy[t];k=a.animationCache;if(this.JITCompile&&q[t][n]!==undefined)if(a instanceof THREE.Bone){a.skinMatrix=q[t][n];a.matrixAutoUpdate=!1;a.matrixWorldNeedsUpdate=
 !1}else{a.matrix=q[t][n];a.matrixAutoUpdate=!1;a.matrixWorldNeedsUpdate=!0}else{if(this.JITCompile)if(a instanceof THREE.Bone)a.skinMatrix=a.animationCache.originalMatrix;else a.matrix=a.animationCache.originalMatrix;for(var A=0;A<3;A++){b=c[A];h=k.prevKey[b];j=k.nextKey[b];if(j.time<=u){if(x<u)if(this.loop){h=this.data.hierarchy[t].keys[0];for(j=this.getNextKeyWith(b,t,1);j.time<x;){h=j;j=this.getNextKeyWith(b,t,j.index+1)}}else{this.stop();return}else{do{h=j;j=this.getNextKeyWith(b,t,j.index+1)}while(j.time<
-x)}k.prevKey[b]=h;k.nextKey[b]=j}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(x-h.time)/(j.time-h.time);e=h[b];g=j[b];if(d<0||d>1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+t);d=d<0?0:1}if(b==="pos"){b=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){b.x=e[0]+(g[0]-e[0])*d;b.y=e[1]+(g[1]-e[1])*d;b.z=e[2]+(g[2]-e[2])*d}else{this.points[0]=this.getPrevKeyWith("pos",t,h.index-1).pos;this.points[1]=e;this.points[2]=g;this.points[3]=
-this.getNextKeyWith("pos",t,j.index+1).pos;d=d*0.33+0.33;d=this.interpolateCatmullRom(this.points,d);b.x=d[0];b.y=d[1];b.z=d[2]}}else if(b==="rot")THREE.Quaternion.slerp(e,g,a.quaternion,d);else if(b==="scl"){b=a.scale;b.x=e[0]+(g[0]-e[0])*d;b.y=e[1]+(g[1]-e[1])*d;b.z=e[2]+(g[2]-e[2])*d}}}}if(this.JITCompile&&q[0][n]===undefined){this.hierarchy[0].update(undefined,!0);for(t=0;t<this.hierarchy.length;t++)q[t][n]=this.hierarchy[t]instanceof THREE.Bone?this.hierarchy[t].skinMatrix.clone():this.hierarchy[t].matrix.clone()}}};
+x)}k.prevKey[b]=h;k.nextKey[b]=j}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(x-h.time)/(j.time-h.time);e=h[b];g=j[b];if(d<0||d>1){console.log("THREE.Animation.update: Warning! Scale out of bounds:"+d+" on bone "+t);d=d<0?0:1}if(b==="pos"){b=a.position;if(this.interpolationType===THREE.AnimationHandler.LINEAR){b.x=e[0]+(g[0]-e[0])*d;b.y=e[1]+(g[1]-e[1])*d;b.z=e[2]+(g[2]-e[2])*d}else if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){this.points[0]=
+this.getPrevKeyWith("pos",t,h.index-1).pos;this.points[1]=e;this.points[2]=g;this.points[3]=this.getNextKeyWith("pos",t,j.index+1).pos;d=d*0.33+0.33;e=this.interpolateCatmullRom(this.points,d);b.x=e[0];b.y=e[1];b.z=e[2];if(this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD){d=this.interpolateCatmullRom(this.points,d*1.01);this.target.set(d[0],d[1],d[2]);this.target.subSelf(b);this.target.y=0;this.target.normalize();d=Math.atan2(this.target.x,this.target.z);a.rotation.set(0,d,0)}}}else if(b===
+"rot")THREE.Quaternion.slerp(e,g,a.quaternion,d);else if(b==="scl"){b=a.scale;b.x=e[0]+(g[0]-e[0])*d;b.y=e[1]+(g[1]-e[1])*d;b.z=e[2]+(g[2]-e[2])*d}}}}if(this.JITCompile&&q[0][n]===undefined){this.hierarchy[0].update(undefined,!0);for(t=0;t<this.hierarchy.length;t++)q[t][n]=this.hierarchy[t]instanceof THREE.Bone?this.hierarchy[t].skinMatrix.clone():this.hierarchy[t].matrix.clone()}}};
 THREE.Animation.prototype.interpolateCatmullRom=function(a,c){var b=[],d=[],e,g,h,j,k,n;e=(a.length-1)*c;g=Math.floor(e);e-=g;b[0]=g==0?g:g-1;b[1]=g;b[2]=g>a.length-2?g:g+1;b[3]=g>a.length-3?g:g+2;g=a[b[0]];j=a[b[1]];k=a[b[2]];n=a[b[3]];b=e*e;h=e*b;d[0]=this.interpolate(g[0],j[0],k[0],n[0],e,b,h);d[1]=this.interpolate(g[1],j[1],k[1],n[1],e,b,h);d[2]=this.interpolate(g[2],j[2],k[2],n[2],e,b,h);return d};
 THREE.Animation.prototype.interpolate=function(a,c,b,d,e,g,h){a=(b-a)*0.5;d=(d-c)*0.5;return(2*(c-b)+a+d)*h+(-3*(c-b)-2*a-d)*g+a*e+c};THREE.Animation.prototype.getNextKeyWith=function(a,c,b){var d=this.data.hierarchy[c].keys;if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)b=b<d.length-1?b:d.length-1;else b%=d.length;for(;b<d.length;b++)if(d[b][a]!==undefined)return d[b];return this.data.hierarchy[c].keys[0]};
 THREE.Animation.prototype.getPrevKeyWith=function(a,c,b){var d=this.data.hierarchy[c].keys;for(b=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?b>0?b:0:b>=0?b:b+d.length;b>=0;b--)if(d[b][a]!==undefined)return d[b];return this.data.hierarchy[c].keys[d.length-1]};

+ 31 - 9
src/animation/Animation.js

@@ -1,6 +1,7 @@
 /**
  * @author mikael emtinger / http://gomo.se/
  * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
  */
 
 THREE.Animation = function( root, data, interpolationType, JITCompile ) {
@@ -16,6 +17,7 @@ THREE.Animation = function( root, data, interpolationType, JITCompile ) {
 	this.JITCompile = JITCompile !== undefined ? JITCompile : true;
 
 	this.points = [];
+	this.target = new THREE.Vector3();
 
 };
 
@@ -39,7 +41,12 @@ THREE.Animation.prototype.play = function( loop, startTimeMS ) {
 
 			object = this.hierarchy[ h ];
 			
-			object.useQuaternion    = true;
+			if ( this.interpolationType !== THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+
+				object.useQuaternion = true;
+
+			}
+			
 			object.matrixAutoUpdate = true;
 
 			if ( object.animationCache === undefined ) {
@@ -151,6 +158,7 @@ THREE.Animation.prototype.update = function( deltaTimeMS ) {
 	var frame;
 	var JIThierarchy = this.data.JIT.hierarchy;
 	var currentTime, unloopedCurrentTime;
+	var currentPoint, forwardPoint, angle;
 	
 
 	// update
@@ -285,7 +293,7 @@ THREE.Animation.prototype.update = function( deltaTimeMS ) {
 
 				if ( type === "pos" ) {
 
-					vector  = object.position; 
+					vector = object.position; 
 
 					if( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
 						
@@ -293,7 +301,8 @@ THREE.Animation.prototype.update = function( deltaTimeMS ) {
 						vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
 						vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
 
-					} else {						
+					} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+							    this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {						
 		
 						this.points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
 						this.points[ 1 ] = prevXYZ;
@@ -302,11 +311,25 @@ THREE.Animation.prototype.update = function( deltaTimeMS ) {
 
 						scale = scale * 0.33 + 0.33;
 
-						var result = this.interpolateCatmullRom( this.points, scale );
+						currentPoint = this.interpolateCatmullRom( this.points, scale );
 						
-						vector.x = result[ 0 ];
-						vector.y = result[ 1 ];
-						vector.z = result[ 2 ];
+						vector.x = currentPoint[ 0 ];
+						vector.y = currentPoint[ 1 ];
+						vector.z = currentPoint[ 2 ];
+						
+						if( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+							
+							forwardPoint = this.interpolateCatmullRom( this.points, scale * 1.01 );							
+							
+							this.target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
+							this.target.subSelf( vector );
+							this.target.y = 0;
+							this.target.normalize();
+							
+							angle = Math.atan2( this.target.x, this.target.z );
+							object.rotation.set( 0, angle, 0 );
+							
+						}
 
 					}
 
@@ -316,7 +339,7 @@ THREE.Animation.prototype.update = function( deltaTimeMS ) {
 
 				} else if( type === "scl" ) {
 
-					vector   = object.scale;
+					vector = object.scale;
 					
 					vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
 					vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
@@ -391,7 +414,6 @@ THREE.Animation.prototype.interpolateCatmullRom = function ( points, scale ) {
 
 };
 
-
 THREE.Animation.prototype.interpolate = function( p0, p1, p2, p3, t, t2, t3 ) {
 
 	var v0 = ( p2 - p0 ) * 0.5,

+ 1 - 1
src/animation/AnimationHandler.js

@@ -199,7 +199,7 @@ THREE.AnimationHandler = (function() {
 	};
 
 
-	// interpolation typess
+	// interpolation types
 
 	that.LINEAR = 0;
 	that.CATMULLROM = 1;

+ 1 - 0
src/core/Matrix4.js

@@ -76,6 +76,7 @@ THREE.Matrix4.prototype = {
 		if ( z.length() === 0 ) {
 			
 			z.z = 1;
+
 		}
 		
 		x.cross( up, z ).normalize();