# Need help figuring out bone rotations - please help!

**URL:** <https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059>\
**Category:** Questions\
**Tags:** bones, models, animation, skeletal-animation\
**Created:** [August 18, 2021, 8:45pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059 "2021-08-18T20:45:01Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 18, 2021, 8:45pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/1 "2021-08-18T20:45:01Z")

</div>

I have a rigged model setup my scene of a hand:

 ![i1](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/8/f/8fbc9c5b8d860c2b589fad28d77f88716ed2a1f9.png)

I also have position data of a new hand pose that I would like this model to take the form of:

![i2](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/5/c/5c8a4e11fc38e3b61c0e272c34ee212f4c92e423.png)

(^plotting of the position data [visually mirrored as well], I included the sample position data in the uploaded project files)

It should be self explanatory, but for the sake of clarity the key points in this position data represent where the joints between each bone are in 3D space.

The problem is (or at least I think) is that I cannot just move each joint in my rigged model to these points. I need to calculate the rotations from each key point to another and set the Bone Object rotations for each bone on my rigged model/skeleton to have it match the pose. And it makes it more difficult because the rotations are relative to bone previous to it, so once you calculate and set the rotation of the parent, it changes the coordinate system of the child.

So, basically I need an algorithm that takes in these key points for each finger and calculates and sets the correct rotations for each bone on my model to match the pose.

I have a very limited background in linear algebra, and I’ve tried so many different approaches to get this right from using basic trigonometry, axis angle rotations, converting direction vectors to Euler angles, calculating rotation matrices and basis transformations, messing with Quaternions, but I’m really struggling to get anywhere, and I’ve been stuck on this for over a week now, and I’ve tried posting on stackoverflow and gamedev and no one seems to be able to give me help or guidance.

Can someone please help me figure out how to this?

I attached my entire project if necessary. After installing the node packages, it should be immediately ready to go. I’m not asking anyone to do this for me, if anyone could at least help me with that math or any other help at all it would be much appreciated. This project is very important to me! Thank you for your time.

[project.7z](https://discourse.threejs.org/uploads/short-url/6yJxnFsUpEN4elWUwGgxVQuFj4s.7z) (296.7 KB)

* * *

another resource I found: obviously leap motion has a visualizer that’s similar to this. I can’t tell if these calculations in this code [leapjs/threejs-bones.html at 5a89a25b5fd627ec0febeb7e8db77c6ca30f612a · leapmotion/leapjs · GitHub](https://github.com/leapmotion/leapjs/blob/5a89a25b5fd627ec0febeb7e8db77c6ca30f612a/examples/threejs-bones.html) are a clue to the calculations needed to help me

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 18, 2021, 10:00pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/2 "2021-08-18T22:00:13Z")

</div>

I haven’t looked at your project, but are those points just points? If you manage to get the bones to look from one point to another, how will you determine the Roll value of that bone?

You can get the matrixWorld of an object/bone. It will have the world transforms, and from that you can retrieve the orientation of a child object/bone regardless of the orientation of its parent. Or you can get the matrix (not the matrixWorld), and it will represent the local transforms (relative to the parent).

You can also create those matrices for the bones by passing position/rotation/scale to a matrix4, and then applying that to the object/bone.

One thing you can do is move the bone into the scene object, so that it isn’t a child of anything, and apply the matrix to it so that it fits the world transforms… then you can Attach it to a parent bone essentially converting its world transforms into local transforms (attach is different from add).

So for simplicity sake, if you just focus on positions first…  
Get world position of the points… set a bone position to each of those (make sure bones aren’t parented by moving them into the scene).  
Then beginning with the bone that is the root bone, attach(don’t add) each bone in sequence. This will convert their world position into a local position (rotation and scale too).

Of course, you’ll also want to calculate the orientation as well, so you could point the bones at the child bone prior to attaching them all. But you’ll need to figure out how to roll them so that the outer and inner sides of the fingers are correct… You’d need more data from your points in order to do that though if your points are just positions.

Anyways, these are just some thoughts I had to get you thinking about things. If your initial points are just positions, I’m not sure if you can get an accurate pose.  
anyways… maybe someone else has better ideas.

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 18, 2021, 10:36pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/3 "2021-08-18T22:36:03Z")

</div>

@prominent Those points are just points, yeah, if you mean 3D points (x, y, z). If youre asking if there are other things calculated like rotations, no

I think you have some good ideas, specifically detaching each bone, orienting it, and then reattaching it sounds like it might work

I did create a function that basically makes a bone look at a **local** point, so for example lets say the points for the index finger are:

knuckle (0, 0, 0) //p1  
joint1 (0, 1, 1) // p2  
joint2 (0, 1, 2) // p2  
tip (0, 0, 2) //p3

visually (bottom axis is z and up axis is y):

![i3](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/1/a/1a39712543a2e02b735e536dd748c9a48937726e.png)

We use the function:

```javascript
function boneLookAtLocal(bone, position) {
    bone.updateMatrixWorld()
    let direction = position.clone().normalize()
    let pitch = Math.asin(direction.y)// + bone.offset
    let yaw = Math.atan2(direction.x, direction.z); //Beware cos(pitch)==0, catch this exception!
    let roll = 0;
    bone.rotation.set(roll, yaw, pitch);

    console.log(roll, yaw, pitch);
    console.log(roll, THREE.MathUtils.radToDeg(yaw), THREE.MathUtils.radToDeg(pitch));
}

```

we use this function to make the index finger look at p2. This accurately sets the orientation of the first bone on the index finger:

```javascript
        boneLookAtLocal(hand.index[0], p2)

```

![image](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/9/6/96538a8628974491d16c490c0c520b6d9aaa5c30.png)

Now moving on, we want to set the middle bone to an orientation where its just going forward.

As you can see by the axis helpers, the middle bone’s local coordinate system has tranformed, so when we call:

```javascript
        let newDirection = new THREE.Vector3().subVectors(p3, p2) // gets forward direction vector = (0, 0, 1)
        boneLookAtLocal(hand.index[1], newDirection )

```

the bone does not point forward and instead points in the same direction because thats the direction of p3 on its local coordinate system:

![i5](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/3/8/3878fb8f9e98bc3f0d452c83ab3ed0c50c2cfc61.png)

So taking part of your idea, if instead of trying to calculate a new direction vector on the middle bones local coordinate system that will point the bone forward in the direction we want, we detach the bone, orient it on the global access and the reattach it to where it was, will that work?

* * *

In case someone brings it up, I tried subtracting the offsets of the parent bone (yaw and pitch) when calling boneLookAtLocal() on the child bone to orient it correctly and that does not work for some reason

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 18, 2021, 11:20pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/4 "2021-08-18T23:20:07Z")

