Skip to content

Commit

Permalink
Fix incorrect sign in Quaternion#getEulerAnglesZYX
Browse files Browse the repository at this point in the history
  • Loading branch information
56738 committed Dec 28, 2022
1 parent 03cbd5e commit 10bb9ae
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/joml/Quaterniond.java
Original file line number Diff line number Diff line change
Expand Up @@ -2847,7 +2847,7 @@ public Vector3d getEulerAnglesXYZ(Vector3d eulerAngles) {
}

public Vector3d getEulerAnglesZYX(Vector3d eulerAngles) {
eulerAngles.x = Math.atan2(y * z + w * x, 0.5 - x * x + y * y);
eulerAngles.x = Math.atan2(y * z + w * x, 0.5 - x * x - y * y);
eulerAngles.y = Math.safeAsin(-2.0 * (x * z - w * y));
eulerAngles.z = Math.atan2(x * y + w * z, 0.5 - y * y - z * z);
return eulerAngles;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/joml/Quaternionf.java
Original file line number Diff line number Diff line change
Expand Up @@ -1956,7 +1956,7 @@ public Vector3f getEulerAnglesXYZ(Vector3f eulerAngles) {
}

public Vector3f getEulerAnglesZYX(Vector3f eulerAngles) {
eulerAngles.x = Math.atan2(y * z + w * x, 0.5f - x * x + y * y);
eulerAngles.x = Math.atan2(y * z + w * x, 0.5f - x * x - y * y);
eulerAngles.y = Math.safeAsin(-2.0f * (x * z - w * y));
eulerAngles.z = Math.atan2(x * y + w * z, 0.5f - y * y - z * z);
return eulerAngles;
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/org/joml/test/QuaternionDTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,28 @@ void testGetEulerAnglesXYZ() {
throw new AssertionError();
}

@Test
void testGetEulerAnglesZYX() {
Random rnd = new Random(1L);
int failure = 0;
int N = 30000;
for (int i = 0; i < N; i++) {
double x = (rnd.nextFloat() * 2.0 - 1.0) * Math.PI;
double y = (rnd.nextFloat() * 2.0 - 1.0) * Math.PI;
double z = (rnd.nextFloat() * 2.0 - 1.0) * Math.PI;
Quaterniond p = new Quaterniond().rotateZ(z).rotateY(y).rotateX(x);
Vector3d a = p.getEulerAnglesZYX(new Vector3d());
Quaterniond q = new Quaterniond().rotateZ(a.z).rotateY(a.y).rotateX(a.x);
Vector3d v = new Vector3d(rnd.nextFloat()*2-1, rnd.nextFloat()*2-1, rnd.nextFloat()*2-1);
Vector3d t1 = p.transform(v, new Vector3d());
Vector3d t2 = q.transform(v, new Vector3d());
if (!t1.equals(t2, 1E-10f))
failure++;
}
if ((float)failure / N > 0.0001f) // <- allow for a failure rate of 0.01%
throw new AssertionError();
}

@Test
void testGetEulerAnglesZXY() {
Random rnd = new Random(1L);
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/org/joml/test/QuaternionfTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,28 @@ void testGetEulerAnglesXYZ() {
throw new AssertionError();
}

@Test
void testGetEulerAnglesZYX() {
Random rnd = new Random(1L);
int failure = 0;
int N = 30000;
for (int i = 0; i < N; i++) {
float x = (rnd.nextFloat() * 2f - 1f) * (float) Math.PI;
float y = (rnd.nextFloat() * 2f - 1f) * (float) Math.PI;
float z = (rnd.nextFloat() * 2f - 1f) * (float) Math.PI;
Quaternionf p = new Quaternionf().rotateZYX(z, y, x);
Vector3f a = p.getEulerAnglesZYX(new Vector3f());
Quaternionf q = new Quaternionf().rotateZ(a.z).rotateY(a.y).rotateX(a.x);
Vector3f v = new Vector3f(rnd.nextFloat()*2-1, rnd.nextFloat()*2-1, rnd.nextFloat()*2-1);
Vector3f t1 = p.transform(v, new Vector3f());
Vector3f t2 = q.transform(v, new Vector3f());
if (!t1.equals(t2, 1E-3f))
failure++;
}
if ((float)failure / N > 0.0001f) // <- allow for a failure rate of 0.01%
throw new AssertionError();
}

@Test
void testGetEulerAnglesZXY() {
Random rnd = new Random(1L);
Expand Down

0 comments on commit 10bb9ae

Please sign in to comment.