Browse Source

*Animation: Clean up.

Mr.doob 10 years ago
parent
commit
498475b292

+ 223 - 220
src/extras/animation/Animation.js

@@ -21,383 +21,386 @@ THREE.Animation = function ( root, data ) {
 
 };
 
+THREE.Animation.prototype = {
 
-THREE.Animation.prototype.keyTypes = [ "pos", "rot", "scl" ];
+	constructor: THREE.Animation,
 
+	keyTypes:  [ "pos", "rot", "scl" ],
 
-THREE.Animation.prototype.play = function ( startTime, weight ) {
+	play: function ( startTime, weight ) {
 
-	this.currentTime = startTime !== undefined ? startTime : 0;
-	this.weight = weight !== undefined ? weight : 1;
+		this.currentTime = startTime !== undefined ? startTime : 0;
+		this.weight = weight !== undefined ? weight : 1;
 
-	this.isPlaying = true;
+		this.isPlaying = true;
 
-	this.reset();
+		this.reset();
 
-	THREE.AnimationHandler.play( this );
+		THREE.AnimationHandler.play( this );
 
-};
+	},
 
+	stop: function() {
 
-THREE.Animation.prototype.stop = function() {
+		this.isPlaying = false;
 
-	this.isPlaying = false;
+		THREE.AnimationHandler.stop( this );
 
-	THREE.AnimationHandler.stop( this );
+	},
 
-};
+	reset: function () {
 
-THREE.Animation.prototype.reset = function () {
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			var object = this.hierarchy[ h ];
 
-		var object = this.hierarchy[ h ];
+			if ( object.animationCache === undefined ) {
 
-		if ( object.animationCache === undefined ) {
+				object.animationCache = {
+					animations: {},
+					blending: {
+						positionWeight: 0.0,
+						quaternionWeight: 0.0,
+						scaleWeight: 0.0
+					}
+				};
+			}
 
-			object.animationCache = {
-				animations: {},
-				blending: {
-					positionWeight: 0.0,
-					quaternionWeight: 0.0,
-					scaleWeight: 0.0
-				}
-			};
-		}
+			var name = this.data.name;
+			var animations = object.animationCache.animations;
+			var animationCache = animations[ name ];
 
-		if ( object.animationCache.animations[this.data.name] === undefined ) {
+			if ( animationCache === undefined ) {
 
-			object.animationCache.animations[this.data.name] = {};
-			object.animationCache.animations[this.data.name].prevKey = { pos: 0, rot: 0, scl: 0 };
-			object.animationCache.animations[this.data.name].nextKey = { pos: 0, rot: 0, scl: 0 };
-			object.animationCache.animations[this.data.name].originalMatrix = object.matrix;
+				animationCache = {
+					prevKey: { pos: 0, rot: 0, scl: 0 },
+					nextKey: { pos: 0, rot: 0, scl: 0 },
+					originalMatrix: object.matrix
+				};
 
-		}
+				animations[ name ] = animationCache;
 
-		var animationCache = object.animationCache.animations[this.data.name];
+			}
 
-		// Get keys to match our current time
+			// Get keys to match our current time
 
-		for ( var t = 0; t < 3; t ++ ) {
+			for ( var t = 0; t < 3; t ++ ) {
 
-			var type = this.keyTypes[ t ];
+				var type = this.keyTypes[ t ];
 
-			var prevKey = this.data.hierarchy[ h ].keys[ 0 ];
-			var nextKey = this.getNextKeyWith( type, h, 1 );
+				var prevKey = this.data.hierarchy[ h ].keys[ 0 ];
+				var nextKey = this.getNextKeyWith( type, h, 1 );
 
-			while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+				while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
-				prevKey = nextKey;
-				nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
+					prevKey = nextKey;
+					nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 
-			}
+				}
+
+				animationCache.prevKey[ type ] = prevKey;
+				animationCache.nextKey[ type ] = nextKey;
 
-			animationCache.prevKey[ type ] = prevKey;
-			animationCache.nextKey[ type ] = nextKey;
+			}
 
 		}
 
-	}
+	},
 
