Spaces:
Running
Running
/** | |
* @author alteredq / http://alteredqualia.com/ | |
*/ | |
THREE.MorphBlendMesh = function ( geometry, material ) { | |
THREE.Mesh.call( this, geometry, material ); | |
this.animationsMap = {}; | |
this.animationsList = []; | |
// prepare default animation | |
// (all frames played together in 1 second) | |
var numFrames = Object.keys( this.morphTargetDictionary ).length; | |
var name = '__default'; | |
var startFrame = 0; | |
var endFrame = numFrames - 1; | |
var fps = numFrames / 1; | |
this.createAnimation( name, startFrame, endFrame, fps ); | |
this.setAnimationWeight( name, 1 ); | |
}; | |
THREE.MorphBlendMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { | |
constructor: THREE.MorphBlendMesh, | |
createAnimation: function ( name, start, end, fps ) { | |
var animation = { | |
start: start, | |
end: end, | |
length: end - start + 1, | |
fps: fps, | |
duration: ( end - start ) / fps, | |
lastFrame: 0, | |
currentFrame: 0, | |
active: false, | |
time: 0, | |
direction: 1, | |
weight: 1, | |
directionBackwards: false, | |
mirroredLoop: false | |
}; | |
this.animationsMap[ name ] = animation; | |
this.animationsList.push( animation ); | |
}, | |
autoCreateAnimations: function ( fps ) { | |
var pattern = /([a-z]+)_?(\d+)/i; | |
var firstAnimation, frameRanges = {}; | |
var i = 0; | |
for ( var key in this.morphTargetDictionary ) { | |
var chunks = key.match( pattern ); | |
if ( chunks && chunks.length > 1 ) { | |
var name = chunks[ 1 ]; | |
if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity }; | |
var range = frameRanges[ name ]; | |
if ( i < range.start ) range.start = i; | |
if ( i > range.end ) range.end = i; | |
if ( ! firstAnimation ) firstAnimation = name; | |
} | |
i ++; | |
} | |
for ( var name in frameRanges ) { | |
var range = frameRanges[ name ]; | |
this.createAnimation( name, range.start, range.end, fps ); | |
} | |
this.firstAnimation = firstAnimation; | |
}, | |
setAnimationDirectionForward: function ( name ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.direction = 1; | |
animation.directionBackwards = false; | |
} | |
}, | |
setAnimationDirectionBackward: function ( name ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.direction = - 1; | |
animation.directionBackwards = true; | |
} | |
}, | |
setAnimationFPS: function ( name, fps ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.fps = fps; | |
animation.duration = ( animation.end - animation.start ) / animation.fps; | |
} | |
}, | |
setAnimationDuration: function ( name, duration ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.duration = duration; | |
animation.fps = ( animation.end - animation.start ) / animation.duration; | |
} | |
}, | |
setAnimationWeight: function ( name, weight ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.weight = weight; | |
} | |
}, | |
setAnimationTime: function ( name, time ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.time = time; | |
} | |
}, | |
getAnimationTime: function ( name ) { | |
var time = 0; | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
time = animation.time; | |
} | |
return time; | |
}, | |
getAnimationDuration: function ( name ) { | |
var duration = - 1; | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
duration = animation.duration; | |
} | |
return duration; | |
}, | |
playAnimation: function ( name ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.time = 0; | |
animation.active = true; | |
} else { | |
console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" ); | |
} | |
}, | |
stopAnimation: function ( name ) { | |
var animation = this.animationsMap[ name ]; | |
if ( animation ) { | |
animation.active = false; | |
} | |
}, | |
update: function ( delta ) { | |
for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) { | |
var animation = this.animationsList[ i ]; | |
if ( ! animation.active ) continue; | |
var frameTime = animation.duration / animation.length; | |
animation.time += animation.direction * delta; | |
if ( animation.mirroredLoop ) { | |
if ( animation.time > animation.duration || animation.time < 0 ) { | |
animation.direction *= - 1; | |
if ( animation.time > animation.duration ) { | |
animation.time = animation.duration; | |
animation.directionBackwards = true; | |
} | |
if ( animation.time < 0 ) { | |
animation.time = 0; | |
animation.directionBackwards = false; | |
} | |
} | |
} else { | |
animation.time = animation.time % animation.duration; | |
if ( animation.time < 0 ) animation.time += animation.duration; | |
} | |
var keyframe = animation.start + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 ); | |
var weight = animation.weight; | |
if ( keyframe !== animation.currentFrame ) { | |
this.morphTargetInfluences[ animation.lastFrame ] = 0; | |
this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight; | |
this.morphTargetInfluences[ keyframe ] = 0; | |
animation.lastFrame = animation.currentFrame; | |
animation.currentFrame = keyframe; | |
} | |
var mix = ( animation.time % frameTime ) / frameTime; | |
if ( animation.directionBackwards ) mix = 1 - mix; | |
if ( animation.currentFrame !== animation.lastFrame ) { | |
this.morphTargetInfluences[ animation.currentFrame ] = mix * weight; | |
this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight; | |
} else { | |
this.morphTargetInfluences[ animation.currentFrame ] = weight; | |
} | |
} | |
} | |
} ); | |