Getting the direction of a bone

I want to get the actual direction of a bone in the world space.
What I tried was using absolute position of child bone.

function getBoneDirection {
    var childBones = bone.getChildren();
    if (childBones.length == 0) {
         console.log("no child bone");
      return new BABYLON.Vector3(0,0,0);
    }

    var childBone = childBones[0];
    var childBonePose = childBone.getAbsolutePosition(mesh);
    var thisBonePose = bone.getAbsolutePosition(mesh);

    var boneDirection = childBonePose.subtract(thisBonePose);
    boneDirection = BABYLON.Vector3.Normalize(boneDirection);
    }

However, in this case, it is impossible the get the direction of a bone if it doesn’t have a child.

How can I correctly get the direction of a bone?

Hi @Keunwoo_Park, I think something like this could work:

1. Getting absolute position, rotation, and scale of bone:

const scale = new BABYLON.Vector3();
const rotation = new BABYLON.Quaternion();
const position = new BABYLON.Vector3();

const matrix = mesh.skeleton.bones[0].getWorldMatrix();
const matrix2 = mesh.getWorldMatrix();
const matrix3 = matrix.multiply(matrix2);

matrix3.decompose(scale, rotation, position);

This should find the absolute position, rotation, and scale of bones[0], which is part of the skeleton assigned to mesh.

2. Getting direction of bone (similar to getForwardRayToRef in Babylon source code):

const forward = new BABYLON.Vector3(1, 0, 0);
// I think using matrix3 from above should work
const forwardWorld = BABYLON.Vector3.TransformNormal(forward, matrix3);
const direction = BABYLON.Vector3.Normalize(forwardWorld);

BABYLON.Debug.BoneAxesViewer in https://www.babylonjs-playground.com/#1EVNNB#15 (mentioned in Use Bones and Skeletons - Babylon.js Documentation) also shows the direction of bones

Thanks for the reply.
However, it doesn’t seem working.
Here is my playground.
https://playground.babylonjs.com/#9JWAWG#4

You can use ‘getBoneDirectionOld’ for my old algorithm, instead of ‘getBoneDirection’.

I’m aware of the BoneAxesViewer, but it doesn’t provide bone axis vectors. Am I right?

https://playground.babylonjs.com/#9JWAWG#6

Orange lines show the bone direction. However, this direction may not be the parent-child direction you’re looking for.

You may want to check out the post Return to Rest not Behaving as Expected? by @Pryme8, @Evgeni_Popov, @Drigax. We could get the parent-child bone direction by using the same matrix method on the bone meshes rather than the bone itself.

I appreciate your answer.
However, I could not understand what is going on with the playground you shared.

I checked the Skeleton Viewer, and it also uses positions of parent and child bones, when the bone doesn’t have a length property.
https://www.babylonjs-playground.com/#1BZJVJ#7

I’m using dummy3 model, and it doesn’t have bone length.
https://www.babylonjs-playground.com/#1BZJVJ#385

I guess the ‘direction of a bone’ can’t be defined if a bone doesn’t have a child.

I think you could grab the direction of the parent bone then transform that value by the rotation value of the bone without a child.

https://playground.babylonjs.com/#9JWAWG#9

There is this too, but that’s technically the inverted direction

3 Likes

https://doc.babylonjs.com/api/classes/babylon.bone#getdirection

Thanks. However, as I know, Bone.getDirection returns rotation of a bone space, not the direction of a bone in the space.

Nope, it returns the bones direction in world space.

Ok. Then I’m confused about the ‘localAxis’. How should I set the local axis parameter?
When I set them as just Y axis, the results of getDirection is Y axis.
https://playground.babylonjs.com/#9JWAWG#10

Looks like getDirection doesn’t work with that model.

Here it works fine:
https://www.babylonjs-playground.com/#1B1PUZ#80

1 Like

getDirection does not give the direction of a bone but the transform of a passed (local) direction to world space. It returns simply bone_world_matrix * passed_axis.

It could match the bone direction in some specific cases (depending on the bone world matrix and the passed axis), but in general it won’t.

1 Like

Sorry, when getDirection was written it always returned the world direction from a local direction. The bone class has changed a lot since then and those changes seem to have broken this function in some situations. An issue should be created on github to fix this.

That’s what it does and what the doc says:

Get the world direction from an axis that is in the local space of the bone

It does not say if returns the bone direction. I don’t know what it used to return, but the current implementation is in accordance with the doc.