-};
+	resetBlendWeights: function () {
+
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
-THREE.Animation.prototype.resetBlendWeights = function () {
+			var object = this.hierarchy[ h ];
+			var animationCache = object.animationCache;
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			if ( animationCache !== undefined ) {
 
-		var object = this.hierarchy[ h ];
+				var blending = animationCache.blending;
 
-		if ( object.animationCache !== undefined ) {
+				blending.positionWeight = 0.0;
+				blending.quaternionWeight = 0.0;
+				blending.scaleWeight = 0.0;
 
-			object.animationCache.blending.positionWeight = 0.0;
-			object.animationCache.blending.quaternionWeight = 0.0;
-			object.animationCache.blending.scaleWeight = 0.0;
+			}
 
 		}
 
-	}
+	},
 
-};
+	update: ( function() {
 
-THREE.Animation.prototype.update = (function() {
+		var points = [];
+		var target = new THREE.Vector3();
+		var newVector = new THREE.Vector3();
+		var newQuat = new THREE.Quaternion();
 
-	var points = [];
-	var target = new THREE.Vector3();
-	var newVector = new THREE.Vector3();
-	var newQuat = new THREE.Quaternion();
+		// Catmull-Rom spline
 
-	// Catmull-Rom spline
+		var interpolateCatmullRom = function ( points, scale ) {
 
-	var interpolateCatmullRom = function ( points, scale ) {
+			var c = [], v3 = [],
+			point, intPoint, weight, w2, w3,
+			pa, pb, pc, pd;
 
-		var c = [], v3 = [],
-		point, intPoint, weight, w2, w3,
-		pa, pb, pc, pd;
+			point = ( points.length - 1 ) * scale;
+			intPoint = Math.floor( point );
+			weight = point - intPoint;
 
-		point = ( points.length - 1 ) * scale;
-		intPoint = Math.floor( point );
-		weight = point - intPoint;
+			c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
+			c[ 1 ] = intPoint;
+			c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
+			c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
 
-		c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
-		c[ 1 ] = intPoint;
-		c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
-		c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
+			pa = points[ c[ 0 ] ];
+			pb = points[ c[ 1 ] ];
+			pc = points[ c[ 2 ] ];
+			pd = points[ c[ 3 ] ];
 
-		pa = points[ c[ 0 ] ];
-		pb = points[ c[ 1 ] ];
-		pc = points[ c[ 2 ] ];
-		pd = points[ c[ 3 ] ];
+			w2 = weight * weight;
+			w3 = weight * w2;
 
-		w2 = weight * weight;
-		w3 = weight * w2;
+			v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
+			v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
+			v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
 
-		v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
-		v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
-		v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
+			return v3;
 
-		return v3;
+		};
 
-	};
+		var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
 
-	var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
+			var v0 = ( p2 - p0 ) * 0.5,
+				v1 = ( p3 - p1 ) * 0.5;
 
-		var v0 = ( p2 - p0 ) * 0.5,
-			v1 = ( p3 - p1 ) * 0.5;
+			return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
 
-		return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
+		};
 
-	};
+		return function ( delta ) {
 
-	return function ( delta ) {
+			if ( this.isPlaying === false ) return;
 
-		if ( this.isPlaying === false ) return;
+			this.currentTime += delta * this.timeScale;
 
-		this.currentTime += delta * this.timeScale;
+			if ( this.weight === 0 )
+				return;
 
-		if ( this.weight === 0 )
-			return;
+			//
 
-		//
+			var duration = this.data.length;
 
-		var duration = this.data.length;
+			if ( this.currentTime > duration || this.currentTime < 0 ) {
 
-		if ( this.currentTime > duration || this.currentTime < 0 ) {
+				if ( this.loop ) {
 
-			if ( this.loop ) {
+					this.currentTime %= duration;
 
-				this.currentTime %= duration;
+					if ( this.currentTime < 0 )
+						this.currentTime += duration;
 
-				if ( this.currentTime < 0 )
-					this.currentTime += duration;
+					this.reset();
 
-				this.reset();
+				} else {
 
-			} else {
+					this.stop();
 
-				this.stop();
+				}
 
 			}
 
-		}
+			for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
-		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+				var object = this.hierarchy[ h ];
+				var animationCache = object.animationCache.animations[this.data.name];
+				var blending = object.animationCache.blending;
 
-			var object = this.hierarchy[ h ];
-			var animationCache = object.animationCache.animations[this.data.name];
-			var blending = object.animationCache.blending;
+				// loop through pos/rot/scl
 
-			// loop through pos/rot/scl
+				for ( var t = 0; t < 3; t ++ ) {
 
-			for ( var t = 0; t < 3; t ++ ) {
+					// get keys
 
-				// get keys
+					var type    = this.keyTypes[ t ];
+					var prevKey = animationCache.prevKey[ type ];
+					var nextKey = animationCache.nextKey[ type ];
 
-				var type    = this.keyTypes[ t ];
-				var prevKey = animationCache.prevKey[ type ];
-				var nextKey = animationCache.nextKey[ type ];
+					if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) ||
+						( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) {
 
-				if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) ||
-					( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) {
+						prevKey = this.data.hierarchy[ h ].keys[ 0 ];
+						nextKey = this.getNextKeyWith( type, h, 1 );
 
-					prevKey = this.data.hierarchy[ h ].keys[ 0 ];
-					nextKey = this.getNextKeyWith( type, h, 1 );
+						while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
-					while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+							prevKey = nextKey;
+							nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 
-						prevKey = nextKey;
-						nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
+						}
+
+						animationCache.prevKey[ type ] = prevKey;
+						animationCache.nextKey[ type ] = nextKey;
 
 					}
 
-					animationCache.prevKey[ type ] = prevKey;
-					animationCache.nextKey[ type ] = nextKey;
+					var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
 
-				}
+					var prevXYZ = prevKey[ type ];
+					var nextXYZ = nextKey[ type ];
 
-				var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
+					if ( scale < 0 ) scale = 0;
+					if ( scale > 1 ) scale = 1;
 
-				var prevXYZ = prevKey[ type ];
-				var nextXYZ = nextKey[ type ];
+					// interpolate
 
-				if ( scale < 0 ) scale = 0;
-				if ( scale > 1 ) scale = 1;
+					if ( type === "pos" ) {
 
-				// interpolate
+						if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
 
-				if ( type === "pos" ) {
+							newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
+							newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
+							newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
 
-					if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
+							// blend
+							var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
+							object.position.lerp( newVector, proportionalWeight );
+							blending.positionWeight += this.weight;
 
-						newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
-						newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
-						newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
+						} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+									this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
-						// blend
-						var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
-						object.position.lerp( newVector, proportionalWeight );
-						blending.positionWeight += this.weight;
+							points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
+							points[ 1 ] = prevXYZ;
+							points[ 2 ] = nextXYZ;
+							points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
 
-					} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-								this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+							scale = scale * 0.33 + 0.33;
 
-						points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
-						points[ 1 ] = prevXYZ;
-						points[ 2 ] = nextXYZ;
-						points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
+							var currentPoint = interpolateCatmullRom( points, scale );
+							var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
+							blending.positionWeight += this.weight;
 
-						scale = scale * 0.33 + 0.33;
+							// blend
 
-						var currentPoint = interpolateCatmullRom( points, scale );
-						var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
-						blending.positionWeight += this.weight;
+							var vector = object.position;
 
-						// blend
+							vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight;
+							vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight;
+							vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight;
 
-						var vector = object.position;
-						
-						vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight;
-						vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight;
-						vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight;
+							if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
-						if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+								var forwardPoint = interpolateCatmullRom( points, scale * 1.01 );
 
-							var forwardPoint = interpolateCatmullRom( points, scale * 1.01 );
+								target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
+								target.sub( vector );
+								target.y = 0;
+								target.normalize();
 
-							target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
-							target.sub( vector );
-							target.y = 0;
-							target.normalize();
+								var angle = Math.atan2( target.x, target.z );
+								object.rotation.set( 0, angle, 0 );
 
-							var angle = Math.atan2( target.x, target.z );
-							object.rotation.set( 0, angle, 0 );
+							}
 
 						}
 
-					}
+					} else if ( type === "rot" ) {
 
-				} else if ( type === "rot" ) {
+						THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale );
 
