Unable to update the position/rotation/scale etc of deeply nested child nodes

Hi there, I’m really hoping that someone can help me.

I’m new to threeJS / React Fiber. I have a model of an animal which I am trying to animate. Essentially when the cursor moves, the animal moves it’s head to watch it. Relatively simple.

I exported the model from Blender in the glb format, used gltfjsx to create a react-friendly format. Everything seems to be working as intended re: rendering.

Where I run into trouble is that when I am attempting to move the skeletal frame (i.e. nodes) it will only work on some nodes (rotates based on cursor position). It seems that as soon as I am targeting a deeply nested node it stops working.

For example:

const boneToModify = nodes["MCH-torsoparent"].children[0].children[0];
// will work fine
const boneToModify = nodes["MCH-torsoparent"].children[0].children[0].children[0].children[0];
// will not work
const boneToModify = nodes["MCH-torsoparent"].getByObjectId(20); // or similar getMethod
// will also not work

I’m wondering if it is something to do with how my glb file is structured but I feel if that were the case then none of the nodes would be able to be modified?

I would really appreciate any help or advice anyone can give. I’ve attached a screenshot showing the structure of my glb file and below you can find the generated jsx file.

Thank you in advance.

Best,

David

import { useRef } from "react";
import { useGLTF, useAnimations } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { getMouseDegrees } from '@/utils/getMouseDegrees';
import { MathUtils } from "three";

