# How to correctly setup a proxy node for RotationGizmo

**URL:** <https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354>\
**Category:** Questions\
**Tags:** gizmo, quaternion, math, rotation, matrix\
**Created:** [July 3, 2025, 8:24am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354 "2025-07-03T08:24:43Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 3, 2025, 8:24am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/1 "2025-07-03T08:24:43Z")

</div>

For anyone interested , this is the latest playground:

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

* * *

I’m using RotationGizmo for nodes with non uniform scaling, and searched the forum to find this post about proxing transfroms.

> [@Rotate gizmo not working with non uniform mesh scaling](https://forum.babylonjs.com/t/rotate-gizmo-not-working-with-non-uniform-mesh-scaling/37586/5):
>
> Since bjs 3 or 4, rotation with non uniform scaling makes the mesh to explode because inconsistency between the world matrix and orientation quaternion. I’ve changed that recently to display a message instead of watching NaN vertices everywhere. It’s possible to have non uniform scaling and rotation but you have to set updateGizmoRotationToMatchAttachedMesh to false. Another solution is to use the gizmo with a proxy transform and apply rotation to the mesh when dragging gizmo. I’ll find time…

I’ve tried to setup a proxy node but failed, see this playground:

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

Here are things that went wrong:

1. Initial rotation is wrong.  
 ![initial rotation](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/5/e/5ecdbe058e851aa83fb5b9c5310345065fdac03f.gif)
2. The rotation changed greatly when rotating around a special direction.  
 ![bad rotation](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/e/a/ea7d316427c2c78af940cd3d93df512b508e2d45.gif)

So how to correctly setup a proxy node for RotationGizmo like that?

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [July 3, 2025, 9:15am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/2 "2025-07-03T09:15:33Z")

</div>

I did a quick example : [Babylon.js Playground](https://playground.babylonjs.com/#XZQ05H)

The important part is to not decompose/recompose matrix or even use it but use the quaternion directly.

The core of the problem is passing this orientation information bertween the various part of the engine.

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 3, 2025, 9:21am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/3 "2025-07-03T09:21:46Z")

</div>

Good, this works smoothly, but what if the box have parent nodes? My playground is made to simulate this case, but absoluteRotationQuaternion does not seem to work.

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [July 3, 2025, 9:45am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/4 "2025-07-03T09:45:07Z")

</div>

yes, this needs to be computed :

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

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 4, 2025, 1:18am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/5 "2025-07-04T01:18:00Z")

</div>

Thanks for that.

After some hours I managed to setup the correct initial position, but there are still visible diff in rotation.

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

To show it more clearly, the gizmo with proxy have black lines, and the inspector gizmo has its default color.

proxy gizmo:

 ![proxy gizmo](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/0/d/0de127db5a9d64fda746c2e0e760eaaec03d9989.png)

inspector gizmo:

 ![inspector gizmo](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/9/7/9798bd38d30e10706fec0422ace22d81fd675405.png)

> **old post, now solved**
>
> ~~If the box have multi levels of hierarchy, should the parents be iterated in forward or reverse order, to multply rotationQuaternions, in initialization and onDragObservable?~~
> 
> ~~In my example there still seems to be somthing wrong with the initial postion and rotation~~  
> [https://playground.babylonjs.com/#GIZMO1#2](https://playground.babylonjs.com/#GIZMO1#2)
> 
> proxy gizmo:
> 
> ![proxy gizmo](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/3/3/33bda0679d2a65d619fd19c802fb0c25765cbe48.png)
> 
> inspector gizmo:
> 
> ![inspector gizmo](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/a/3/a3a08ed2a20ec3a5bdd672b37f0b509973b81e34.png)

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [July 4, 2025, 8:33am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/6 "2025-07-04T08:33:44Z")

</div>

I don’t think the inspector gizmo handles properly this kind of hierarchy. I would not trust its position/orientation.

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 4, 2025, 8:41am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/7 "2025-07-04T08:41:12Z")

</div>

So how can I verify the correctness of the gimo? Is there something I can compare with?

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [July 4, 2025, 9:54am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/8 "2025-07-04T09:54:48Z")

</div>

orientations accumulate. So the hierarchy leave (the end of the transform hierarchy tree) orientation should be the same with the proxy and the object it’s attached to. basically, world space quaternions of the proxy and the box should be the same. And to compute that world space quaternion, multiply the quaternion by the world space quaternion of its parent recursively.

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 5, 2025, 2:14am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/9 "2025-07-05T02:14:12Z")

</div>

I’ve made a pg implementing this with the help of ai, can I say it’s correct enough if the `maxErr` less than `FLT_EPSILON` or `Number.EPSILON`?

```js
        tempQuat2.set(0, 0, 0, 1);
        for (let i = nodes.length - 1; i >= 0; i--) {
            tempQuat2.multiplyInPlace(getQuaternion(nodes[i]));
        }
        var dot = tempQuat2.normalize().dot(getQuaternion(proxy).normalize());
        var maxErr = Math.abs(Math.abs(dot) - 1);
        const FLT_EPSILON = 1.19209290e-07;
        const angleErr = 2 * Math.acos(Math.min(1, Math.abs(dot))) * 180/Math.PI;
        console.log(maxErr, maxErr <= FLT_EPSILON, 'angular error (deg):', angleErr);

```

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

---

<div class="post-metadata">

**Author:** ![kzhsw](https://avatars.discourse-cdn.com/v4/letter/k/848f3c/32.png) [@kzhsw](https://forum.babylonjs.com/u/kzhsw)\
**Post date:** [July 5, 2025, 4:00am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/10 "2025-07-05T04:00:08Z")

</div>

> [@Cedric](#):
>
> The important part is to not decompose/recompose matrix

I’ve asked AI about that, and it said that’s a limit in current decompose algorithm, and [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) is needed in case of “sheared matrix”.  
A few searches leads me to [svd-js](https://www.npmjs.com/package/svd-js), and here is an example of using it with RotationGizmo.  
So, could there be a real fix with this, so that no proxy node needed?

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

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [July 7, 2025, 7:56am UTC](https://forum.babylonjs.com/t/how-to-correctly-setup-a-proxy-node-for-rotationgizmo/59354/11 "2025-07-07T07:56:03Z")

</div>

I think long term best solution is to not use decompose/recompose in gizmo code and keep the TRS values for whole transformation pipeline.