</div>

When you get the newDirection by subtracting p3 from p2, you can convert that into the local position of the bone…  
You’ll need to first add the world position of the bone to the newDirection, so that the point represents a world position…  
newDirection.add( hand.index[1].position );  
hand.index[1].worldToLocal( newDirection );  
Then you can do:  
boneLookAtLocal(hand.index[1], newDirection );

That should make it point in the correct direction.

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 12:31am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/5 "2021-08-19T00:31:12Z")

</div>

I tried that before too, this is the result:

![i6](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/a/7/a761e3e0781ac6a527bf6d642061e95e7982f55d.png)

```javascript
        boneLookAtLocal(hand.index[0], new THREE.Vector3(0, 1, 1)) // first rotation

        let middleBoneDirection = new THREE.Vector3(0, 0, 1)
        middleBoneDirection.add(hand.index[1].position)
        hand.index[1].worldToLocal(middleBoneDirection)
        boneLookAtLocal(hand.index[1], middleBoneDirection)

```

It should be pointing flat, forward towards the z axis but its angled upwards to the left instead?

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 19, 2021, 1:24am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/6 "2021-08-19T01:24:07Z")

</div>

Oh, I think you need to get world position of the hand.index[1].position (since the bone is a child)… You can create another temp vector and do…  
hand.index[1].getWorldPosition( tempVector );  
then add that to the newDirection…

so here’s the steps…

hand.index[1].getWorldPosition( tempVector );  
newDirection.add( tempVector );  
hand.index[1].worldToLocal( newDirection );  
boneLookAtLocal(hand.index[1], newDirection );

Try that…

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 1:35am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/7 "2021-08-19T01:35:39Z")

</div>

doesn’t work ☹

 ![i7](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/6/f697640ccf7c1254a1dbcaa8492a19cdb70d4b97.png)

```javascript
        boneLookAtLocal(hand.index[0], new THREE.Vector3(0, 1, 1))
        let newDirection = new THREE.Vector3(0, 0, 1)
        let tempVector = new THREE.Vector3()
        hand.index[1].getWorldPosition( tempVector );
        newDirection.add( tempVector );
        hand.index[1].worldToLocal( newDirection );
        boneLookAtLocal(hand.index[1], newDirection );

```

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 19, 2021, 2:40am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/8 "2021-08-19T02:40:57Z")

</div>

Ok…  
Try…

```
    boneLookAtLocal(hand.index[0], new THREE.Vector3(0, 1, 1))
    let newDirection = new THREE.Vector3(0, 0, 1)
    let tempVector = new THREE.Vector3()
    hand.index[1].getWorldPosition( tempVector );
    newDirection.add( tempVector );
    hand.index[1].parent.worldToLocal( newDirection );
    newDirection.sub( hand.index[1].position );
    boneLookAtLocal(hand.index[1], newDirection );

```

I think that’ll work, heh… it will convert the position to the parent’s local space, and then when subtract the bone’s position it will have the final position to look at locally.

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 2:59am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/9 "2021-08-19T02:59:34Z")

</div>

> [@prominent](#):
>
> ```javascript
> boneLookAtLocal(hand.index[0], new THREE.Vector3(0, 1, 1))
> let newDirection = new THREE.Vector3(0, 0, 1)
> let tempVector = new THREE.Vector3()
> hand.index[1].getWorldPosition( tempVector );
> newDirection.add( tempVector );
> hand.index[1].parent.worldToLocal( newDirection );
> newDirection.sub( hand.index[1].position );
> boneLookAtLocal(hand.index[1], newDirection );
> 
> ```

![i8](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/1/f1be1ae881eeb16d937af0a85435f53943fdb87e.png)

I dont know why this doesnt work either, that should work in my head

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 19, 2021, 3:19am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/10 "2021-08-19T03:19:46Z")

