Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 43 additions & 47 deletions src/animation/KeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,26 @@ import { LinearInterpolant } from '../math/interpolants/LinearInterpolant.js';
import { DiscreteInterpolant } from '../math/interpolants/DiscreteInterpolant.js';
import { AnimationUtils } from './AnimationUtils.js';

function KeyframeTrack( name, times, values, interpolation ) {
class KeyframeTrack {

if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
constructor( name, times, values, interpolation ) {

this.name = name;
if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );

this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
this.name = name;

this.setInterpolation( interpolation || this.DefaultInterpolation );
this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
this.values = AnimationUtils.convertArray( values, this.ValueBufferType );

}

// Static methods
this.setInterpolation( interpolation || this.DefaultInterpolation );

Object.assign( KeyframeTrack, {
}

// Serialization (in static context, because of constructor invocation
// and automatic invocation of .toJSON):

toJSON: function ( track ) {
static toJSON( track ) {

const trackType = track.constructor;

Expand Down Expand Up @@ -67,37 +65,25 @@ Object.assign( KeyframeTrack, {

}

} );

Object.assign( KeyframeTrack.prototype, {

constructor: KeyframeTrack,

TimeBufferType: Float32Array,

ValueBufferType: Float32Array,

DefaultInterpolation: InterpolateLinear,

InterpolantFactoryMethodDiscrete: function ( result ) {
InterpolantFactoryMethodDiscrete( result ) {

return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );

},
}

InterpolantFactoryMethodLinear: function ( result ) {
InterpolantFactoryMethodLinear( result ) {

return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );

},
}

InterpolantFactoryMethodSmooth: function ( result ) {
InterpolantFactoryMethodSmooth( result ) {

return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );

},
}

setInterpolation: function ( interpolation ) {
setInterpolation( interpolation ) {

let factoryMethod;

Expand Down Expand Up @@ -152,9 +138,9 @@ Object.assign( KeyframeTrack.prototype, {

return this;

},
}

getInterpolation: function () {
getInterpolation() {

switch ( this.createInterpolant ) {

Expand All @@ -172,16 +158,16 @@ Object.assign( KeyframeTrack.prototype, {

}

},
}

getValueSize: function () {
getValueSize() {

return this.values.length / this.times.length;

},
}

// move all keyframes either forwards or backwards in time
shift: function ( timeOffset ) {
shift( timeOffset ) {

if ( timeOffset !== 0.0 ) {

Expand All @@ -197,10 +183,10 @@ Object.assign( KeyframeTrack.prototype, {

return this;

},
}

// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
scale: function ( timeScale ) {
scale( timeScale ) {

if ( timeScale !== 1.0 ) {

Expand All @@ -216,11 +202,11 @@ Object.assign( KeyframeTrack.prototype, {

return this;

},
}

// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
trim: function ( startTime, endTime ) {
trim( startTime, endTime ) {

const times = this.times,
nKeys = times.length;
Expand Down Expand Up @@ -260,10 +246,10 @@ Object.assign( KeyframeTrack.prototype, {

return this;

},
}

// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
validate: function () {
validate() {

let valid = true;

Expand Down Expand Up @@ -337,11 +323,11 @@ Object.assign( KeyframeTrack.prototype, {

return valid;

},
}

// removes equivalent sequential keys as common in morph target sequences
// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
optimize: function () {
optimize() {

// times or values may be shared with other tracks, so overwriting is unsafe
const times = AnimationUtils.arraySlice( this.times ),
Expand Down Expand Up @@ -450,9 +436,9 @@ Object.assign( KeyframeTrack.prototype, {

return this;

},
}

clone: function () {
clone() {

const times = AnimationUtils.arraySlice( this.times, 0 );
const values = AnimationUtils.arraySlice( this.values, 0 );
Expand All @@ -467,6 +453,16 @@ Object.assign( KeyframeTrack.prototype, {

}

}

Object.assign( KeyframeTrack.prototype, {

TimeBufferType: Float32Array,

ValueBufferType: Float32Array,

DefaultInterpolation: InterpolateLinear,

} );
Comment on lines +458 to 466
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I debated whether or not to preserve these prototype properties. They should reduce memory footprint with a large number of animation tracks, though I don't know if that matters in real world usage. They seem better suited as static props than instance props? Anyways, let me know what direction is good and I can tweak this PR as needed.

Honestly, all of the inheritance doesn't seem that useful. In the long run maybe the track system could just be refactored with a more data-driven approach.


export { KeyframeTrack };
11 changes: 2 additions & 9 deletions src/animation/tracks/BooleanKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of Boolean keyframe values.
*/
class BooleanKeyframeTrack extends KeyframeTrack {}

function BooleanKeyframeTrack( name, times, values ) {

KeyframeTrack.call( this, name, times, values );

}

BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {

constructor: BooleanKeyframeTrack,
Object.assign( BooleanKeyframeTrack.prototype, {

ValueTypeName: 'bool',
ValueBufferType: Array,
Expand Down
11 changes: 2 additions & 9 deletions src/animation/tracks/ColorKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of keyframe values that represent color.
*/
class ColorKeyframeTrack extends KeyframeTrack {}

function ColorKeyframeTrack( name, times, values, interpolation ) {

KeyframeTrack.call( this, name, times, values, interpolation );

}

ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {

constructor: ColorKeyframeTrack,
Object.assign( ColorKeyframeTrack.prototype, {

ValueTypeName: 'color'

Expand Down
11 changes: 2 additions & 9 deletions src/animation/tracks/NumberKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of numeric keyframe values.
*/
class NumberKeyframeTrack extends KeyframeTrack {}

function NumberKeyframeTrack( name, times, values, interpolation ) {

KeyframeTrack.call( this, name, times, values, interpolation );

}

NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {

constructor: NumberKeyframeTrack,
Object.assign( NumberKeyframeTrack.prototype, {

ValueTypeName: 'number'

Expand Down
17 changes: 6 additions & 11 deletions src/animation/tracks/QuaternionKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,24 @@ import { QuaternionLinearInterpolant } from '../../math/interpolants/QuaternionL
/**
* A Track of quaternion keyframe values.
*/
class QuaternionKeyframeTrack extends KeyframeTrack {

function QuaternionKeyframeTrack( name, times, values, interpolation ) {
InterpolantFactoryMethodLinear( result ) {

KeyframeTrack.call( this, name, times, values, interpolation );
return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );

}
}

QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
}

constructor: QuaternionKeyframeTrack,
Object.assign( QuaternionKeyframeTrack.prototype, {

ValueTypeName: 'quaternion',

// ValueBufferType is inherited

DefaultInterpolation: InterpolateLinear,

InterpolantFactoryMethodLinear: function ( result ) {

return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );

},

InterpolantFactoryMethodSmooth: undefined // not yet implemented
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this pattern where prototype methods are undefined to drive fallback logic in base KeyframeTrack. It feels kind of wrong to mutate the KeyframeTrack interface, although I guess if these can be considered internal it doesn't matter. No need to change now, just pointing it out as another candidate for some cleanup down the road.


} );
Expand Down
11 changes: 2 additions & 9 deletions src/animation/tracks/StringKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track that interpolates Strings
*/
class StringKeyframeTrack extends KeyframeTrack {}

function StringKeyframeTrack( name, times, values, interpolation ) {

KeyframeTrack.call( this, name, times, values, interpolation );

}

StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {

constructor: StringKeyframeTrack,
Object.assign( StringKeyframeTrack.prototype, {

ValueTypeName: 'string',
ValueBufferType: Array,
Expand Down
11 changes: 2 additions & 9 deletions src/animation/tracks/VectorKeyframeTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,9 @@ import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of vectored keyframe values.
*/
class VectorKeyframeTrack extends KeyframeTrack {}

function VectorKeyframeTrack( name, times, values, interpolation ) {

KeyframeTrack.call( this, name, times, values, interpolation );

}

VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {

constructor: VectorKeyframeTrack,
Object.assign( VectorKeyframeTrack.prototype, {

ValueTypeName: 'vector'

Expand Down