How to correctly setup a proxy node for RotationGizmo

For anyone interested , this is the latest playground:


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

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

Here are things that went wrong:

  1. Initial rotation is wrong.
    initial rotation
  2. The rotation changed greatly when rotating around a special direction.
    bad rotation

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

I did a quick example : Babylon.js Playground

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.

1 Like

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.

yes, this needs to be computed :

2 Likes

Thanks for that.

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

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

proxy gizmo:

inspector gizmo:

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

proxy gizmo:

inspector gizmo:

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

1 Like

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

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.

1 Like

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?

        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);

I’ve asked AI about that, and it said that’s a limit in current decompose algorithm, and singular value decomposition is needed in case of “sheared matrix”.
A few searches leads me to 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?

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

1 Like