export default function Model({mouse, ...props}) {
  const group = useRef()
  const { nodes, materials, animations } = useGLTF('/azura3d-transformed.glb')
  const { actions } = useAnimations(animations, group);

  const moveHead = (mouse, bone, degreeLimit = 40) => {
    const degrees = getMouseDegrees(mouse.x,mouse.y,degreeLimit);
    bone.rotation.xD = MathUtils.lerp(bone.rotation.xD || 0, degrees.y, 0.1)
    bone.rotation.yD = MathUtils.lerp(bone.rotation.yD || 0, degrees.x, 0.1)
    bone.rotation.x = MathUtils.degToRad(bone.rotation.xD)
    bone.rotation.y = MathUtils.degToRad(bone.rotation.yD)
}

const {size} = useThree();
const boneToModify = nodes['DEF-spine011'];
// const boneToModify = nodes["MCH-torsoparent"].children[0].children[3].children[0];
useFrame((state,delta) => {
  const mouse = {x: size.width / 2 + (state.mouse.x * size.width) / 2, y: size.height / 2 + (-state.mouse.y * size.height) / 2}
  moveHead(mouse,boneToModify);
  boneToModify.rotation.x += 0.01;
  // boneToModify.scale.x += 0.01;
})

  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Scene">
        <group name="metarig" position={[0, -4.07, 0]} rotation={[0, Math.PI / 2, 0]} scale={6.1}>
          <group name="spine004" position={[0, 0.8, -0.44]} rotation={[1.45, 0, 0]}>
            <group name="spine003_1" rotation={[-3.03, 0.22, -0.04]}>
              <group name="spine002_1" position={[0, 0.13, 0]} rotation={[-0.26, 0.28, -0.14]}>
                <group name="spine001_1" position={[0, 0.31, 0]} rotation={[-0.21, 0.39, 0.19]}>
                  <group name="spine_1" position={[0, 0.16, 0]} rotation={[-0.09, 0.08, -0.26]} />
                </group>
              </group>
            </group>
            <group name="spine005" position={[0, 0.09, 0]} rotation={[0.28, 0, 0]}>
              <group name="spine006" position={[0, 0.18, 0]} rotation={[-0.12, 0, 0]}>
                <group name="spine007" position={[0, 0.15, 0]} rotation={[-0.06, 0, 0]}>
                  <group name="spine008" position={[0, 0.19, 0]} rotation={[-0.05, 0, 0]}>
                    <group name="spine009" position={[0, 0.23, 0]} rotation={[-0.48, 0.04, -0.02]}>
                      <group name="spine010" position={[0, 0.07, 0]} rotation={[-0.03, -0.04, -0.06]}>
                        <group name="spine011" position={[0, 0.06, 0]} rotation={[0.17, -0.02, 0.1]} />
                      </group>
                    </group>
                    <group name="shoulderL_1" position={[0.06, 0.11, -0.1]} rotation={[1.25, 0.16, -0.33]}>
                      <group name="front_thighL" position={[0, 0.21, 0.13]} rotation={[0.15, -0.12, 0.35]}>
                        <group name="front_shinL" position={[0, 0.24, 0]} rotation={[0.5, -0.02, 0.31]}>
                          <group name="front_footL" position={[0, 0.18, 0]} rotation={[-0.43, 0.16, -0.32]}>
                            <group name="front_toeL_1" position={[0, 0.27, 0]} rotation={[1.92, 0, -2.56]} />
                          </group>
                        </group>
                      </group>
                    </group>
                    <group name="shoulderR_1" position={[-0.06, 0.11, -0.1]} rotation={[1.25, -0.16, 0.33]}>
                      <group name="front_thighR" position={[0.03, 0.22, 0.12]} rotation={[0.37, 0.04, -0.3]}>
                        <group name="front_shinR" position={[0, 0.23, 0]} rotation={[0.58, -0.07, -0.3]}>
                          <group name="front_footR" position={[0, 0.18, 0]} rotation={[-0.78, -0.22, 0.08]}>
                            <group name="front_toeR_1" position={[0, 0.26, 0]} rotation={[2.09, 0.12, 2.91]} />
                          </group>
                        </group>
                      </group>
                    </group>
                    <group name="breastL_1" position={[0.03, 0, 0.11]} rotation={[0.84, 0, 0]} />
                    <group name="breastR_1" position={[-0.03, 0, 0.11]} rotation={[0.84, 0, 0]} />
                  </group>
                </group>
              </group>
              <group name="pelvisL" position={[0, 0.01, 0.2]} rotation={[2.34, -1.08, -2.53]} />
              <group name="pelvisR" position={[0, 0.01, 0.2]} rotation={[2.34, 1.08, 2.53]} />
              <group name="thighL" position={[0.12, 0.02, 0.06]} rotation={[1.49, -0.04, 0.06]}>
                <group name="shinL" position={[0, 0.41, 0]} rotation={[1.26, -0.17, -0.07]}>
                  <group name="footL" position={[0, 0.2, 0]} rotation={[-1.61, 0.06, 0.15]}>
                    <group name="toeL_1" position={[0, 0.27, 0]} rotation={[2.05, -0.07, -2.94]} />
                  </group>
                </group>
              </group>
              <group name="thighR" position={[-0.14, 0.02, 0.07]} rotation={[1.16, 0.13, -0.12]}>
                <group name="shinR" position={[0, 0.4, 0]} rotation={[0.77, 0.18, -0.02]}>
                  <group name="footR" position={[0, 0.11, 0]} rotation={[-0.81, 0, 0.05]}>
                    <group name="toeR_1" position={[0, 0.23, 0]} rotation={[2.04, 0.06, -2.93]} />
                  </group>
                </group>
              </group>
            </group>
          </group>
        </group>
        <group name="rig" position={[0.01, -4.11, 0]} rotation={[0, 1.57, 0]} scale={5.95}>
          <primitive object={nodes.root} />
          <primitive object={nodes['MCH-torsoparent']} />
          <primitive object={nodes['MCH-front_foot_ikparentL']} />
          <primitive object={nodes['MCH-front_thigh_ik_targetparentL']} />
          <primitive object={nodes['MCH-front_foot_ikparentR']} />
          <primitive object={nodes['MCH-front_thigh_ik_targetparentR']} />
          <primitive object={nodes['MCH-foot_ikparentL']} />
          <primitive object={nodes['MCH-thigh_ik_targetparentL']} />
          <primitive object={nodes['MCH-foot_ikparentR']} />
          <primitive object={nodes['MCH-thigh_ik_targetparentR']} />
          <group name="Plane">
            <skinnedMesh name="Plane_1" geometry={nodes.Plane_1.geometry} material={materials['Material.005']} skeleton={nodes.Plane_1.skeleton} />
            <skinnedMesh name="Plane_2" geometry={nodes.Plane_2.geometry} material={materials['Material.002']} skeleton={nodes.Plane_2.skeleton} />
            <skinnedMesh name="Plane_3" geometry={nodes.Plane_3.geometry} material={materials['Material.003']} skeleton={nodes.Plane_3.skeleton} />
            <skinnedMesh name="Plane_4" geometry={nodes.Plane_4.geometry} material={materials['Material.004']} skeleton={nodes.Plane_4.skeleton} />
          </group>
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/azura3d-transformed.glb')

These groups are all empty. And I think you are supposed to move bones. Gltfjsx is useful when you need the full model scene graph, to make direct changes mostly, but when you don’t, and you just need to mutate a few bones I wouldn’t recommend it, especially since bones are not part of the declarative graph anyway.

Btw here’s an older example for what you want r3f bones - CodeSandbox

@ drcmda - just wanted to say thank you - this sort of highlighted that I had an issue with my model. Ended up pointed me in the right direction. Thanks.