|
@@ -3,33 +3,38 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
THREE.Animation = function( root, data ) {
|
|
THREE.Animation = function( root, data ) {
|
|
-
|
|
|
|
- this.root = root;
|
|
|
|
- this.data = data;
|
|
|
|
|
|
+
|
|
|
|
+ this.root = root;
|
|
|
|
+ this.data = data;
|
|
this.hierarchy = [];
|
|
this.hierarchy = [];
|
|
|
|
|
|
this.startTime = 0;
|
|
this.startTime = 0;
|
|
this.isPlaying = false;
|
|
this.isPlaying = false;
|
|
- this.loop = true;
|
|
|
|
-
|
|
|
|
- this.offset = 0;
|
|
|
|
|
|
+ this.loop = true;
|
|
|
|
|
|
|
|
+ this.offset = 0;
|
|
|
|
|
|
// need to initialize data?
|
|
// need to initialize data?
|
|
|
|
|
|
- if( !this.data.initialized )
|
|
|
|
|
|
+ if( !this.data.initialized ) {
|
|
|
|
+
|
|
THREE.AnimationHandler.initData( this.data );
|
|
THREE.AnimationHandler.initData( this.data );
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
|
|
// setup hierarchy
|
|
// setup hierarchy
|
|
|
|
|
|
- if( root instanceof THREE.SkinnedMesh ) {
|
|
|
|
-
|
|
|
|
- for( var b = 0; b < this.root.bones.length; b++ )
|
|
|
|
|
|
+ if ( root instanceof THREE.SkinnedMesh ) {
|
|
|
|
+
|
|
|
|
+ for( var b = 0; b < this.root.bones.length; b++ ) {
|
|
|
|
+
|
|
this.hierarchy.push( this.root.bones[ b ] );
|
|
this.hierarchy.push( this.root.bones[ b ] );
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
-
|
|
|
|
|
|
+
|
|
// parse hierarchy and match against animation (somehow)
|
|
// parse hierarchy and match against animation (somehow)
|
|
|
|
|
|
}
|
|
}
|
|
@@ -44,36 +49,35 @@ THREE.Animation = function( root, data ) {
|
|
THREE.Animation.prototype.play = function( loop ) {
|
|
THREE.Animation.prototype.play = function( loop ) {
|
|
|
|
|
|
if( !this.isPlaying ) {
|
|
if( !this.isPlaying ) {
|
|
-
|
|
|
|
|
|
+
|
|
this.isPlaying = true;
|
|
this.isPlaying = true;
|
|
this.startTime = new Date().getTime() * 0.001;
|
|
this.startTime = new Date().getTime() * 0.001;
|
|
|
|
|
|
-
|
|
|
|
// reset key cache
|
|
// reset key cache
|
|
-
|
|
|
|
- for( var h = 0; h < this.hierarchy.length; h++ ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ for ( var h = 0; h < this.hierarchy.length; h++ ) {
|
|
|
|
+
|
|
this.hierarchy[ h ].useQuaternion = true;
|
|
this.hierarchy[ h ].useQuaternion = true;
|
|
this.hierarchy[ h ].matrixAutoUpdate = true;
|
|
this.hierarchy[ h ].matrixAutoUpdate = true;
|
|
-
|
|
|
|
- if( this.hierarchy[ h ].prevKey === undefined ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if ( this.hierarchy[ h ].prevKey === undefined ) {
|
|
|
|
+
|
|
this.hierarchy[ h ].prevKey = { pos: 0, rot: 0, scl: 0 };
|
|
this.hierarchy[ h ].prevKey = { pos: 0, rot: 0, scl: 0 };
|
|
this.hierarchy[ h ].nextKey = { pos: 0, rot: 0, scl: 0 };
|
|
this.hierarchy[ h ].nextKey = { pos: 0, rot: 0, scl: 0 };
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
this.hierarchy[ h ].prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ];
|
|
this.hierarchy[ h ].prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ];
|
|
this.hierarchy[ h ].prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ];
|
|
this.hierarchy[ h ].prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ];
|
|
this.hierarchy[ h ].prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ];
|
|
this.hierarchy[ h ].prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ];
|
|
-
|
|
|
|
|
|
+
|
|
this.hierarchy[ h ].nextKey.pos = this.getNextKeyWith( "pos", h, 1 );
|
|
this.hierarchy[ h ].nextKey.pos = this.getNextKeyWith( "pos", h, 1 );
|
|
this.hierarchy[ h ].nextKey.rot = this.getNextKeyWith( "rot", h, 1 );
|
|
this.hierarchy[ h ].nextKey.rot = this.getNextKeyWith( "rot", h, 1 );
|
|
this.hierarchy[ h ].nextKey.scl = this.getNextKeyWith( "scl", h, 1 );
|
|
this.hierarchy[ h ].nextKey.scl = this.getNextKeyWith( "scl", h, 1 );
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
this.update();
|
|
this.update();
|
|
-
|
|
|
|
|
|
+
|
|
THREE.AnimationHandler.add( this );
|
|
THREE.AnimationHandler.add( this );
|
|
|
|
|
|
}
|
|
}
|
|
@@ -86,9 +90,9 @@ THREE.Animation.prototype.play = function( loop ) {
|
|
*/
|
|
*/
|
|
|
|
|
|
THREE.Animation.prototype.pause = function() {
|
|
THREE.Animation.prototype.pause = function() {
|
|
-
|
|
|
|
|
|
+
|
|
THREE.AnimationHandler.remove( this );
|
|
THREE.AnimationHandler.remove( this );
|
|
-
|
|
|
|
|
|
+
|
|
// todo
|
|
// todo
|
|
}
|
|
}
|
|
|
|
|
|
@@ -98,7 +102,7 @@ THREE.Animation.prototype.pause = function() {
|
|
*/
|
|
*/
|
|
|
|
|
|
THREE.Animation.prototype.stop = function() {
|
|
THREE.Animation.prototype.stop = function() {
|
|
-
|
|
|
|
|
|
+
|
|
this.isPlaying = false;
|
|
this.isPlaying = false;
|
|
THREE.AnimationHandler.remove( this );
|
|
THREE.AnimationHandler.remove( this );
|
|
}
|
|
}
|
|
@@ -110,15 +114,15 @@ THREE.Animation.prototype.stop = function() {
|
|
|
|
|
|
THREE.Animation.prototype.update = function( time ) {
|
|
THREE.Animation.prototype.update = function( time ) {
|
|
|
|
|
|
- // todo: add input time
|
|
|
|
|
|
+ // TODO: add input time
|
|
|
|
|
|
// early out
|
|
// early out
|
|
-
|
|
|
|
|
|
+
|
|
if( !this.isPlaying ) return;
|
|
if( !this.isPlaying ) return;
|
|
|
|
|
|
|
|
|
|
// vars
|
|
// vars
|
|
-
|
|
|
|
|
|
+
|
|
var types = [ "pos", "rot", "scl" ];
|
|
var types = [ "pos", "rot", "scl" ];
|
|
var scale;
|
|
var scale;
|
|
var relative;
|
|
var relative;
|
|
@@ -127,117 +131,116 @@ THREE.Animation.prototype.update = function( time ) {
|
|
var object;
|
|
var object;
|
|
var frame;
|
|
var frame;
|
|
var JIThierarchy = this.data.JIT.hierarchy;
|
|
var JIThierarchy = this.data.JIT.hierarchy;
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
// update
|
|
// update
|
|
-
|
|
|
|
|
|
+
|
|
var currentTime = new Date().getTime() * 0.001 - this.startTime + this.offset;
|
|
var currentTime = new Date().getTime() * 0.001 - this.startTime + this.offset;
|
|
var unloopedCurrentTime = currentTime;
|
|
var unloopedCurrentTime = currentTime;
|
|
|
|
|
|
|
|
|
|
// looped?
|
|
// looped?
|
|
-
|
|
|
|
- if( currentTime > this.data.length ) {
|
|
|
|
-
|
|
|
|
- while( currentTime > this.data.length )
|
|
|
|
|
|
+
|
|
|
|
+ if ( currentTime > this.data.length ) {
|
|
|
|
+
|
|
|
|
+ while( currentTime > this.data.length ) {
|
|
|
|
+
|
|
currentTime -= this.data.length;
|
|
currentTime -= this.data.length;
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
this.startTime = new Date().getTime() * 0.001 - currentTime;
|
|
this.startTime = new Date().getTime() * 0.001 - currentTime;
|
|
currentTime = new Date().getTime() * 0.001 - this.startTime;
|
|
currentTime = new Date().getTime() * 0.001 - this.startTime;
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
frame = Math.min( parseInt( currentTime * this.data.fps ), parseInt( this.data.length * this.data.fps ) );
|
|
frame = Math.min( parseInt( currentTime * this.data.fps ), parseInt( this.data.length * this.data.fps ) );
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
// update
|
|
// update
|
|
-
|
|
|
|
- for( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
|
|
|
|
|
|
+
|
|
|
|
+ for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
|
|
|
|
|
|
object = this.hierarchy[ h ];
|
|
object = this.hierarchy[ h ];
|
|
-
|
|
|
|
- if( JIThierarchy[ h ][ frame ] !== undefined ) {
|
|
|
|
|
|
|
|
- object.skinMatrix = JIThierarchy[ h ][ frame ];
|
|
|
|
- object.matrixAutoUpdate = false;
|
|
|
|
- object.matrixNeedsUpdate = false;
|
|
|
|
|
|
+ if ( JIThierarchy[ h ][ frame ] !== undefined ) {
|
|
|
|
+
|
|
|
|
+ object.skinMatrix = JIThierarchy[ h ][ frame ];
|
|
|
|
+ object.matrixAutoUpdate = false;
|
|
|
|
+ object.matrixNeedsUpdate = false;
|
|
|
|
|
|
object.skinMatrix.flattenToArrayOffset( this.root.boneMatrices, h * 16 );
|
|
object.skinMatrix.flattenToArrayOffset( this.root.boneMatrices, h * 16 );
|
|
-
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
-
|
|
|
|
- for( var t = 0; t < 3; t++ ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ for ( var t = 0; t < 3; t++ ) {
|
|
|
|
+
|
|
// get keys
|
|
// get keys
|
|
-
|
|
|
|
|
|
+
|
|
var type = types[ t ];
|
|
var type = types[ t ];
|
|
var prevKey = object.prevKey[ type ];
|
|
var prevKey = object.prevKey[ type ];
|
|
var nextKey = object.nextKey[ type ];
|
|
var nextKey = object.nextKey[ type ];
|
|
-
|
|
|
|
|
|
+
|
|
// switch keys?
|
|
// switch keys?
|
|
|
|
|
|
- if( nextKey.time < unloopedCurrentTime ) {
|
|
|
|
-
|
|
|
|
|
|
+ if ( nextKey.time < unloopedCurrentTime ) {
|
|
|
|
+
|
|
// did we loop?
|
|
// did we loop?
|
|
-
|
|
|
|
- if( currentTime < unloopedCurrentTime ) {
|
|
|
|
-
|
|
|
|
- if( this.loop ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if ( currentTime < unloopedCurrentTime ) {
|
|
|
|
+
|
|
|
|
+ if ( this.loop ) {
|
|
|
|
+
|
|
prevKey = this.data.hierarchy[ h ].keys[ 0 ];
|
|
prevKey = this.data.hierarchy[ h ].keys[ 0 ];
|
|
nextKey = this.getNextKeyWith( type, h, 1 );
|
|
nextKey = this.getNextKeyWith( type, h, 1 );
|
|
|
|
|
|
} else {
|
|
} else {
|
|
-
|
|
|
|
|
|
+
|
|
this.stop();
|
|
this.stop();
|
|
return;
|
|
return;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
} else {
|
|
} else {
|
|
-
|
|
|
|
|
|
+
|
|
do {
|
|
do {
|
|
-
|
|
|
|
|
|
+
|
|
prevKey = nextKey;
|
|
prevKey = nextKey;
|
|
nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
|
|
nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
|
|
|
|
|
|
- }
|
|
|
|
- while( nextKey.time < currentTime )
|
|
|
|
|
|
+ } while( nextKey.time < currentTime )
|
|
|
|
+
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
object.prevKey[ type ] = prevKey;
|
|
object.prevKey[ type ] = prevKey;
|
|
object.nextKey[ type ] = nextKey;
|
|
object.nextKey[ type ] = nextKey;
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
// interpolate rot (quaternion slerp)
|
|
// interpolate rot (quaternion slerp)
|
|
-
|
|
|
|
|
|
+
|
|
object.matrixAutoUpdate = true;
|
|
object.matrixAutoUpdate = true;
|
|
object.matrixNeedsUpdate = true;
|
|
object.matrixNeedsUpdate = true;
|
|
-
|
|
|
|
- scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
|
|
|
|
|
|
+
|
|
|
|
+ scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
|
|
prevXYZ = prevKey[ type ];
|
|
prevXYZ = prevKey[ type ];
|
|
nextXYZ = nextKey[ type ];
|
|
nextXYZ = nextKey[ type ];
|
|
-
|
|
|
|
- if( type === "rot" ) {
|
|
|
|
-
|
|
|
|
- if( scale < 0 || scale > 1 ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if ( type === "rot" ) {
|
|
|
|
+
|
|
|
|
+ if ( scale < 0 || scale > 1 ) {
|
|
|
|
+
|
|
console.log( "Scale out of bounds:" + scale );
|
|
console.log( "Scale out of bounds:" + scale );
|
|
scale = scale < 0 ? 0 : 1;
|
|
scale = scale < 0 ? 0 : 1;
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale );
|
|
THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale );
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// lerp pos/scl
|
|
// lerp pos/scl
|
|
|
|
|
|
else {
|
|
else {
|
|
-
|
|
|
|
|
|
+
|
|
vector = type === "pos" ? object.position : object.scale;
|
|
vector = type === "pos" ? object.position : object.scale;
|
|
vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
|
|
vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
|
|
vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
|
|
vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
|
|
@@ -250,59 +253,45 @@ THREE.Animation.prototype.update = function( time ) {
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
// update JIT?
|
|
// update JIT?
|
|
-
|
|
|
|
- if( JIThierarchy[ 0 ][ frame ] === undefined ) {
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if ( JIThierarchy[ 0 ][ frame ] === undefined ) {
|
|
|
|
+
|
|
this.hierarchy[ 0 ].update( undefined, true );
|
|
this.hierarchy[ 0 ].update( undefined, true );
|
|
-
|
|
|
|
- for( var h = 0; h < this.hierarchy.length; h++ )
|
|
|
|
|
|
+
|
|
|
|
+ for ( var h = 0; h < this.hierarchy.length; h++ ) {
|
|
|
|
+
|
|
JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
|
|
JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Update Object
|
|
* Update Object
|
|
- */
|
|
|
|
-
|
|
|
|
-THREE.Animation.prototype.updateObject = function( h, currentTime, unloopedCurrentTime ) {
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
|
|
+ */
|
|
|
|
|
|
|
|
+THREE.Animation.prototype.updateObject = function( h, currentTime, unloopedCurrentTime ) {}
|
|
|
|
|
|
|
|
|
|
THREE.Animation.prototype.getNextKeyWith = function( type, h, key ) {
|
|
THREE.Animation.prototype.getNextKeyWith = function( type, h, key ) {
|
|
-
|
|
|
|
- var keys = this.data.hierarchy[ h ].keys;
|
|
|
|
-
|
|
|
|
- for( ; key < keys.length; key++ ) {
|
|
|
|
-
|
|
|
|
- if( keys[ key ][ type ] !== undefined )
|
|
|
|
- return keys[ key ];
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return this.data.hierarchy[ h ].keys[ 0 ];
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
+ var keys = this.data.hierarchy[ h ].keys;
|
|
|
|
|
|
|
|
+ for ( ; key < keys.length; key++ ) {
|
|
|
|
|
|
|
|
+ if ( keys[ key ][ type ] !== undefined ) {
|
|
|
|
|
|
|
|
+ return keys[ key ];
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ return this.data.hierarchy[ h ].keys[ 0 ];
|
|
|
|
|
|
|
|
+}
|