Note that there are some explanatory texts on larger screens.

plurals
  1. POThreeJS - how to set current time in Animation
    text
    copied!<p>I'm using skinning / skeletal animation in ThreeJS. I have an animation, and I want to be able to move backward and forward through it, and jump to different locations within it, rather than the usual looping behaviour.</p> <p>The animation is created like this, as in the example:</p> <pre><code>var animation = new THREE.Animation( mesh, geometry.animation.name ); </code></pre> <p>I have tried updating the animation with negative deltas, as well as setting animation.currentTime directly:</p> <pre><code>animation.currentTime = animationLocation; </code></pre> <p>These appear to work only if I move forward in time, but if I go backward the animation breaks and I get an error:</p> <pre><code>THREE.Animation.update: Warning! Scale out of bounds: ... on bone ... </code></pre> <p>One thing that does actually work without error is to call <code>stop()</code> and then <code>play()</code> with a new start time:</p> <pre><code>animation.stop(); animation.play( true, animationLocation ); </code></pre> <p>...however when I look at what these functions are actually doing, they involve many many function calls, looping, resetting transforms etc. This seems like a horrible way to do it, even if it works as a hack. </p> <p>It may be that this functionality does not exist yet, in which case I'll try to dig in and create a function that does a minimal amount of work, but I'm hoping there is another way that I haven't found. </p> <p>Can anyone help with this?</p> <p>[UPDATE]</p> <p>As an update on my progress, I'll post the best solution I have at this time...</p> <p>I pulled out the contents of the <code>stop()</code> and <code>play()</code> functions, and stripped out everything I could, making some assumptions about certain values having already been set by 'play()'. </p> <p>This still seems like it is probably not the best way to do it, but it is doing a bit less work than by just calling <code>stop()</code> then <code>play()</code>.</p> <p>This is what I was able to get it down to:</p> <pre><code>THREE.Animation.prototype.gotoTime = function( time ) { //clamp to duration of the animation: time = THREE.Math.clamp( time, 0, this.length ); this.currentTime = time; // reset key cache var h, hl = this.hierarchy.length, object; for ( h = 0; h &lt; hl; h ++ ) { object = this.hierarchy[ h ]; var prevKey = object.animationCache.prevKey; var nextKey = object.animationCache.nextKey; prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ]; prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ]; prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ]; nextKey.pos = this.getNextKeyWith( "pos", h, 1 ); nextKey.rot = this.getNextKeyWith( "rot", h, 1 ); nextKey.scl = this.getNextKeyWith( "scl", h, 1 ); } //isPlaying must be true for update to work due to "early out" //so remember the current play state: var wasPlaying = this.isPlaying; this.isPlaying = true; //update with a delta time of zero: this.update( 0 ); //reset the play state: this.isPlaying = wasPlaying; } </code></pre> <p>The main limitation of the function in terms of usefulness is that you can't interpolate from one arbitrary time to another. You can basically just scrub around in the animation.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload