213 lines
4.4 KiB
JavaScript
213 lines
4.4 KiB
JavaScript
/**
|
|
* @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 ];
|
|
|
|
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.warn( 'THREE.MorphAnimMesh: animation[' + label + '] undefined in .playAnimation()' );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
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;
|
|
|
|
};
|