/** * @author alteredq / http://alteredqualia.com/ */ THREE.MorphAnimMesh = function ( geometry, material ) { THREE.Mesh.call( this, geometry, material ); this.type = 'MorphAnimMesh'; // API this.duration = 1000; // milliseconds this.mirroredLoop = false; this.time = 0; // internals this.lastKeyframe = 0; this.currentKeyframe = 0; this.direction = 1; this.directionBackwards = false; this.setFrameRange( 0, this.geometry.morphTargets.length - 1 ); }; THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype ); THREE.MorphAnimMesh.prototype.constructor = THREE.MorphAnimMesh; THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) { this.startKeyframe = start; this.endKeyframe = end; this.length = this.endKeyframe - this.startKeyframe + 1; }; THREE.MorphAnimMesh.prototype.setDirectionForward = function () { this.direction = 1; this.directionBackwards = false; }; THREE.MorphAnimMesh.prototype.setDirectionBackward = function () { this.direction = - 1; this.directionBackwards = true; }; THREE.MorphAnimMesh.prototype.parseAnimations = function () { var geometry = this.geometry; if ( ! geometry.animations ) geometry.animations = {}; var firstAnimation, animations = geometry.animations; var pattern = /([a-z]+)_?(\d+)/; for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) { var morph = geometry.morphTargets[ i ]; var parts = morph.name.match( pattern ); if ( parts && parts.length > 1 ) { var label = parts[ 1 ]; var num = parts[ 2 ]; if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity }; var animation = animations[ label ]; if ( i < animation.start ) animation.start = i; if ( i > animation.end ) animation.end = i; if ( ! firstAnimation ) firstAnimation = label; } } geometry.firstAnimation = firstAnimation; }; THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) { if ( ! this.geometry.animations ) this.geometry.animations = {}; this.geometry.animations[ label ] = { start: start, end: end }; }; THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) { var animation = this.geometry.animations[ label ]; if ( animation ) { this.setFrameRange( animation.start, animation.end ); this.duration = 1000 * ( ( animation.end - animation.start ) / fps ); this.time = 0; } else { THREE.warning( 'animation[' + label + '] undefined' ); } }; THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) { var frameTime = this.duration / this.length; this.time += this.direction * delta; if ( this.mirroredLoop ) { if ( this.time > this.duration || this.time < 0 ) { this.direction *= - 1; if ( this.time > this.duration ) { this.time = this.duration; this.directionBackwards = true; } if ( this.time < 0 ) { this.time = 0; this.directionBackwards = false; } } } else { this.time = this.time % this.duration; if ( this.time < 0 ) this.time += this.duration; } var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 ); if ( keyframe !== this.currentKeyframe ) { this.morphTargetInfluences[ this.lastKeyframe ] = 0; this.morphTargetInfluences[ this.currentKeyframe ] = 1; this.morphTargetInfluences[ keyframe ] = 0; this.lastKeyframe = this.currentKeyframe; this.currentKeyframe = keyframe; } var mix = ( this.time % frameTime ) / frameTime; if ( this.directionBackwards ) { mix = 1 - mix; } this.morphTargetInfluences[ this.currentKeyframe ] = mix; this.morphTargetInfluences[ this.lastKeyframe ] = 1 - mix; }; THREE.MorphAnimMesh.prototype.interpolateTargets = function ( a, b, t ) { var influences = this.morphTargetInfluences; for ( var i = 0, l = influences.length; i < l; i ++ ) { influences[ i ] = 0; } if ( a > -1 ) influences[ a ] = 1 - t; if ( b > -1 ) influences[ b ] = t; }; THREE.MorphAnimMesh.prototype.clone = function ( object ) { if ( object === undefined ) object = new THREE.MorphAnimMesh( this.geometry, this.material ); object.duration = this.duration; object.mirroredLoop = this.mirroredLoop; object.time = this.time; object.lastKeyframe = this.lastKeyframe; object.currentKeyframe = this.currentKeyframe; object.direction = this.direction; object.directionBackwards = this.directionBackwards; THREE.Mesh.prototype.clone.call( this, object ); return object; };