Browse Source

avoid clones while interpolating values.

Ben Houston 10 years ago
parent
commit
281f51051c
3 changed files with 51 additions and 9 deletions
  1. 15 2
      src/animation/AnimationUtils.js
  2. 30 5
      src/animation/KeyframeTrack.js
  3. 6 2
      src/animation/PropertyBinding.js

+ 15 - 2
src/animation/AnimationUtils.js

@@ -19,6 +19,19 @@
 
 	},
 
+ 	clone: function( exemplarValue ) {
+
+ 		var typeName = typeof exemplarValue;
+		if( typeName === "object" ) {
+			if( exemplarValue.clone ) {
+				return exemplarValue.clone();
+			}
+			console.error( "can not figure out how to copy exemplarValue", exemplarValue );
+		}
+
+		return exemplarValue;
+
+	},
 
  	lerp: function( a, b, alpha, interTrack ) {
 
@@ -41,7 +54,7 @@
 
 					return function( a, b, alpha ) {
 						//console.log( a, b );
-						return a.clone().lerp( b, alpha );
+						return a.lerp( b, alpha );
 					}
 
 				}
@@ -49,7 +62,7 @@
 
 					return function( a, b, alpha ) {
 						//console.log( a, b );
-						return a.clone().slerp( b, alpha );
+						return a.slerp( b, alpha );
 					}
 
 				}

+ 30 - 5
src/animation/KeyframeTrack.js

@@ -11,7 +11,11 @@
 THREE.KeyframeTrack = function ( name, keys ) {
 
 	this.name = name;
-	this.keys = keys || [];	// time in seconds, value as value
+	this.keys = keys;	// time in seconds, value as value
+
+	// local cache of value type to avoid allocations during runtime.
+	this.result = THREE.AnimationUtils.clone( this.keys[0].value );
+	//console.log( 'constructor result', this.result )
 
 	this.sort();
 	this.validate();
@@ -22,6 +26,8 @@ THREE.KeyframeTrack.prototype = {
 
 	constructor: THREE.KeyframeTrack,
 
+	// TODO: this is a straight forward linear search for the key that corresponds to this time, this
+	//    should be optimized.
 	getAt: function( time ) {
 		//console.log( 'KeyframeTrack[' + this.name + '].getAt( ' + time + ' )' );
 
@@ -32,7 +38,11 @@ THREE.KeyframeTrack.prototype = {
 		if( this.keys[0].time >= time ) {
 
 			//console.log( '   before: ' + this.keys[0].value );
-			return this.keys[0].value;
+			this.setResult( this.keys[0].value );
+
+			//console.log( 'first result', this.result )
+
+			return this.result;
 
 		}
 
@@ -40,11 +50,16 @@ THREE.KeyframeTrack.prototype = {
 		if( this.keys[ this.keys.length - 1 ].time <= time ) {
 
 			//console.log( '   after: ' + this.keys[ this.keys.length - 1 ].value );
-			return this.keys[ this.keys.length - 1 ].value;
+			this.setResult( this.keys[ this.keys.length - 1 ].value );
+
+			//console.log( 'last result', this.result )
+
+			return this.result;
 
 		}
 
 		// interpolate to the required time
+		// TODO: Optimize this better than a linear search for each key.
 		for( var i = 1; i < this.keys.length; i ++ ) {
 
 			if( time <= this.keys[ i ].time ) {
@@ -52,8 +67,10 @@ THREE.KeyframeTrack.prototype = {
 				// linear interpolation to start with
 				var alpha = ( time - this.keys[ i - 1 ].time ) / ( this.keys[ i ].time - this.keys[ i - 1 ].time );
 
-				var interpolatedValue = this.lerp( this.keys[ i - 1 ].value, this.keys[ i ].value, alpha );
+				this.setResult( this.keys[ i - 1 ].value );
 
+				this.result = this.lerp( this.result, this.keys[ i ].value, alpha );
+				//console.log( 'lerp result', this.result )
 				/*console.log( '   interpolated: ', {
 					value: interpolatedValue, 
 					alpha: alpha,
@@ -63,7 +80,7 @@ THREE.KeyframeTrack.prototype = {
 					value1: this.keys[ i ].value
 				} );*/
 
-				return interpolatedValue;
+				return this.result;
 
 			}
 		}
@@ -71,6 +88,14 @@ THREE.KeyframeTrack.prototype = {
 		throw new Error( "should never get here." );
 
 	},
+	setResult: function( value ) {
+		if( this.result.copy ) {
+			this.result.copy( value );
+		}
+		else {
+			this.result = value;
+		}
+	},
 
 	// memoization of the lerp function for speed.
 	// NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.

+ 6 - 2
src/animation/PropertyBinding.js

@@ -46,15 +46,19 @@ THREE.PropertyBinding.prototype = {
 
 			if( this.cumulativeWeight === 0 ) {
 
-				this.cumulativeValue = value;
+				if( this.cumulativeValue === null ) {
+					this.cumulativeValue = THREE.AnimationUtils.clone( value );
+				}
 				this.cumulativeWeight = weight;
-
+				//console.log( this );
+	
 			}
 			else {
 
 				var lerpAlpha = weight / ( this.cumulativeWeight + weight );
 				this.cumulativeValue = lerp( this.cumulativeValue, value, lerpAlpha );
 				this.cumulativeWeight += weight;
+				//console.log( this );
 
 			}
 		}