How to control the joints in GLTF?

Supposing I’ve created a model has 2 segments connected with 1 joints, and exported this model as GLTF, and loaded this GLTF with threejs, I want to know how to keep threejs controls the joints angle as animation?

let myBone = animationScene.getObjectByName( "elbowBone" )
...
myBone.rotation.x += .1;

// Load GLTF model
const loader = new THREE.GLTFLoader();
loader.load(‘model.gltf’, (gltf) => {
const model = gltf.scene;
const mixer = new THREE.AnimationMixer(model);
const clips = gltf.animations;

// Get the first animation clip
const clip = clips[0];

// Create animation action
const action = mixer.clipAction(clip);
action.play();

// Add model to the scene
scene.add(model);

// Animation loop
function animate() {
    requestAnimationFrame(animate);

    // Update mixer
    mixer.update(deltaTime);

    // Render scene
    renderer.render(scene, camera);
}

animate();

});

Thanks, if that animationScense = gltf.scene?

1 Like

Thank, how to rotate the bone as Manthrax’s code?

To rotate a bone in Three.js, you typically manipulate the bone’s rotation property. Assuming you have access to the bone object, you can rotate it around its local axes by setting its rotation property.

// Assuming you have a bone object named 'bone'
bone.rotation.x = angleX; // Rotate around the X-axis
bone.rotation.y = angleY; // Rotate around the Y-axis
bone.rotation.z = angleZ; // Rotate around the Z-axis

Replace angleX, angleY, and angleZ with the desired rotation angles in radians or degrees. This will rotate the bone around its local X, Y, and Z axes respectively.

If you want to rotate the bone relative to its current orientation, you can use the .rotateX(), .rotateY(), and .rotateZ() methods:

// Assuming you have a bone object named 'bone'
bone.rotateX(angleX); // Rotate around the local X-axis
bone.rotateY(angleY); // Rotate around the local Y-axis
bone.rotateZ(angleZ); // Rotate around the local Z-axis

Again, replace angleX, angleY, and angleZ with the desired rotation angles.

I attached the testing files, run ‘cd loadGLTF’ ‘npm install’ ‘npm run dev’ to run this project.I can load the Joint1.gltf file and shown in the scene, and the ‘bone’ element can be found, but I can’t rotate it.
loadGLTF.zip (40.3 KB)

When you set rotation.x it is in radians not degrees, so if you set it to 60, that is actually close to 2PI10 which might look like no rotation. Also setting it to 60 ignores what it started at… so you want to add, not =.
Try: bone.rotation.x += Math.PI*.5 // Add 45 degrees to the rotation

Oh, but as you can see I’ve comment line 48, if I un-comment I will get this error,

That means “bone” is undefined… so you haven’t found the bone properly I think.

Can you do a

gltf.scene.traverse(e => e.isBone && console.log(e.name) )

and list all the bone names ?
Then make sure you are doing gltf.scene.getObjectByName ( ) with the correct bone name?

I looked at your GLTF file and it doesn’t appear to have actual bones in it.
Here are the node names and types in your file:

Root Group
index.js:631 Joint1 Object3D
index.js:631 occurrence_of_Bone Object3D
index.js:631 Bone Group
index.js:631 mesh0_mesh Mesh
index.js:631 mesh0_mesh_1 Mesh
index.js:631 mesh0_mesh_2 Mesh
index.js:631 mesh0_mesh_3 Mesh
index.js:631 mesh0_mesh_4 Mesh
index.js:631 mesh0_mesh_5 Mesh
index.js:631 mesh0_mesh_6 Mesh
index.js:631 mesh0_mesh_7 Mesh
index.js:631 mesh0_mesh_8 Mesh
index.js:631 mesh0_mesh_9 Mesh
index.js:631 occurrence_of_Bone_1 Object3D
index.js:631 Bone_1 Group
index.js:631 mesh0_mesh Mesh
index.js:631 mesh0_mesh_1 Mesh
index.js:631 mesh0_mesh_2 Mesh
index.js:631 mesh0_mesh_3 Mesh
index.js:631 mesh0_mesh_4 Mesh
index.js:631 mesh0_mesh_5 Mesh
index.js:631 mesh0_mesh_6 Mesh
index.js:631 mesh0_mesh_7 Mesh
index.js:631 mesh0_mesh_8 Mesh
index.js:631 mesh0_mesh_9 Mesh

So you have meshes, and groups, and Object3D but not actual bones.

That said, you can get one of those objects… like

let someNode = gltf.scene.getObjectByName('Bone')

or

let someNode = gltf.scene.getObjectByName('Bone_1')

and then

someNode.rotation.x += .1 

Notice it is case sensitive… so

gltf.scene.getObjectByName('bone')

will not work and return undefined.

I think there is some confusion on your part between “bones” and objects in threejs

Bones are used in SkinnedMeshes like characters, where the multiple Bones can affect parts of the same mesh.

What you have in your file is just Meshes, but meshes can be rotated, scaled, positioned also.

hi, as you can see, I had used gltf.scene.getObjectByName in line 32, that didn’t work, so I tried another way. I am new to this 3D world, I don’t know how to define a real bone in 3D design software. The attachment is the STEP file, would you help me to add bone to it? Thank you very much!
image
Joint1.step (12.2 KB)

You don’t have to use a bone. getObjectByName(‘Bone’) should be working.
Setting rotation to 60 will appear to do no rotation because 60 radians is ~3600 degrees, so it won’t look like its rotated at all.
You don’t need that compileAsync stuff. await’ing on it kinda defeats the purpose of doing it. Just let renderer.render take care of it.
You don’t need setPath.

Try just this:

loader.load('./Joint1.gltf',(gltf)=>{
    scene.add(gltf.scene);
    gltf.scene.getObjectByName('Bone').rotation.x += Math.PI * .5;
})
1 Like

Thank you very much! It works now, but I have not defined the real bone how three.js know where is the joint point to rotate? and can I define real bone in any 3D design software?

Gltf loader contains all the details in a mesh. Just log your attribute gltf. Y’ll get the exact details of the uploaded mesh

1 Like

Ok, thanks.

Yeah you can make real bones with an “Armature” in blender, or maya, or 3ds, before exporting to gltf.
For mechanical things you probably don’t need bones though. You only really need true bones if the bone is moving only part of a mesh… like in character animation, where each vertex has weights to different bones… or for like… soft objects.

The rotation point is the origin of the root object. If you need to rotate around a different origin, you can attach the object to a new node, and then move it, and then rotate the parent.

1 Like

Mechanical things don’t need real bone? I learn threejs is for simulating the mechanical movement with multiple DOF, let me try to make a more complicated gltf file for further test.

1 Like

Yeah. Regular linkages can be simulated with just simple object hierarchies. You only need bones if a single mesh is going to transformed by multiple different transforms…
For instance a character body is 1 mesh, but has many bones, each bone, modifying a different region of the body.
For mechanical things… usually only 1 part is affected by each transform. (unless you have things like soft wires or flexible parts connecting, then you may need to use bones to make it look realistic)

I want to simulate the multi DOF robot arm using inverse kinematics, do you think no bone should be OK?