-					THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale );
+						// Avoid paying the cost of an additional slerp if we don't have to
+						if ( blending.quaternionWeight === 0 ) {
 
-					// Avoid paying the cost of an additional slerp if we don't have to
-					if ( blending.quaternionWeight === 0 ) {
+							object.quaternion.copy(newQuat);
+							blending.quaternionWeight = this.weight;
 
-						object.quaternion.copy(newQuat);
-						blending.quaternionWeight = this.weight;
+						} else {
 
-					} else {
+							var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight );
+							THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight );
+							blending.quaternionWeight += this.weight;
 
-						var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight );
-						THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight );
-						blending.quaternionWeight += this.weight;
+						}
 
-					}
+					} else if ( type === "scl" ) {
 
-				} else if ( type === "scl" ) {
+						newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
+						newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
+						newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
 
-					newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
-					newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
-					newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
+						var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight );
+						object.scale.lerp( newVector, proportionalWeight );
+						blending.scaleWeight += this.weight;
 
-					var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight );
-					object.scale.lerp( newVector, proportionalWeight );
-					blending.scaleWeight += this.weight;
+					}
 
 				}
 
 			}
 
-		}
-
-		return true;
-
-	};
+			return true;
 
-})();
+		};
 
+	} )(),
 
