# Convert rotation system

Hello,

I am (still) writing a CAD-Program (Computer Aided Design) using JME and it works fine.
But there is still one thing that makes me crazy.
All my rotations are extrinsic.
Every object has a rotation in degrees over the angles x,y and z that are done one after the other with the following method (which works fine):

Quaternion quatLocal = new Quaternion();        // actual local rotation
Quaternion quatRotation = new Quaternion();     // rotation to add

// the extrinsic rotations round X, Y und Z-Axis are done one afther the other
quatLocal = this.node.getLocalRotation();        // actual rotation

quatLocal = quatRotation.mult(quatLocal);

quatLocal = quatRotation.mult(quatLocal);

quatLocal = quatRotation.mult(quatLocal);

node.setLocalRotation(quatLocal);

the problem is, that when I try to read the actual rotation from an existing node I get angles back in a different system.

node.getLocalRotation
float[] angles = node.getLocalRotation().toAngles(angles);
float x = Math.toDegrees(angles[0]);
float y = Math.toDegrees(angles[1]);
float z = Math.toDegrees(angles[2]);

I think itâ€™s because JME ist rotating in xzy-order and not in xyz-order like I do.
Thatâ€™s why i have to do the rotation axis after axis and can not use the method node.setLocalRotation()

For example in my system the rotation is (0,30,270)
But when I read the rotation from the node I get (150,180,90).

I would be very very happy if somebody would know a method how to transform the (150,180,90)(JME-system) into the (0,30,270)(my system).
It doesnâ€™t even matter if the result is different as long it fits into my system (because there are always several ways to get the same result when rotating.)

1 Like

No. Itâ€™s because euler-style angles are ambiguous and quaternions are compact rotations. Every quaterion is unique (excluding the negative form) but euler-style angles are not unique. You can never really expect to get the same angle-triple back out of a quaternion that you put into it. Itâ€™s just part of the math.

Order does also come into play but thatâ€™s inherent in the quaterionâ€¦ where there is no order. Itâ€™s a compact rotation in axes at once.

Especially in an example like this. If you are already allowing angles to be something other than +/- 180 then you are going to have an infinite variation in what angle-triple can produce a particular quaternion. And even in that case, you can imagine how 0, 180, 0 could be the same as 180, 0, 180. Both would produce the same quaternion.

If you need the original angle-triple then you will have to keep the angle-triple and then never use JME to transform the rotationâ€¦ always reconstruct that rotation from your own. You lose the ability to compose rotations using Quaterions, though.

My description was wrong. Im not using 0Â°â€¦360Â° but -180Â°â€¦+180Â°.
But my problem stays the same.
It would be ok for me if I get back 0,180,0 or 180,0,180.
But I think the mathematics would be very complicated to transform that.
At the Moment I just use a table with which I translate the JME values into â€śmyâ€ť values.
Gladly I only need values in 15Â° or 30Â° steps. Example:

6:297:38:135:225:240
6:332:303:30:345:300
7:17:29:15:15:30
7:31:13:15:30:15
7:49:339:165:135:150
7:131:21:165:45:150
7:149:347:15:150:15
7:163:331:15:165:30
7:197:29:15:195:330
7:211:13:15:210:345
7:229:339:165:315:210
7:311:21:165:225:210
7:329:347:15:330:345
7:343:331:15:345:330
8:17:331:0:15:330

first tree numbers are the JME-value (x,y,z via getLocalRotation())
last three numbers are the equivalent values in my system (x,y,z).

Okay, so youâ€™re applying the angles extrinsically in X,Y,Z order and you want to find some angles that would reproduce a given quaternion. The simple solution would be to store the angles alongside the quaternion, for instance in the nodeâ€™s user data:

node.setLocalRotation(quatLocal);
node.setUserData("xDegrees", this.getRotX());
node.setUserData("yDegrees", this.getRotEwY());
node.setUserData("zDegrees", this.getRotZ());

Then you can get the angles back using (Float)node.getUserData("xDegrees") and so on.

But letâ€™s assume you have some reason not to do it that way. To avoid doing a ton of trigonometry, my next suggestion would be to convert the quaternion to an equivalent 3x3 rotation matrix, then use textbook formulas to find suitable angles:

Matrix3f r = new Matrix3f();
//...
quatLocal.toRotationMatrix(r);

float r11 = r.get(0, 0); // textbook indices are 1,2,3 not 0,1,2
float r21 = r.get(1, 0);
float r31 = r.get(2, 0);
float r32 = r.get(2, 1);
float r33 = r.get(2, 2);

float cr31 = FastMath.sqrt(1f - r31 * r31);