</div>

What does it look like with the visual indicators for the bone’s axis? Maybe your lookat function is rotating around the wrong axis? I know that objects in three.js look down the z axis, and so that axis would control the Roll I think. y would be Yaw, and x would be Pitch… at least I think so… Your function has them differently. Maybe you can try changing those?

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 3:24am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/11 "2021-08-19T03:24:05Z")

</div>

> [@prominent](#):
>
> ```javascript
> boneLookAtLocal(hand.index[0], new THREE.Vector3(0, 1, 1))
> let newDirection = new THREE.Vector3(0, 0, 1)
> let tempVector = new THREE.Vector3()
> hand.index[1].getWorldPosition( tempVector );
> newDirection.add( tempVector );
> hand.index[1].parent.worldToLocal( newDirection );
> newDirection.sub( hand.index[1].position );
> boneLookAtLocal(hand.index[1], newDirection );
> 
> ```

 ![i9](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/4/6/46b1821f98e3db6b7d38a168165ee1c6150c613e.png)

is this what you mean by visual indicators, the axis helpers? And okay ill try setting the rotations as (pitch, yaw, roll) and other combinations see if that changes it

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 3:46am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/12 "2021-08-19T03:46:04Z")

</div>

@prominent I think I found a different solution, attach the bone in question to the scene before rotating it to rotate it on the global access instead of local and then reattach the bone to its parent:

```javascript
function boneLookAtLocal(bone, position) {
    bone.updateMatrixWorld()
    let direction = position.clone().normalize()
    let pitch = Math.asin(-direction.y)// + bone.offset
    let yaw = Math.atan2(direction.x, direction.z); //Beware cos(pitch)==0, catch this exception!
    let roll = Math.PI;
    bone.rotation.set(roll, yaw, pitch);
}

function boneLookAtWorld(bone, position) {
    scene.attach(bone)
    boneLookAtLocal(bone, position)
    bone.parent.attach(bone) 
}

boneLookAtWorld(hand.wrist, new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[0], new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[1], new THREE.Vector3(1, 0, 1))
boneLookAtWorld(hand.index[2], new THREE.Vector3(0, -1, 0)) 

```

yields:

 ![i10.PNG](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/f/3/f3d8634ad339ac676ba2e0dbcf603bb738760be7.jpeg)

which is how is exactly what I want! However, if we rotate the wrist right after those 4 calls in a different direction:

 ![i11](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/0/8/08706c53881f0cfd4d6ac0c0968a72789c4c5d93.png)

The wrist rotates without the rest of the finger. And if you noticed in the previous picture, the blue and green lines that make up the finger on the skeleton helper disappeared, so I’m thinking that when I call attach() it removes the bond from following the rotation of the parent.

Is there anyway to “re-astablish” that bond without resetting the fingers rotations? or anyway to capture the position it would be in and then move it there or?

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 19, 2021, 3:57am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/13 "2021-08-19T03:57:14Z")

</div>

hm, that’s interesting to know… I haven’t worked much with skinned meshes, so I’m not sure.

I was going to suggest maybe using the built in lookAt() function of the objects/bones instead of your function… to look at the position, to at least test and see if that points them in the correct direction( they might not have their roll correct though)…

I’m not sure how to rebind the mesh to the bone if attaching removes it.

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 4:00am UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/14 "2021-08-19T04:00:00Z")

</div>

Thats a good idea, let me try that as well. Thank you for you help so far!

---

<div class="post-metadata">

**Author:** ![user1234](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/user1234/32/20176_2.png) [@user1234](https://discourse.threejs.org/u/user1234)\
**Post date:** [August 19, 2021, 7:14pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/15 "2021-08-19T19:14:42Z")

</div>

@prominent in case it helps you one day, I figured it out!

The reason this is happening is because in:

```javascript
function boneLookAtWorld(bone, v) {
    scene.attach(bone)
    boneLookAtLocal(bone, v)
    bone.parent.attach(bone)
}

```

when we attach the bone to scene, scene becomes the bone’s new parent. So after we perform the rotation via boneLookAtLocal() and reattach the bone, we aren’t reattaching the bone to the original parent! The bone is just being reattached to the scene which it is already attached to.

This is solved by changing boneLookAtWorld() to:

```javascript
function boneLookAtWorld(bone, v) {
    const parent = bone.parent;
    scene.attach(bone)
    boneLookAtLocal(bone, v)
    parent.attach(bone)
}

```

---

<div class="post-metadata">

**Author:** ![prominent](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@prominent](https://discourse.threejs.org/u/prominent)\
**Post date:** [August 19, 2021, 7:44pm UTC](https://discourse.threejs.org/t/need-help-figuring-out-bone-rotations-please-help/29059/16 "2021-08-19T19:44:07Z")

</div>

oh yeah, that makes sense 🙂  
nice that you got it working!