+	getNextKeyWith: function ( type, h, key ) {
 
+		var keys = this.data.hierarchy[ h ].keys;
 
+		if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+			 this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
-// Get next key with
+			key = key < keys.length - 1 ? key : keys.length - 1;
 
-THREE.Animation.prototype.getNextKeyWith = function ( type, h, key ) {
+		} else {
 
-	var keys = this.data.hierarchy[ h ].keys;
+			key = key % keys.length;
 
-	if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-		 this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
-
-		key = key < keys.length - 1 ? key : keys.length - 1;
-
-	} else {
+		}
 
-		key = key % keys.length;
+		for ( ; key < keys.length; key ++ ) {
 
-	}
+			if ( keys[ key ][ type ] !== undefined ) {
 
-	for ( ; key < keys.length; key ++ ) {
+				return keys[ key ];
 
-		if ( keys[ key ][ type ] !== undefined ) {
-
-			return keys[ key ];
+			}
 
 		}
 
-	}
-
-	return this.data.hierarchy[ h ].keys[ 0 ];
+		return this.data.hierarchy[ h ].keys[ 0 ];
 
-};
+	},
 
-// Get previous key with
+	getPrevKeyWith: function ( type, h, key ) {
 
-THREE.Animation.prototype.getPrevKeyWith = function ( type, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
 
-	var keys = this.data.hierarchy[ h ].keys;
+		if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+			this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
-	if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-		this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+			key = key > 0 ? key : 0;
 
-		key = key > 0 ? key : 0;
+		} else {
 
-	} else {
+			key = key >= 0 ? key : key + keys.length;
 
-		key = key >= 0 ? key : key + keys.length;
+		}
 
-	}
 
+		for ( ; key >= 0; key -- ) {
 
-	for ( ; key >= 0; key -- ) {
+			if ( keys[ key ][ type ] !== undefined ) {
 
-		if ( keys[ key ][ type ] !== undefined ) {
+				return keys[ key ];
 
-			return keys[ key ];
+			}
 
 		}
 
-	}
+		return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
 
-	return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
+	}
 
 };

+ 98 - 101
src/extras/animation/KeyFrameAnimation.js

@@ -50,195 +50,192 @@ THREE.KeyFrameAnimation = function ( data ) {
 
 };
 
