|
@@ -3857,6 +3857,7 @@ class GLTFParser {
|
|
|
loadAnimation( animationIndex ) {
|
|
|
|
|
|
const json = this.json;
|
|
|
+ const parser = this;
|
|
|
|
|
|
const animationDef = json.animations[ animationIndex ];
|
|
|
const animationName = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
|
|
@@ -3914,103 +3915,23 @@ class GLTFParser {
|
|
|
|
|
|
if ( node === undefined ) continue;
|
|
|
|
|
|
- node.updateMatrix();
|
|
|
-
|
|
|
- let TypedKeyframeTrack;
|
|
|
-
|
|
|
- switch ( PATH_PROPERTIES[ target.path ] ) {
|
|
|
-
|
|
|
- case PATH_PROPERTIES.weights:
|
|
|
-
|
|
|
- TypedKeyframeTrack = NumberKeyframeTrack;
|
|
|
- break;
|
|
|
-
|
|
|
- case PATH_PROPERTIES.rotation:
|
|
|
-
|
|
|
- TypedKeyframeTrack = QuaternionKeyframeTrack;
|
|
|
- break;
|
|
|
-
|
|
|
- case PATH_PROPERTIES.position:
|
|
|
- case PATH_PROPERTIES.scale:
|
|
|
- default:
|
|
|
-
|
|
|
- TypedKeyframeTrack = VectorKeyframeTrack;
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- const targetName = node.name ? node.name : node.uuid;
|
|
|
-
|
|
|
- const interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear;
|
|
|
-
|
|
|
- const targetNames = [];
|
|
|
-
|
|
|
- if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
|
|
|
-
|
|
|
- node.traverse( function ( object ) {
|
|
|
-
|
|
|
- if ( object.morphTargetInfluences ) {
|
|
|
-
|
|
|
- targetNames.push( object.name ? object.name : object.uuid );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- targetNames.push( targetName );
|
|
|
+ if ( node.updateMatrix ) {
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- let outputArray = outputAccessor.array;
|
|
|
-
|
|
|
- if ( outputAccessor.normalized ) {
|
|
|
-
|
|
|
- const scale = getNormalizedComponentScale( outputArray.constructor );
|
|
|
- const scaled = new Float32Array( outputArray.length );
|
|
|
-
|
|
|
- for ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {
|
|
|
-
|
|
|
- scaled[ j ] = outputArray[ j ] * scale;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- outputArray = scaled;
|
|
|
+ node.updateMatrix();
|
|
|
+ node.matrixAutoUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
- for ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {
|
|
|
-
|
|
|
- const track = new TypedKeyframeTrack(
|
|
|
- targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
|
|
|
- inputAccessor.array,
|
|
|
- outputArray,
|
|
|
- interpolation
|
|
|
- );
|
|
|
-
|
|
|
- // Override interpolation with custom factory method.
|
|
|
- if ( sampler.interpolation === 'CUBICSPLINE' ) {
|
|
|
-
|
|
|
- track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
|
|
|
+ const createdTracks = parser._createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target );
|
|
|
|
|
|
- // A CUBICSPLINE keyframe in glTF has three output values for each input value,
|
|
|
- // representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
|
|
|
- // must be divided by three to get the interpolant's sampleSize argument.
|
|
|
+ if ( createdTracks ) {
|
|
|
|
|
|
- const interpolantType = ( this instanceof QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;
|
|
|
+ for ( let k = 0; k < createdTracks.length; k ++ ) {
|
|
|
|
|
|
- return new interpolantType( this.times, this.values, this.getValueSize() / 3, result );
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
|
|
|
- track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
|
|
|
+ tracks.push( createdTracks[ k ] );
|
|
|
|
|
|
}
|
|
|
|
|
|
- tracks.push( track );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -4341,6 +4262,135 @@ class GLTFParser {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ _createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target ) {
|
|
|
+
|
|
|
+ const tracks = [];
|
|
|
+
|
|
|
+ const targetName = node.name ? node.name : node.uuid;
|
|
|
+
|
|
|
+ const targetNames = [];
|
|
|
+
|
|
|
+ if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
|
|
|
+
|
|
|
+ node.traverse( function ( object ) {
|
|
|
+
|
|
|
+ if ( object.morphTargetInfluences ) {
|
|
|
+
|
|
|
+ targetNames.push( object.name ? object.name : object.uuid );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ targetNames.push( targetName );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ let TypedKeyframeTrack;
|
|
|
+
|
|
|
+ switch ( PATH_PROPERTIES[ target.path ] ) {
|
|
|
+
|
|
|
+ case PATH_PROPERTIES.weights:
|
|
|
+
|
|
|
+ TypedKeyframeTrack = NumberKeyframeTrack;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PATH_PROPERTIES.rotation:
|
|
|
+
|
|
|
+ TypedKeyframeTrack = QuaternionKeyframeTrack;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PATH_PROPERTIES.position:
|
|
|
+ case PATH_PROPERTIES.scale:
|
|
|
+ default:
|
|
|
+ switch ( outputAccessor.itemSize ) {
|
|
|
+
|
|
|
+ case 1:
|
|
|
+ TypedKeyframeTrack = NumberKeyframeTrack;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ case 3:
|
|
|
+ TypedKeyframeTrack = VectorKeyframeTrack;
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : InterpolateLinear;
|
|
|
+
|
|
|
+ const outputArray = this._getArrayFromAccessor( outputAccessor );
|
|
|
+
|
|
|
+ for ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {
|
|
|
+
|
|
|
+ const track = new TypedKeyframeTrack(
|
|
|
+ targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
|
|
|
+ inputAccessor.array,
|
|
|
+ outputArray,
|
|
|
+ interpolation
|
|
|
+ );
|
|
|
+
|
|
|
+ // Override interpolation with custom factory method.
|
|
|
+ if ( interpolation === 'CUBICSPLINE' ) {
|
|
|
+
|
|
|
+ this._createCubicSplineTrackInterpolant( track );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ tracks.push( track );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return tracks;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ _getArrayFromAccessor( accessor ) {
|
|
|
+
|
|
|
+ let outputArray = accessor.array;
|
|
|
+
|
|
|
+ if ( accessor.normalized ) {
|
|
|
+
|
|
|
+ const scale = getNormalizedComponentScale( outputArray.constructor );
|
|
|
+ const scaled = new Float32Array( outputArray.length );
|
|
|
+
|
|
|
+ for ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {
|
|
|
+
|
|
|
+ scaled[ j ] = outputArray[ j ] * scale;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ outputArray = scaled;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return outputArray;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ _createCubicSplineTrackInterpolant( track ) {
|
|
|
+
|
|
|
+ track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
|
|
|
+
|
|
|
+ // A CUBICSPLINE keyframe in glTF has three output values for each input value,
|
|
|
+ // representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
|
|
|
+ // must be divided by three to get the interpolant's sampleSize argument.
|
|
|
+
|
|
|
+ const interpolantType = ( this instanceof QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;
|
|
|
+
|
|
|
+ return new interpolantType( this.times, this.values, this.getValueSize() / 3, result );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
|
|
|
+ track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/**
|