# Inconsistent GLTF bone transformations

**URL:** <https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358>\
**Category:** Bugs\
**Created:** [April 14, 2022, 12:20pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358 "2022-04-14T12:20:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [April 14, 2022, 12:20pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/1 "2022-04-14T12:20:31Z")

</div>

Hi,  
some GLTF characters have their bone positions and/or rotations messed up. I can’t say what’s exactly wrong, but BoneAxesViewer also gets it wrong. That’s regression in v5.  
Playground: [Babylon.js Playground](https://playground.babylonjs.com/#H925CH)

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/e/5/e5c7cbc28ac39c7b6828725f15a2e4db2b247106.jpeg)

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [April 14, 2022, 4:15pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/2 "2022-04-14T16:15:58Z")

</div>

pinging @bghgary

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [April 14, 2022, 4:19pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/3 "2022-04-14T16:19:35Z")

</div>

I’m doing a first check to see if I can fix within the next hour

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [April 14, 2022, 4:49pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/4 "2022-04-14T16:49:23Z")

</div>

Ok I found the root cause 🙂  
The way we handled skeleton within glTF was a bit too convoluted in 4.2

So we decided to simplify it a bit. From the breaking changes of 5.0:  
[https://doc.babylonjs.com/whats-new#breaking-changes](https://doc.babylonjs.com/whats-new#breaking-changes)

> Loading glTF assets with skins now places skinned meshes as siblings of the corresponding skeleton root nodes instead of using `skeleton.overrideMesh`

(@bghgary I think we should document that and how it works in the skeleton documentation)

Here is the fix for your PG:  
[GLTF character bone positions | Babylon.js Playground (babylonjs.com)](https://playground.babylonjs.com/#H925CH#2)

The idea is to figure out which transformNode is the root of the actual mesh

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [April 14, 2022, 8:51pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/5 "2022-04-14T20:51:39Z")

</div>

> [@Deltakosh](#):
>
> (@bghgary I think we should document that and how it works in the skeleton documentation)

Maybe we need a link. I documented how this works for gltf here: [glTF 2.0 Skinning | Babylon.js Documentation](https://doc.babylonjs.com/divingDeeper/importers/glTF/glTFSkinning)

---

<div class="post-metadata">

**Author:** ![Deltakosh](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/deltakosh/32/26635_2.png) [@Deltakosh](https://forum.babylonjs.com/u/Deltakosh)\
**Post date:** [April 14, 2022, 9:02pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/6 "2022-04-14T21:02:52Z")

</div>

Even better:  
[GLTF character bone positions | Babylon.js Playground (babylonjs.com)](https://playground.babylonjs.com/#H925CH#6)

I’m using `node.getTransformNode()` on the root bone to get the mesh to use with BoneAxesViewer

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [April 14, 2022, 9:09pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/7 "2022-04-14T21:09:31Z")

</div>

… and that seems to be container.skeletons[0].bones[0].getTransformNode() - at least as far as BoneAxisViewer is concerned, at least in the playground 🙂  
Locally I have a twilight zone: two BoneAxisViewers, for upper and lower leg, and they work fine as long as I update lower one first 😁 Otherwise I get like

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/8/5/852963136e9408b7a1389441610e7728c46f6a6e.jpeg)  
Something seems off with transformation hierarchy…

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [April 29, 2022, 12:35pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/8 "2022-04-29T12:35:29Z")

</div>

I have update on this: [GLTF character bone positions | Babylon.js Playground (babylonjs.com)](https://playground.babylonjs.com/#H925CH#7)  
This looks fine; but create root mesh and bone absolute position goes way away.

So really, what do I need to do to get actual bone position?

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [April 29, 2022, 3:02pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/9 "2022-04-29T15:02:04Z")

</div>

cc @bghgary

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [April 29, 2022, 5:58pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/10 "2022-04-29T17:58:22Z")

</div>

> [@Josip\_Almasi](#):
>
> This looks fine; but create root mesh and bone absolute position goes way away.

Sorry, I’m not understanding this. What do you mean?

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [May 3, 2022, 8:45am UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/11 "2022-05-03T08:45:47Z")

</div>

@bghgary see the playground above, in particular

```auto
            // replace this with with that to mess it up
            var root = container.meshes[0];
            //var root = container.createRootMesh();

```

and

```auto
            var absolutePos = bone.getAbsolutePosition(transform);
            console.log(absolutePos);
            var sphere = BABYLON.MeshBuilder.CreateSphere();
            sphere.position = absolutePos;

```

The absolute position of the bone changes from  
\_x: -1.195454716682434, \_y: 1.6862452030181885, \_z: -0.047228556126356125  
to  
\_x: -3.9090933799743652, \_y: 33.72490310668945, \_z: 0.9445710778236389  
when the root mesh is created. Not very absolute is it? 😉  
So is it expected behavior? If it is, what do I need to do to get actual absolute position of the bone?

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [May 3, 2022, 4:06pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/12 "2022-05-03T16:06:32Z")

</div>

You would need to force computing the world matrices if you do changes before using them: [https://playground.babylonjs.com/#H925CH#8](https://playground.babylonjs.com/#H925CH#8)

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [May 3, 2022, 6:07pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/13 "2022-05-03T18:07:12Z")

</div>

Oh dang, but on transform node!  
I’ve been trying on bone 🙂  
Alright thanks @sebavan

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [June 14, 2022, 9:40am UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/14 "2022-06-14T09:40:05Z")

</div>

What a mess 😁  
Took me quite a while to pinpoint where things have gone wrong, had to look for babylon 4 on cdns to compare.  
So Bone.getAbsolutePosition() used to return:  
{X: 0.1375466307330413 Y:1.6750438330035953 Z:0.01731602581149172}  
with babylon 4, and with 5 returns  
{X: 0.13754705781588328 Y: -0.017311424858179172 Z: 1.6750443792873426}  
Care to guess how it affects IK? 😉  
No big deal, says me, I’ll just use Bone.getAbsolutePosition(someTransform), right?  
Yeah right.  
This position mess only reflects what happened with rotation matrix. Rotation of the same bone was  
{X: 0.7772532463104096 Y:0.40210674488017334 Z:0.40210645730669714 W:-0.26925494988232973}  
with 4, and with 5 is  
{X: -0.35920901177680326 Y: -3.02053400145857e-7 Z: -0.5686636932234524 W: 0.7399930535454382}  
And I can’t create playground example with babylon 4, right?  
So instead of wasting even more time, let me simply ask.  
For IK I need two vectors: current arm vector, and target vector.  
Then I simply  
var finalRotation = new BABYLON.Matrix();  
BABYLON.Matrix.RotationAlignToRef(armVector.normalizeToNew(), targetVector.normalizeToNew(), finalRotation);  
and use this rotation quaternion for either directly setting arm quaternion or animation.  
So how do I get target vector and arm vector, in the same coordinate system that bone quaternion uses?  
I see bunch of methods containing ‘local’ and ‘absolute’ in their names, but absolute obviously is not absolute, and what’s ‘local’ supposed to mean?  
So please, **how can I convert a vector in global coordinate system** (intentionally avoiding word ‘absolute’) **to coordinate system of a bone**?  
Some context - this doesn’t work with babylon 5:

[![](https://img.youtube.com/vi/05Tmra7nSTY/maxresdefault.jpg "VRSpace.org presentation at VR Days Europe 2020") ](https://www.youtube.com/watch?v=05Tmra7nSTY)

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [June 14, 2022, 4:43pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/16 "2022-06-14T16:43:14Z")

</div>

Assigned @bghgary on June 14, 2022, 4:43pm UTC



---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [June 14, 2022, 5:35pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/17 "2022-06-14T17:35:00Z")

</div>

> [@Josip\_Almasi](#):
>
> Bone.getAbsolutePosition()

What bone are you referring to here?

> [@Josip\_Almasi](#):
>
> And I can’t create playground example with babylon 4, right?

You can create a playground with 4 by selecting the version near the top right.

> [@Josip\_Almasi](#):
>
> So how do I get target vector and arm vector, in the same coordinate system that bone quaternion uses?

If you can get it working with Babylon 4.2.1 in the playground, I can look into why it doesn’t work in 5.x.

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [June 14, 2022, 6:38pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/18 "2022-06-14T18:38:53Z")

</div>

@sebavan I appreciate it, but ‘magic’ is not really a way to go 🙂 Clear way to convert from this to that coordinate system is, and it might already be there.

@bghgary that’s the catch, it’s some bone (arm,leg…) with some characters. When I look at the avatar structure, there’s exactly one difference: TransformNode child of RootNode (model correction matrix) is rotated by 90 degrees for some models and not rotated for others, see attached images (both characters are supposed to touch the sphere). But all characters are rotated by -90 in RootNode (gltf orientation matrix). So for the characters that have these rotations zeroing each other out, my math works fine, and for others, not.  
And more than that I really can’t say 🙂  
Because, well everyone works with predefined character structure, right? Well I’ve come up with the system that recognizes structure of some 96% rigged characters. I just download them from sketchfab, and have no idea where they come from, how they are made, and what bone orientations are.  
You know they say, give me a firm spot on which to stand, and I shall move the world 😉

OK thanks, I’ll come up with a playground.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/b/0/b03c7225e1fe226b3d7be116b6226002ff73fc78.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/8/a/8a2cc2ccbe45bdce730692d8dbc125b412eff94d.jpeg)

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [June 14, 2022, 7:01pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/19 "2022-06-14T19:01:32Z")

</div>

I’m not asking for generically what bone. I need a specific example, so I can debug the problem.

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [June 14, 2022, 7:32pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/20 "2022-06-14T19:32:33Z")

</div>

> [@Josip\_Almasi](#):
>
> magic

By magic I meant a flag loading as before but it was for a totally different issue

---

<div class="post-metadata">

**Author:** ![Josip\_Almasi](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/josip_almasi/32/6391_2.png) [@Josip\_Almasi](https://forum.babylonjs.com/u/Josip_Almasi)\
**Post date:** [June 14, 2022, 9:00pm UTC](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358/21 "2022-06-14T21:00:54Z")

</div>

@bghgary here’s the playground 1, for babylon 4:

> **[Babylon.js Playground](https://playground.babylonjs.com/#H925CH%2332)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Some bookkeeping but all fine.  
And here’s the same with babylon 5:

> **[Babylon.js Playground](https://playground.babylonjs.com/#H925CH%2333)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

Well I just can’t figure out how to get simple position of a bone.  
Funny though, things change with call to container.createRootMesh(). It almost becomes usable, except left and right side switched places 🙂

[Next page](https://forum.babylonjs.com/t/inconsistent-gltf-bone-transformations/29358.md?page=2)
