Skip to content

Commit

Permalink
Add Quaternion.getEulerAnglesYXZ()
Browse files Browse the repository at this point in the history
  • Loading branch information
httpdigest committed Dec 15, 2021
1 parent 1c1922f commit f5ede55
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/org/joml/Quaterniond.java
Original file line number Diff line number Diff line change
Expand Up @@ -2782,6 +2782,13 @@ public Vector3d getEulerAnglesZXY(Vector3d eulerAngles) {
return eulerAngles;
}

public Vector3d getEulerAnglesYXZ(Vector3d eulerAngles) {
eulerAngles.x = Math.safeAsin(-2.0 * (y * z - w * x));
eulerAngles.y = Math.atan2(x * z + y * w, 0.5 - y * y - x * x);
eulerAngles.z = Math.atan2(y * x + w * z, 0.5 - x * x - z * z);
return eulerAngles;
}

public Quaterniond rotateAxis(double angle, double axisX, double axisY, double axisZ, Quaterniond dest) {
double hangle = angle / 2.0;
double sinAngle = Math.sin(hangle);
Expand Down
13 changes: 13 additions & 0 deletions src/org/joml/Quaterniondc.java
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,19 @@ public interface Quaterniondc {
*/
Vector3d getEulerAnglesZXY(Vector3d eulerAngles);

/**
* Get the euler angles in radians in rotation sequence <code>YXZ</code> of this quaternion and store them in the
* provided parameter <code>eulerAngles</code>.
* <p>
* The Euler angles are always returned as the angle around X in the {@link Vector3d#x} field, the angle around Y in the {@link Vector3d#y}
* field and the angle around Z in the {@link Vector3d#z} field of the supplied {@link Vector3d} instance.
*
* @param eulerAngles
* will hold the euler angles in radians
* @return the passed in vector
*/
Vector3d getEulerAnglesYXZ(Vector3d eulerAngles);

/**
* Apply a rotation to <code>this</code> quaternion rotating the given radians about the specified axis
* and store the result in <code>dest</code>.
Expand Down
7 changes: 7 additions & 0 deletions src/org/joml/Quaternionf.java
Original file line number Diff line number Diff line change
Expand Up @@ -1873,6 +1873,13 @@ public Vector3f getEulerAnglesZXY(Vector3f eulerAngles) {
return eulerAngles;
}

public Vector3f getEulerAnglesYXZ(Vector3f eulerAngles) {
eulerAngles.x = Math.safeAsin(-2.0f * (y * z - w * x));
eulerAngles.y = Math.atan2(x * z + y * w, 0.5f - y * y - x * x);
eulerAngles.z = Math.atan2(y * x + w * z, 0.5f - x * x - z * z);
return eulerAngles;
}

public float lengthSquared() {
return Math.fma(x, x, Math.fma(y, y, Math.fma(z, z, w * w)));
}
Expand Down
13 changes: 13 additions & 0 deletions src/org/joml/Quaternionfc.java
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,19 @@ public interface Quaternionfc {
*/
Vector3f getEulerAnglesZXY(Vector3f eulerAngles);

/**
* Get the euler angles in radians in rotation sequence <code>YXZ</code> of this quaternion and store them in the
* provided parameter <code>eulerAngles</code>.
* <p>
* The Euler angles are always returned as the angle around X in the {@link Vector3f#x} field, the angle around Y in the {@link Vector3f#y}
* field and the angle around Z in the {@link Vector3f#z} field of the supplied {@link Vector3f} instance.
*
* @param eulerAngles
* will hold the euler angles in radians
* @return the passed in vector
*/
Vector3f getEulerAnglesYXZ(Vector3f eulerAngles);

/**
* Return the square of the length of this quaternion.
*
Expand Down
21 changes: 21 additions & 0 deletions test/org/joml/test/QuaternionDTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,25 @@ public static void testGetEulerAnglesZXY() {
if ((float)failure / N > 0.0001f) // <- allow for a failure rate of 0.01%
throw new AssertionError();
}

public static void testGetEulerAnglesYXZ() {
Random rnd = new Random(1L);
int failure = 0;
int N = 3000000;
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().rotateY(y).rotateX(x).rotateZ(z);
Vector3d a = p.getEulerAnglesYXZ(new Vector3d());
Quaterniond q = new Quaterniond().rotateY(a.y).rotateX(a.x).rotateZ(a.z);
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();
}
}
21 changes: 21 additions & 0 deletions test/org/joml/test/QuaternionfTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,25 @@ public static void testGetEulerAnglesZXY() {
if ((float)failure / N > 0.0001f) // <- allow for a failure rate of 0.01%
throw new AssertionError();
}

public static void testGetEulerAnglesYXZ() {
Random rnd = new Random(1L);
int failure = 0;
int N = 3000000;
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().rotateY(y).rotateX(x).rotateZ(z);
Vector3f a = p.getEulerAnglesYXZ(new Vector3f());
Quaternionf q = new Quaternionf().rotateY(a.y).rotateX(a.x).rotateZ(a.z);
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();
}
}

0 comments on commit f5ede55

Please sign in to comment.