How to use the rotation matrix correctly?

Hello everyone.

After days of research, the rotation matrices are not behaving like I expect, and I don’t know what I am missing. I need to define the rotation of each object in my scene in the form of three direction unit vectors, each one describing the direction of one local axis. Following this thread, I have created a simple scene with two axes. I am applying rotations to the second one, while the first one (in the center) shows the global coordinates.

In my case, the default direction vectors for an object are the following. These values mean that there is no rotation applied on the object.

Axis x: (1,0,0)
Axis y: (0,1,0)
Axis z: (0,0,1)

Following this criteria, I have tried to rotate the object 90º on the Y axis counter clockwise (so that the Z axis ends up pointing in the direction of the current x Axis):

const rotationMatrix = new THREE.Matrix4();
rotationMatrix.set( 
  0  ,0  ,-1 ,0
 ,0  ,1  ,0  ,0
 ,1  ,0  ,0  ,0
 ,0  ,0  ,0  ,1
 );
axes.rotation.setFromRotationMatrix(rotationMatrix);

The first issue that I have encountered is that the rotation is not made in the direction I expected; in this case, it is made clockwise instead of counter clockwise.

I can fix this inverting the local rotation after applying the rotation matrix:

axes.rotation.x *= -1;
axes.rotation.y *= -1;
axes.rotation.z *= -1;

So far, so good, and this works for rotations in all the axes. Nonetheless, there might be objects that have rotations in multiple axes. For example, I want to rotate this object not only 90º on the Y axis, but also 90º on the (global) Z axis. The result that I expect is an object that has the the local X pointing to the global -Z, the local Y pointing to the global X and the local Z pointing to the global -Y.

const rotationMatrix = new THREE.Matrix4();
rotationMatrix.set( 
 0  ,0  ,-1 ,0
,1  ,0  ,0  ,0
,0  ,-1 ,0  ,0
,0  ,0  ,0  ,1
);
axes.rotation.setFromRotationMatrix(rotationMatrix);
axes.rotation.x *= -1;
axes.rotation.y *= -1;
axes.rotation.z *= -1;

But this is what I get:

Is there something I missed about the rotation matrix?
Thank you in advance!

  1. Unless you’re doing it for the sake of learning matrices, you can use Matrix4.makeRotationAxis instead of writing the 1’s and 0’s by hand. (You can also read the transform matrices directly from the object to save them.)

  2. I recall exactly nothing from the university course about matrixes - but looking at this, this, and these docs - it doesn’t seem like the diagonal values are the only numbers you should care about when doing the rotations by hand. :thinking:

I am doing this as part of a IFC Loader for Three.js. In IFC files, the transformation of each object in space is given by three attributes:

  • Location: a 3d vector (x,y,z) that indicates the position of the object in space.

  • X Axis direction: a 3d vector (x1,x2,x3) that indicates the direction of the local X axis of the object relative to the X axis of the global coordinate system. For example: if the local X axis of a door is pointing to the global Y axis, this vector would be (0,1,0). If it was pointing to the negative global Z axis, this would be (0,0,-1).

  • Z Axis direction: Same as the X axis, but for the Z axis.

The Y axis is not given explicitly, but can be calculated as the product of X and Z.

What I am trying here is to convert this axis orientations (which are given by the IFC file) to Three.js rotations. Rotation matrices are the best way I could come up with (even though I could not make it work as I expected). Any other method or suggestion to archieve this would be welcomed as well. :slightly_smiling_face:

When taking about x-axis, y-axis and z-axis direction, you actually refer to the right, up and forward vectors which compose the basis of a matrix.

If you want to convert a coordinate system (e.g. from IFC) to the one of three.js, I highly recommend the following topic: Convert from one coordinate system to another?

I don’t know the conventions of IFC but three.js uses a right handed coordinate system with +Y up.

3 Likes

/cc

Thank you for the reference and the quick response!
Investigating deeper in that direction (and with the help of a mathematician friend) I have discovered that the vectors I have form the 4x4 direction matrix, which is the inverse matrix of the 4x4 rotation matrix. A call to Matrix4.getInverse was the solution to define rotations using direction vectors.

const x = transform[xAxis];
const y = transform[yAxis];
const z = transform[zAxis];
const directionMatrix = new THREE.Matrix4();
const rotationMatrix = new THREE.Matrix4();
directionMatrix.set( 
 x[0] ,x[1] ,x[2] ,0
,y[0] ,y[1] ,y[2] ,0
,z[0] ,z[1] ,z[2] ,0
,0    ,0    ,0    ,1
);
rotationMatrix.getInverse(directionMatrix);
return rotationMatrix;
1 Like