+THREE.KeyFrameAnimation.prototype = {
 
-THREE.KeyFrameAnimation.prototype.play = function ( startTime ) {
+	constructor: THREE.KeyFrameAnimation,
 
-	this.currentTime = startTime !== undefined ? startTime : 0;
+	play: function ( startTime ) {
 
-	if ( this.isPlaying === false ) {
+		this.currentTime = startTime !== undefined ? startTime : 0;
 
-		this.isPlaying = true;
+		if ( this.isPlaying === false ) {
 
-		// reset key cache
+			this.isPlaying = true;
 
-		var h, hl = this.hierarchy.length,
-			object,
-			node;
+			// reset key cache
 
-		for ( h = 0; h < hl; h ++ ) {
+			var h, hl = this.hierarchy.length,
+				object,
+				node;
 
-			object = this.hierarchy[ h ];
-			node = this.data.hierarchy[ h ];
+			for ( h = 0; h < hl; h ++ ) {
 
-			if ( node.animationCache === undefined ) {
+				object = this.hierarchy[ h ];
+				node = this.data.hierarchy[ h ];
 
-				node.animationCache = {};
-				node.animationCache.prevKey = null;
-				node.animationCache.nextKey = null;
-				node.animationCache.originalMatrix = object.matrix;
+				if ( node.animationCache === undefined ) {
 
-			}
+					node.animationCache = {};
+					node.animationCache.prevKey = null;
+					node.animationCache.nextKey = null;
+					node.animationCache.originalMatrix = object.matrix;
+
+				}
+
+				var keys = this.data.hierarchy[h].keys;
 
-			var keys = this.data.hierarchy[h].keys;
+				if (keys.length) {
 
-			if (keys.length) {
+					node.animationCache.prevKey = keys[ 0 ];
+					node.animationCache.nextKey = keys[ 1 ];
 
-				node.animationCache.prevKey = keys[ 0 ];
-				node.animationCache.nextKey = keys[ 1 ];
+					this.startTime = Math.min( keys[0].time, this.startTime );
+					this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
 
-				this.startTime = Math.min( keys[0].time, this.startTime );
-				this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
+				}
 
 			}
 
+			this.update( 0 );
+
 		}
 
-		this.update( 0 );
+		this.isPaused = false;
 
-	}
+		THREE.AnimationHandler.play( this );
 
-	this.isPaused = false;
+	},
 
-	THREE.AnimationHandler.play( this );
+	stop: function () {
 
-};
+		this.isPlaying = false;
+		this.isPaused  = false;
 
+		THREE.AnimationHandler.stop( this );
 
-THREE.KeyFrameAnimation.prototype.stop = function() {
+		// reset JIT matrix and remove cache
 
-	this.isPlaying = false;
-	this.isPaused  = false;
-
-	THREE.AnimationHandler.stop( this );
+		for ( var h = 0; h < this.data.hierarchy.length; h ++ ) {
 
-	// reset JIT matrix and remove cache
+			var obj = this.hierarchy[ h ];
+			var node = this.data.hierarchy[ h ];
 
-	for ( var h = 0; h < this.data.hierarchy.length; h ++ ) {
-		
-		var obj = this.hierarchy[ h ];
-		var node = this.data.hierarchy[ h ];
+			if ( node.animationCache !== undefined ) {
 
-		if ( node.animationCache !== undefined ) {
+				var original = node.animationCache.originalMatrix;
 
-			var original = node.animationCache.originalMatrix;
+				original.copy( obj.matrix );
+				obj.matrix = original;
 
-			original.copy( obj.matrix );
-			obj.matrix = original;
+				delete node.animationCache;
 
-			delete node.animationCache;
+			}
 
 		}
 
-	}
-
-};
+	},
 
+	update: function ( delta ) {
 
-// Update
+		if ( this.isPlaying === false ) return;
 
-THREE.KeyFrameAnimation.prototype.update = function ( delta ) {
+		this.currentTime += delta * this.timeScale;
 
-	if ( this.isPlaying === false ) return;
+		//
 
-	this.currentTime += delta * this.timeScale;
+		var duration = this.data.length;
 
-	//
+		if ( this.loop === true && this.currentTime > duration ) {
 
-	var duration = this.data.length;
+			this.currentTime %= duration;
 
-	if ( this.loop === true && this.currentTime > duration ) {
+		}
 
-		this.currentTime %= duration;
+		this.currentTime = Math.min( this.currentTime, duration );
 
-	}
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
-	this.currentTime = Math.min( this.currentTime, duration );
+			var object = this.hierarchy[ h ];
+			var node = this.data.hierarchy[ h ];
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			var keys = node.keys,
+				animationCache = node.animationCache;
 
-		var object = this.hierarchy[ h ];
-		var node = this.data.hierarchy[ h ];
 
-		var keys = node.keys,
-			animationCache = node.animationCache;
+			if ( keys.length ) {
 
+				var prevKey = animationCache.prevKey;
+				var nextKey = animationCache.nextKey;
 
-		if ( keys.length ) {
+				if ( nextKey.time <= this.currentTime ) {
 
-			var prevKey = animationCache.prevKey;
-			var nextKey = animationCache.nextKey;
+					while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
-			if ( nextKey.time <= this.currentTime ) {
+						prevKey = nextKey;
+						nextKey = keys[ prevKey.index + 1 ];
 
-				while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+					}
 
-					prevKey = nextKey;
-					nextKey = keys[ prevKey.index + 1 ];
+					animationCache.prevKey = prevKey;
+					animationCache.nextKey = nextKey;
 
 				}
 
-				animationCache.prevKey = prevKey;
-				animationCache.nextKey = nextKey;
+				if ( nextKey.time >= this.currentTime ) {
 
-			}
+					prevKey.interpolate( nextKey, this.currentTime );
 
-			if ( nextKey.time >= this.currentTime ) {
+				} else {
 
-				prevKey.interpolate( nextKey, this.currentTime );
+					prevKey.interpolate( nextKey, nextKey.time );
 
-			} else {
+				}
 
-				prevKey.interpolate( nextKey, nextKey.time );
+				this.data.hierarchy[ h ].node.updateMatrix();
+				object.matrixWorldNeedsUpdate = true;
 
 			}
 
-			this.data.hierarchy[ h ].node.updateMatrix();
-			object.matrixWorldNeedsUpdate = true;
-
 		}
 
-	}
-
-};
+	},
 
-// Get next key with
+	getNextKeyWith: function ( sid, h, key ) {
 
-THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
+		key = key % keys.length;
 
-	var keys = this.data.hierarchy[ h ].keys;
-	key = key % keys.length;
+		for ( ; key < keys.length; key ++ ) {
 
-	for ( ; key < keys.length; key ++ ) {
+			if ( keys[ key ].hasTarget( sid ) ) {
 
-		if ( keys[ key ].hasTarget( sid ) ) {
+				return keys[ key ];
 
-			return keys[ key ];
+			}
 
 		}
 
-	}
-
-	return keys[ 0 ];
+		return keys[ 0 ];
 
-};
+	},
 
-// Get previous key with
+	getPrevKeyWith: function ( sid, h, key ) {
 
-THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
+		key = key >= 0 ? key : key + keys.length;
 
-	var keys = this.data.hierarchy[ h ].keys;
-	key = key >= 0 ? key : key + keys.length;
+		for ( ; key >= 0; key -- ) {
 
-	for ( ; key >= 0; key -- ) {
+			if ( keys[ key ].hasTarget( sid ) ) {
 
-		if ( keys[ key ].hasTarget( sid ) ) {
+				return keys[ key ];
 
-			return keys[ key ];
+			}
 
 		}
 
-	}
+		return keys[ keys.length - 1 ];
 
-	return keys[ keys.length - 1 ];
+	}
 
 };

+ 7 - 5
src/extras/animation/MorphAnimation.js

@@ -50,19 +50,21 @@ THREE.MorphAnimation.prototype = {
 		var interpolation = this.duration / this.frames;
 		var frame = Math.floor( this.currentTime / interpolation );
 
+		var influences = this.mesh.morphTargetInfluences;
+
 		if ( frame != this.currentFrame ) {
 
-			this.mesh.morphTargetInfluences[ this.lastFrame ] = 0;
-			this.mesh.morphTargetInfluences[ this.currentFrame ] = 1;
-			this.mesh.morphTargetInfluences[ frame ] = 0;
+			influences[ this.lastFrame ] = 0;
+			influences[ this.currentFrame ] = 1;
+			influences[ frame ] = 0;
 
 			this.lastFrame = this.currentFrame;
 			this.currentFrame = frame;
 
 		}
 
-		this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
-		this.mesh.morphTargetInfluences[ this.lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ];
+		influences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
+		influences[ this.lastFrame ] = 1 - influences[ frame ];
 
 	}