Three.js: Euler.setFromRotationMatrix returns incorrect values for y

Created on 17 Jun 2019  路  4Comments  路  Source: mrdoob/three.js

Description of the problem

Hello,

I came across a small but really nerve racking bug in the 'setFromRotationMatrix' method of the Euler class. Context is the following:

I am developing a kind of gizmo rotation control just like the rotation control in the threejs transform control example. While rotating an object around the Y-Axis i noticed that whenever the rotation was near the 90 or -90 degrees, and i got very slow with my rotation, then the object was rotating back and forth!. Tracking down the problem really took me quite a while ...

I created a very basic fiddle for this, you can see the results in the console:

https://jsfiddle.net/kceyo61j/1/

You can see that if you increase the rotation up from 90 degrees , very slightly!, then the Euler rotation for the Y-axis is decreasing (moving backwards!), while the others increase. When increasing the rotation to 90.25 the Euler rotation for X- and Z-Axis are adjusted so that the overall rotation is correct again. (I don't know where the sweetspot is but 90.25 works while 90.22 degrees does not.

As far as i can see, this caused my object to rotate backwards when getting slow at around 90 and -90 degrees.

Another hint: I don't really understand what the setFromRotationMatrix method is doing but i found out that if you increase the comparison value of 0.99999 then the problem is not noticable anymore (but probably still exists for smaller rotation values!)

Thanks for any help here and please correct me if i am wrong.

Three.js version
  • [x ] Dev

Most helpful comment

If I substitute the rotate function with this code, it works right:

function rotate(axis, angle) {

    mesh.matrixAutoUpdate = false;

    rotMat = new THREE.Matrix4().makeRotationAxis(axis, angle);

    mesh.matrix.multiply(rotMat);

        mesh.rotation.setFromRotationMatrix(mesh.matrix);    

}

BTW, it is very important to not create matrices and other objects ni each frame. You should create those objects as global variables and reuse them.

All 4 comments

Euler angles are not unique, and they occur in triples. Multiple triples can correspond to the same orientation. You can not observe a single component and conclude anything.

Also, three.js is quaternion-based. It is not clear what you are doing in your app, but you are likely better off setting the quaternion directly:

object.quaternion.setFromRotationMatrix( matrix );

If you still believe there is a three.js bug, please provide a more-detailed live example.

@WestLangley Yes setting the quaternion directly removes the problem, thank you for that hint!

But I still think it's a bug, which is why i made this more detailed live example. I think people who are working with the euler rotation instead of the quaternion directly (like in the example) could also run into this problem, which is why i think you should have a second look.

Here i use (afaik) a valid method for rotating threejs objects (-> Method "rotate"). You can press X, Y and Z for switching between the different rotation modes. Up and Down increasing or decreasing the angle.

I slow down the rotation speed when the angle is near 90 degrees.

You will notice that when rotating around the X- and Z-axis, there is no issue -> rotation keeps on. However, when rotating around Y axis the rotation stops just before 90 degrees. The angle value keeps flipping back and forth and you never get over 90 degrees.

So how to exactly reproduce:

  1. Open the provided fiddle link
  2. Press 'Y' to start the rotation mode around the Y-axis.
  3. Hold the 'Arrow-Up' key until the AngleY value reaches around 90 degrees.

If I substitute the rotate function with this code, it works right:

function rotate(axis, angle) {

    mesh.matrixAutoUpdate = false;

    rotMat = new THREE.Matrix4().makeRotationAxis(axis, angle);

    mesh.matrix.multiply(rotMat);

        mesh.rotation.setFromRotationMatrix(mesh.matrix);    

}

BTW, it is very important to not create matrices and other objects ni each frame. You should create those objects as global variables and reuse them.

@yomboprime Hey, thank you very much for your input! Works totally fine. And thanks for the advice ;)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

clawconduce picture clawconduce  路  3Comments

seep picture seep  路  3Comments

yqrashawn picture yqrashawn  路  3Comments

jack-jun picture jack-jun  路  3Comments

konijn picture konijn  路  3Comments