How to set a TransformNode world rotation?

I have a model with a hierarchy of bones, and I want to set the world rotation of a certain bone. How can I do that?
I’ve read this topic: How to set world rotation for a transformNode with multiple hierarchy nodes?
But the given answer doesn’t work for me. Setting the local .rotation with the world rotation delta seems wrong. And I can’t figure out how to use matrices for this purpose.

In terms of bones you can use setAxisAngle, setYawPitchRoll, setRotation, or setRotationMatrix to rotate a bone to a specific rotation in local or world space, as you need.

http://grideasy.github.io/tutorials/How_to_use_Bones_and_Skeletons

I am using a .glb model, so I have to set rotation using TransformNode.

This would explain why it doesn’t to just change rotation property. You will have to change rotationQuaternion.

Multiply absoluteRotationQuaternion.inverse() of TransformNode’s parent with your world rotation (as quaternion):

var worldRotation = ... // the world rotation you want to apply on bone (or its TransformNode)
var worldRotationQuat = BABYLON.Quaternion.FromEulerVector(worldRotation);
boneNode.rotationQuaternion = worldRotationQuat.multiply(boneNode.parent.absoluteRotationQuaternion.inverse());
2 Likes

Thanks for the answer! But I am still not sure if it is working properly… Rotation seems off.

I had to reset the root mesh transform, as avatar was initially spawned with (0,180,0) rotation and (1,1,-1) scale for some reason. I’ve also added computeWorldMatrix(true) to get the correct absoluteRotationQuaternion from the parent node (if I understand it correctly). And changed inverse() to invert(). Still no luck!

@romaleks360 your model has quite a large rotation applied by the parent probably by design https://www.babylonjs-playground.com/#WGZLGJ#7792

By setting an absolute 0 0 0 for instance you would cancel the parent rotation making your model probably looking off here.

You will get into conflict by just setting scaling of glb-model to positive values, instead i recommend to use scene.useRightHandedSystem = true.

Also I am not quite sure why it doesn’t work for you. If I apply (0, Math.PI, 0) on head bone node the head is facing backwards, if I apply (0, 0, 0) it is facing forwards. Maybe you didn’t want world rotation (instead one that is relative to bone/mesh/node alignment)?

Here is the head facing backwards PG (neck gets deformed):

In Unity, running headTransform.rotation = Quaternion.Euler(0, 180, 0); gives me another result. The head’s line of sight is paralell to the ground. It applies local offset on the X axis to cancel the neck rotation. I was expecting the same result.
In your sandbox, the final local head rotation in Inspector is (0, 180, 0), which is the same as the target world rotation, so it doesn’t cancel the neck/hierarchy rotation.

I am not sure that it is that simple as currently to stand straight the node is not at 0 0 0 rotation but

You would need to keep this rotation factored in.

@romaleks360 did you mange to solve your problem? I have a similar issue with .glb model. Suggested method by @Takemura to apply world rotation to transformNode is not working for me.

Do you mind sharing a tiny repro in the playground ?

@Deltakosh I have 4 points in WORLD space (positions shown with 4 spheres: red, green, blue, black). I would like to rotate skeleton bones (right forearm and right hand) the same way spheres are rotated. Right forearm rotation is calculated by rotation between vectors red->green and green->blue. Right hand rotation is calculated by rotation between vectors green->blue and blue->black. No luck so far.

Any ideas how to solve it?

Let me add @Evgeni_Popov in case has a few spare cycles to look into this ?

Let’s wrap up what I’m trying to do with Babylon.

I have a skeleton represented by points in the WORLD space.

I would like my gltf model to move the same way. I can not just change absolute positions of gltf model bones as this leads to skin deformations. So I need to calculate each bone rotation/rotationQuaternion. Bone (transformNode) rotation can be only change in LOCAL space.

When rotation is calculated from reference skeleton in WORLD space, I have to convert it to LOCAL bone space.

Interesting enough, I have to find the same solution to get webxr’s body tracking to work correctly. I was planning on tackling this soon (already started with the initial implementation). Seem to be very close to what you are trying to achieve, as the webxr tracker provides a (right-handed) world-space transformation for the body points.
So, I don’t have a solution (yet), but will most certainly need to come up with one.

2 Likes

Still no working solution. Quick question, is there a way to align bones local axies to world axies in babylon?