GLB Blender animation not working in ThreeJS

Hi all,

First of all, I’ve browsed a bit through the forum and I must say it’s an amazing community – I’ve never seen people so patient, kind and happy to help.

Now, regarding my issue – I’m trying to animate a model in three using react-three/fiber and drei.

This is the code of the component

import { useAnimations, useGLTF } from '@react-three/drei';
import { useFrame } from '@react-three/fiber';
import { useEffect } from 'react';
import * as THREE from 'three';

const path = '/animated-curtains.glb';

const AnimatedCurtain = () => {
  const { nodes, animations, scene } = useGLTF(path);
  const { actions, ref, names, mixer } = useAnimations(animations);

  useEffect(() => {
    scene.traverse((child) => {
      if (child instanceof THREE.Mesh) {
        // child.material = new THREE.MeshStandardMaterial({
        //   color: '#ebd8a9',
        //   side: THREE.DoubleSide,
        // });
        child.castShadow = true;
        child.receiveShadow = true;
      }
    });
  }, [scene]);

  // same result with and without this
  useFrame((_state, delta) => mixer.update(delta));

  useEffect(() => {
    console.log('Animations:', animations);
    console.log('Animation Names:', names);
    animations.forEach((clip) => {
      console.log('Clip:', clip.name, {
        duration: clip.duration,
        tracks: clip.tracks.length,
        frames: clip.tracks[0]?.times.length || 0,
      });
    });
  }, [animations, names]);

  useEffect(() => {
    actions[names[0]]?.reset();
    actions[names[0]]?.play();
  }, [actions, names]);

  return (
    <group ref={ref}>
      <primitive object={new THREE.AxesHelper(100)} />
      <primitive object={scene} />
    </group>
  );
};

useGLTF.preload(path);

export default AnimatedCurtain;

I used a pre-existing model taken from the internet with a simple animation. I exported it with the blender addon in 2 different ways but neither is working.

This is the original: https://www.youtube.com/watch?v=xOQ8uOVptGk (can’t upload the file as it’s 20mb)

  1. This one: animated-curtains.glb (119.1 KB) is playing an animation but just animating the top of the cloth, it’s glitchy and not really doing anything. When I log the animations, it returns a duration (~6.6) and a track.
  2. This one: curtains-animation.glb (2.4 MB) is not working at all. When I log the animation, it returns a duration of 0 and no tracks.

I used different settings to tryout stuff but these are the results I’m stuck with. I have the same result in the three.js editor.

Here’s the github repo: GitHub - steoo/recipes-to at animation

I thank you all in advance, have a great weekend.

I think you’re missing a step in there…

You’re getting the animations…

but for each animation, you have to create an action via animation.clipAction()
and play that action using the mixer.

let actions = animations.map( anim=>{
return anim.clipAction(mixer,scene).play();
})

(I might be missing something… I’m not 100% clear on any additional semantics incurred by r3f)

I inspected the code and it’s calling animation.clipAction|() under the hood

I’m investigating a bit more and I reckon the issue is that I’m using an empty object as a hook and the animation won’t be exported because it’s using blender’s physics. So I’m trying to understand how to bake that animation, if even possible.

You can bake some animations from blender physics. So that’s a viable path.

If you’re still having trouble getting animations to play, try to dump the Animation object itself and examine its keyframe tracks. The keyframe tracks contain the name of the object they are bound to, so you can’t just switch out the object, unless the new object you’re switching too has the same name/hierarchy etc.

I managed to bake the animation into the object itself and now it works! :slight_smile:

Thanks for your support!