How to play animation reversed?

Hello!
I created a .glb model with Blender and able to successfully start an animation on click.
I’m not very fond of Blender and would prefer to program the animation to play reversed, rather than animate the reversed animation…

Is there a simple way to play the animation reversed?

code:

import { useEffect } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'

export default function Journal(props) {
    const journal = useGLTF(process.env.PUBLIC_URL + '/journal-full.glb')
    const journalAnimations = useAnimations(journal.animations, journal.scene)
    console.log(journalAnimations.names)
    

    const handleClick = () => {
        const action = journalAnimations.actions.Animation;
        
        if (action) {
          action.reset().play();
        }
      };

    return  <primitive object={journal.scene} 
            rotation={[Math.PI / 2, 0, 0]}
            position={props.position}
            scale={props.scale}
            
            onClick={(e) => {
              e.stopPropagation();
              handleClick(); 
              console.log('Journal clicked')}}

            onPointerEnter={(e) => { 
              document.body.style.cursor = 'pointer'; 
              e.stopPropagation()}}

            onPointerLeave={(e) => { 
              document.body.style.cursor = 'default'; 
              e.stopPropagation()}}
    />;
}

in THREE you can simply set the AnimationMixer.timeScale to a minus number i believe, I’m not 100% on this but you should be able to use something like the following in r3f…

const [timeScale, setTimeScale] = useEffect(-1)
{ actions, mixer } = useAnimations(journal.animations, journal.scene)
//console.log(journalAnimations.names)
console.log(actions.names)

useEffect(()=>{
  mixer.timeScale = timeScale
})

2 Likes

Yep negative timeScale should work…

1 Like

The AnimationAction.timeScale has the same effects.
The Mixer.timeScale is the global effects for all AnimationActions controlled by the mixer, while the AnimationAction.timeScale is the independent effects for AnimationAction self.

2 Likes

I found that the negative timeScale alone simply moved the animation instantly back to its starting point. I tried the solution suggested at Animation jump when timeScale changes sign in the first loop when using LoopPingPong mode · Issue #19151 · mrdoob/three.js · GitHub, but got errors, so adapted it by setting the loop initially to ping pong as suggested there:
action.setLoop( THREE.LoopPingPong );
then, after it started, but before it reached the desired endpoint, resetting it to run only once:
setTimeout(function(){ action.setLoop( THREE.LoopOnce );}, 1000);
I tested it down to 100ms, which was ok, but it failed to instant at 10ms. If the reset time is too late, it will loop one extra time, then stop.

1 Like
        action.reset()
        action.timeScale = -1
        action.time = action.getClip().duration
        action.play()