Rotation by world matrix

Hi everyone.

i’m rotating multiple meshs which are located at some arbitrary x,y,z.
i added it to an Object3D to rotate it along the center of the “world” at 0,0,0.

ortating the parent Object3D called “pivot” is perfect - it rotates everything around the world center.
however, after rotating along a single axis, the next rotation is relative to the current orientation of the Object3D, and not according to the corrosponding world axis.

I’m using pivot.rotation.x and set it to 90 degrees which works perfectly. However, for the next rotation along the y axis, it now rotates along the z axis :frowning:

i’ve tried using rotateOnWorldAxis, rotateOnAxis - all rotate the object according to the local rotation per the example and not according to the world’s X/Y/Z axes.

how do i rotate an object3D by a world axis?

You can take pivot even further with pitch and yaw.

Maybe this is the effect you want.

hi, thank you for the reply.

i’m afraid this is not what i’m looking for - rather something much more simple.

here’s an example:
take a mesh, move it to <100,100,100>
add it to an object3d, which is located at <0,0,0>
rotate it 90deg at the y axis.
now (try) to rotate it 90deg at the x axis - it will not rotate along the x world axis, but rather on the local axis, which is what i’m asking about.

how do i make every rotation to be according to the world and not the local?

do you mean like what happens to the cubelets on a rubiks cube?

yes, thank you very much!

i’m going over the code, trying to understand what’s the difference.
i’m my code, i use mesh.rotation.x/y/z = value, but everytime after applying rotation on another axis - it rotates according to the local rotation and not the world rotation.

i assume it has something with quaternion? or attaching and detaching to pivot elements?
may i ask for your help clarifying what’s this example is doing that i’m missing?

 function resetCubeGroup(cubeGroup, rotationGroup) {
          rotationGroup.children
              .slice()
              .reverse()
              .forEach(function (c) {
                  cubeGroup.attach(c)
              })
          rotationGroup.quaternion.set(0, 0, 0, 1)
      }

I can’t remember how all that code works any more. it was written in a rabbit hole refactoring moment.

But the general idea is,

You have an objectA in the scene, and you want it rotated x,y or z.
Create a new Object3D and attach your objectA to it.
Rotate the Object3D x,y or z.
Then detach the objectA, by attaching it back to the scene.
Reset the empty Object3D so it doesnt accumulate rotations and become gimbal locked in case you want to use it again.

if you want to rotate objectA again in some other rotation.
position the Object3D at desired center of rotation,
attach objectA to it
rotate the Object3D
detach objectA by attaching it back to the scene.

Object3D.attach → Adds object as a child of this, while maintaining the object’s world transform.

1 Like

thanks again!

tried that, worked perfectly, aside from having to add the new Object3D to the scene, as it won’t appear without it.

so this is the reason for rotationGroup.quaternion.set(0, 0, 0, 1) !

thanks a ton! really appreciated!

Yes, the cubelets get gimbal locked if i don’t reset the rotation group

1 Like

Attaching/detaching and rotation resetting is a nice solution. Here is an alternative (in case I have understood the issue correctly):

It looks like you are reusing the same Euler set of angles. Here is the effect that you get (left – original state, middle – after rotation x, right – after rotations x and y):

pivot.rotation.x = Math.PI/2;
pivot.rotation.y = Math.PI/2;

If you prefer to use rotation property (i.e. orientation via Euler angles), you could also try to reorder the angles before the change of each individual Euler angle – i.e., before changing an angle, make it the first one. Here is the result (the first two snapshots are the same, only the third one is different):

pivot.rotation.reorder( 'XYZ' ); // not needed as it is XYZ by default
pivot.rotation.x = Math.PI/2;
pivot.rotation.reorder( 'YZX' );
pivot.rotation.y = Math.PI/2;

2 Likes

this example was exactly what led me to post, thank you so much.

A follow up if i may, in this context:

I plan for the group object to rotate around an axis that is not the world, lets say 45 degrees tilted to the right. This way group.rotation will be relative to the last rotation, per the starting point of this post.

All of this, without affecting the child meshes.

What i did set the group object rotation prior to attaching the child meshes so it will not affect their rotation.

But unexpectedly, now Group.rotation.x / setRotationX is per world axis and not per the Group object rotation!

How do set the group object to rotate around its local axes and not the world axes?

Or phrased differently, how do i solve the same problem, but not for world axes, but for othes axes (given vector)?

Thanks for the help!

just found it. RotateOnAxis does the trick well!