Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

THREE.Matrix4 makeRotationFromEuler function is wrong. #10485

Closed
2 of 12 tasks
tomyi9527 opened this issue Dec 30, 2016 · 7 comments
Closed
2 of 12 tasks

THREE.Matrix4 makeRotationFromEuler function is wrong. #10485

tomyi9527 opened this issue Dec 30, 2016 · 7 comments

Comments

@tomyi9527
Copy link

tomyi9527 commented Dec 30, 2016

(*** This section is for bug reports and feature requests only. This is NOT a help site. Do not ask help questions here. If you need help, please use stackoverflow. ***)

Description of the problem

For the matrix is column major and right multiplication in three js, which means column elements are placed in adjacent memory address, the matrix made from euler order 'XYZ' is actually that of 'ZYX'. I didn't check other euler orders yet. I found this because the euler angles which I exported from FBX file is 'XYZ' order, but I have to set them to 'ZYX' to get the right result in three js. Or I was wrong, if three js rotation is based on the local coordination of object instead of that of it's parent.

Three.js version
  • Dev
  • r82
  • ...
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • Linux
  • Android
  • IOS
Hardware Requirements (graphics card, VR Device, ...)
@WestLangley
Copy link
Collaborator

In three.js, Euler angles are of the intrinsic Tait-Bryan type. Rotations are performed with respect to the local coordinate system. That is, for order XYZ, the rotation is first around X, then around local-Y (which may now be different from the world Y-axis), then local-Z (which may be different from the world Z-axis).

If the rotations are performed with respect to the static world coordinate system, instead of the local coordinate system, then the angles are referred to as extrinsic Euler angles. In that case, for order XYZ, the rotations are around world-X, world-Y, and world-Z.

Euler order XYZ when the angles are interpreted as intrinsic angles is equivalent to order ZYX when the same angles are interpreted as extrinsic angles.

So a reasonable assumption would be that the FBX Euler angles are extrinsic. To convert to three.js angles, reverse the order.

@looeee
Copy link
Collaborator

looeee commented Jan 11, 2017

I'll add a note on this to the docs.

@WestLangley actually there is quite a bit of useful info in your responses and StackOverflow posts - do you mind if I plagiarise some of it?

@WestLangley
Copy link
Collaborator

@looeee OK

@kvark
Copy link

kvark commented Jun 2, 2017

@WestLangley @looeee

Euler order XYZ when the angles are interpreted as intrinsic angles is equivalent to order ZYX when the same angles are interpreted as extrinsic angles.

That doesn't sound right to me. Care to provide a proof link?

Also, Wiki says:

Here we present the results for the two most commonly used conventions: ZXZ for proper Euler angles and ZYX for Tait-Bryan.

And three.js defaults to XYZ for Tait-Bryan... What is the reason for not going with a "commonly used convention"?

@looeee
Copy link
Collaborator

looeee commented Jun 3, 2017

The two most commonly used conventions

Three.js uses one of the two most commonly used conventions. Actually Tait-Bryan are probably more commonly used than 'proper' Euler angles. Intrinsic Tait-Bryan Euler angles are also known as yaw, pitch, and roll.

Euler order XYZ when the angles are interpreted as intrinsic angles is equivalent to order ZYX when the same angles are interpreted as extrinsic angles.

Hmm, this could be written a bit better, as the initial XYZ should be XY'Z'' to show that these are local axes rather than world axes. Something like:

An intrinsic Euler rotation XY'Z'' about the angles a, b, c is equivalent to an extrinsic Euler rotation ZYX about the angles c, b, a.

You can find proofs of the intrinsic to extrinsic transform online. Here's one discussion. Feel free to double check it and update the docs if there is a mistake (there's an "edit button in the top right of each page).

@WestLangley
Copy link
Collaborator

WestLangley commented Jun 3, 2017

It is not correct to say intrinsic Tait-Bryan Euler angles are "known as yaw, pitch, and roll". That is only true in certain use cases -- in spite of what you may have read on Wikipedia.

Please see the section https://en.wikipedia.org/wiki/Euler_angles#Conventions_2. I believe that section is accurate.

Also see https://stackoverflow.com/questions/17517937/three-js-camera-tilt-up-or-down-and-keep-horizon-level/17518092#17518092.

Here we present the results for the two most commonly used conventions: ZXZ for proper Euler angles and ZYX for Tait-Bryan.

"Proper" Euler angles do not apply to us. Also, the ZYX order is used in the aeronautics industry, but unlike our coordinate system with positive y-up, in the aeronautics industry, I believe the coordinate system typically sets positive z-down (so headings are measured clockwise), and with the aircraft aligned with the x-axis. The equivalent order in our y-up coordinate system would be YXZ, although that order implies counterclockwise headings.

If we were to change the default Euler order in three.js, I would select YXZ, because it is the most intuitive and would lead to much less user confusion.

@kvark
Copy link

kvark commented Jun 4, 2017

@looeee

Three.js uses one of the two most commonly used conventions.

Three.js defaults to Tait-Bryan XYZ, while Wikipedia says that one of the conventions is Tait-Bryan ZYX. These are not the same, hence Three.js does not use a common convention.

You can find proofs of the intrinsic to extrinsic transform online. Here's one discussion.

Thanks, that's an interesting read!

@WestLangley
Thanks for the explanation about why Three.js doesn't follow Tait-Bryan ZYX by default! Do you know what existing reference/inspiration was used when picking XYZ by default?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants