Aligning a normal to an axis

I’m trying to orient a mesh after applying a rotation by aligning the normal of a face with an axis (the local Y axis in world coords). I created the above PG to handle the simple case of aligning a normal with the positive Y axis. If I comment out line 13 in the PG (which applies an initial random rotation), then it works as expected; a random facet is chosen and after 5 seconds the mesh is rotated so that the facet normal aligns with the +y axis. However, if I apply a random initial rotation, I do not get an alignment. Can anyone see what I am doing wrong?

Will it work as expected with

box.computeWorldMatrix()

Example - https://playground.babylonjs.com/#3TUYRR#3

1 Like

Thanks, I did forget to recompute the matrix, but it still isn’t working as expected, even if I force it. It should result in the facet normal pointing straight up.

Here is a way that could work I guess: https://playground.babylonjs.com/#3TUYRR#5

Seems to me that box.getFacetNormal(facetIndex) returns a value in worldCoordinates.

So as we have already applied a rotation at line 13, the rotation quaternion we compute with quaternionFromTo(box.getFacetNormal(facetIndex), BABYLON.Axis.Y) is from a randomly rotated box to axis Y.

Because we override the first random quaternion with another random quaternion, we get a random rotation.

Note that if you multiply line 18 quaternion by line 13 quaternion the box is straightup, like you expected, see playground below.

1 Like

Thanks. This works great with the box mesh now even if I apply multiple random rotations; though I’m not sure I understand why the rotation quaternion has to be multiplied by the current rotation. In any case, if I use an imported mesh rather than the box, the same approach doesn’t work (see https://playground.babylonjs.com/#3TUYRR#8). Note that for the the imported mesh I had to change line 71 to subtract get the normal to face outward. I’m guessing that has something to do with the -1 z scale and or the 180 degree rotation about Y that is applied when a GLTF file is imported? More importantly, the final rotation to point the normal up doesn’t seem to be working when the mesh is imported. I am applying the transforms to the root node (also tried applying rotation to the d6 mesh and get the same result. How can apply the correct rotation in the case where the mesh is imported?

I see what I did wrong. I didn’t was multiplying the root quaternion by the box quaternion rather than the root quaternion which is the one being modified. However, when I run the PG with the GLTF file, the normal always ends up facing down, but when I run with the box mesh it ends facing up, even though I am using the positive Y axis for both. I don’t see how the transform applied to a GLTF file to convert from left hand to right hand (-1 z scale and 180 about y) would cause this issue. What am I missing?

cc @bghgary if he has an idea. Can you share your current playground state ?

I’ll investigate once I get this. :slight_smile:

2 Likes

https://playground.babylonjs.com/#3TUYRR#10. Interestingly, I have another PG where I use the current rotation to transform the Y axis (https://playground.babylonjs.com/#CJ7MWE#7) and the box ends up facing correctly, so clearly it has something to do with the GLTF transformation. Thanks so much for the help.

Could you explain why the multiplication is necessary? Clearly I don’t understand Quaternions as much as I thought.

To me it makes more sense to think it in 2 dimensions

You have an object with a rotation property, it’s an angle in degree, R.

First, it’s 0°, straight up.

Then you give it a random rotation, Random°, line 13, the stickman tilts.

Then you compute the “inverse rotation”, -Random°

If you replace the rotation property with -Random°, it’s not straight up.

If you combine both rotation (in 2D, you would add them), it’s straight up as Random + - Random = 0

To combine two quaternion, you have to multiply them, but I don’t know the underlying math, “it just works”.

3 Likes

Check the PG example with Quaternion | Babylon.js Documentation

Even in 2D to carry out a rotation using maths you use matrices. To rotate a 2D vector you multiply by a rotation matrix to give another 2D vector and to apply a second rotation you multiply this by another matrix. Or you can multiply the matrices first and mutiply the original vector by the matrix result. Multiplying rotation matrices combines the rotations.

In 3D, quaternions are matrices in disguise and so you mutiply them to combine rotations.

3 Likes

Thanks. I get it. I keep falling into the trap of thinking of the rotation quaternion as cumulative. It’s not. To make it cumulative you have to multiple the current rotation by the new rotation you want to apply.

1 Like

It sounds like I’m too slow :wink: Let me know if you need further help.

Thanks for the help everyone. Here is the finished product for now. Would love any suggestions on improvements. https://playground.babylonjs.com/#CJ7MWE#13

2 Likes