<p>The bone transforms are relative to their parent in the hierarchy. That's the point of the hierarchy, i.e. when you move your arm, your hand and fingers go along with it. So when an animation (or whatever) changes the transform of A, then bones B and C are supposed to move along with it.</p>

<p>This is accomplished by defining bone B relative to A, and C relative to B, and so on.</p>

<p>Therefore, to get the final transform from bone local space to world space, you have to combine all the transforms from the current bone up the hierarchy to the root.</p>

<p>To put it another way:</p>

<ul>
<li>The <code>localTransform</code> of C takes you to B's local space.</li>
<li>Then the <code>localTransform</code> of B takes you to A's local space.</li>
<li>Then the <code>localTransform</code> of A takes you to world space (since A is the root).</li>
</ul>

CC BY-SA 4.0
2018-05-11T04:40:23.903Z
I thought the local transform of A should take you to B local space, then the local transform of B take you to C local space? for example, for a vertex in world space to get into C space, it needs to be multiplied by CBA*v. Then to get it from C space to world space you would get the inverse of it, which is (CBA)^-1 or A^-1*B^-1*C^-1?
Manh Nguyen
CC BY-SA 4.0
2018-05-11T04:46:37.067Z
@ManhNguyen Local transform takes you from the local space to the parent space, not the other way around. C space to world space would be ABC*v.
Nathan Reed
CC BY-SA 4.0
2018-05-11T04:54:20.820Z
Usually the matrices are set up to describe object in parent space. But it is offcourse possible to store the inverses as the matrix like @ManhNguyen suggests. Ive never seen it done, somebody asked this i think and the answer was that for some reason it feels unnatural. Just as possible to set it up this way just like its possible to have a transposed matrix order in which case all calculations are reverse. So the dev needs to know this.
joojaa
CC BY-SA 4.0
2018-05-11T05:07:15.840Z
@ManhNguyen that wouldnt work if you wanted to have multiple separate objects. But if you shift your reasoning one node up then it would work. Modeller has some leeway in deciding how the computation happens, but it seems that describing the world as a function of objects is a bit out there, but possible.
joojaa
CC BY-SA 4.0
2018-05-11T05:27:21.023Z
@joojaa I followed the math you guys give me and the animation is only correct for 1 out of the 2 models I am working on. Both are loaded by Assimp. The only differences I can think of are that 1 is a fbx file and the other is a dae file and that 1 has multiple mesh not situated at root scene and the other does. Is there something I am missing? The Assimp loader is able to load both models correctly.
Manh Nguyen
CC BY-SA 4.0
2018-05-11T04:26:48.890Z
2018-05-11T04:26:48.890Z
Nathan Reed
<p>Let's say I have the following hierarchy:</p>

<pre><code>Bone A
    Bone B
        Bone C
</code></pre>

<p>Here's how most tutorial is telling me how to calculate the finalMatrix to be sent to shader.</p>

<pre><code>bonePoseToWorldPose(Joint * joint, glm::mat4 &amp; parentTransform, glm::mat4 &amp; globalInverseTransform) {
    joint-&gt;finalTransform = parentTransform * joint-&gt;localTransform; // local transform is the result of interpolating 2 keyframes
    for (int i = 0; i &lt; joint-&gt;children.size(); i++) {
        bonePoseToWorldPose(joint-&gt;children[i], joint-&gt;finalTransform, globalInverseTransform);
    }
    joint-&gt;finalTransform = joint-&gt;finalTransform * joint-&gt;inverseBindTransform;  
}
</code></pre>

<p>Doing it this way, the final transform in bone C for example, would be localTransformA * localTransformB * localTransformC * jointInverseBindTransform.</p>

<p>Which does not make sense to me, and none of the tutorial satisfactorily explains that. Let's go back to the example again. the inverse bind transform would bring a vertex V from mesh space to bone space of Bone C. At bone space C, it would be multiplied with the localTransformC (or interpolated transform C), which I guess would set the model to our desired pose. But what are A and B doing there? </p>

<opengl><linear-algebra>
Skeletal animation: What is the purpose of multiplying interpolated bone matrix with parent's matrix?
Manh Nguyen
# Skeletal animation: What is the purpose of multiplying interpolated bone matrix with parent's matrix?

(Asked by: username_0 on 2018-05-11)

Let's say I have the following hierarchy:

```
Bone A
    Bone B
        Bone C

```

Here's how most tutorial is telling me how to calculate the finalMatrix to be sent to shader.

```
bonePoseToWorldPose(Joint * joint, glm::mat4 & parentTransform, glm::mat4 & globalInverseTransform) {
    joint->finalTransform = parentTransform * joint->localTransform; // local transform is the result of interpolating 2 keyframes
    for (int i = 0; i < joint->children.size(); i++) {
        bonePoseToWorldPose(joint->children[i], joint->finalTransform, globalInverseTransform);
    }
    joint->finalTransform = joint->finalTransform * joint->inverseBindTransform;  
}

```

Doing it this way, the final transform in bone C for example, would be localTransformA \* localTransformB \* localTransformC \* jointInverseBindTransform.

Which does not make sense to me, and none of the tutorial satisfactorily explains that. Let's go back to the example again. the inverse bind transform would bring a vertex V from mesh space to bone space of Bone C. At bone space C, it would be multiplied with the localTransformC (or interpolated transform C), which I guess would set the model to our desired pose. But what are A and B doing there?

**Tags:** opengl, linear-algebra


---

## 1 answers

### Answer by username_1 on 2018-05-11. Score: 3

The bone transforms are relative to their parent in the hierarchy. That's the point of the hierarchy, i.e. when you move your arm, your hand and fingers go along with it. So when an animation (or whatever) changes the transform of A, then bones B and C are supposed to move along with it.

This is accomplished by defining bone B relative to A, and C relative to B, and so on.

Therefore, to get the final transform from bone local space to world space, you have to combine all the transforms from the current bone up the hierarchy to the root.

To put it another way:

* The `localTransform` of C takes you to B's local space.
* Then the `localTransform` of B takes you to A's local space.
* Then the `localTransform` of A takes you to world space (since A is the root).

> **Comments:**
> **username_0**: I thought the local transform of A should take you to B local space, then the local transform of B take you to C local space? for example, for a vertex in world space to get into C space, it needs to be multiplied by CBA*v. Then to get it from C space to world space you would get the inverse of it, which is (CBA)^-1 or A^-1*B^-1*C^-1?  
> **username_1**: @username_0 Local transform takes you from the local space to the parent space, not the other way around. C space to world space would be ABC*v.  
> **username_2**: Usually the matrices are set up to describe object in parent space. But it is offcourse possible to store the inverses as the matrix like @username_0 suggests. Ive never seen it done, somebody asked this i think and the answer was that for some reason it feels unnatural. Just as possible to set it up this way just like its possible to have a transposed matrix order in which case all calculations are reverse. So the dev needs to know this.  
> **username_2**: @username_0 that wouldnt work if you wanted to have multiple separate objects. But if you shift your reasoning one node up then it would work. Modeller has some leeway in deciding how the computation happens, but it seems that describing the world as a function of objects is a bit out there, but possible.  
> **username_0**: @username_2 I followed the math you guys give me and the animation is only correct for 1 out of the 2 models I am working on. Both are loaded by Assimp. The only differences I can think of are that 1 is a fbx file and the other is a dae file and that 1 has multiple mesh not situated at root scene and the other does. Is there something I am missing? The Assimp loader is able to load both models correctly.  

---

