From 5bc191dd8f8b9cb6e260e24e12133b2b2e9f460e Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Wed, 28 May 2025 19:11:35 +0200 Subject: [PATCH] Add test for setPitchYawRollRad rotation conventions --- src/unittest/test_irr_matrix4.cpp | 82 +++++++++++++++++++++---------- src/util/numeric.h | 2 + 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/unittest/test_irr_matrix4.cpp b/src/unittest/test_irr_matrix4.cpp index be6c6aa08..5a9a0041d 100644 --- a/src/unittest/test_irr_matrix4.cpp +++ b/src/unittest/test_irr_matrix4.cpp @@ -6,6 +6,8 @@ #include "irrMath.h" #include "matrix4.h" #include "irr_v3d.h" +#include "util/numeric.h" +#include using matrix4 = core::matrix4; @@ -17,8 +19,58 @@ constexpr v3f x{1, 0, 0}; constexpr v3f y{0, 1, 0}; constexpr v3f z{0, 0, 1}; +constexpr f32 QUARTER_TURN = core::PI / 2; + +static void LEFT_HANDED(const std::function &f) { + SECTION("rotation is left-handed") { + SECTION("around the X-axis") { + matrix4 X; + f(X, {QUARTER_TURN, 0 , 0}); + CHECK(X.transformVect(x).equals(x)); + CHECK(X.transformVect(y).equals(z)); + CHECK(X.transformVect(z).equals(-y)); + } + + SECTION("around the Y-axis") { + matrix4 Y; + f(Y, {0, QUARTER_TURN, 0}); + CHECK(Y.transformVect(y).equals(y)); + CHECK(Y.transformVect(x).equals(-z)); + CHECK(Y.transformVect(z).equals(x)); + } + + SECTION("around the Z-axis") { + matrix4 Z; + f(Z, {0, 0, QUARTER_TURN}); + CHECK(Z.transformVect(z).equals(z)); + CHECK(Z.transformVect(x).equals(y)); + CHECK(Z.transformVect(y).equals(-x)); + } + } +} + TEST_CASE("matrix4") { +// This is in numeric.h rather than matrix4.h, but is conceptually a matrix4 method as well +SECTION("setPitchYawRollRad") { + SECTION("rotation order is YXZ (matrix notation)") { + v3f rot{1, 2, 3}; + matrix4 X, Y, Z, YXZ; + setPitchYawRollRad(X, {rot.X, 0, 0}); + setPitchYawRollRad(Y, {0, rot.Y, 0}); + setPitchYawRollRad(Z, {0, 0, rot.Z}); + setPitchYawRollRad(YXZ, rot); + CHECK(!matrix_equals(X * Y * Z, YXZ)); + CHECK(!matrix_equals(X * Z * Y, YXZ)); + CHECK(matrix_equals(Y * X * Z, YXZ)); + CHECK(!matrix_equals(Y * Z * X, YXZ)); + CHECK(!matrix_equals(Z * X * Y, YXZ)); + CHECK(!matrix_equals(Z * Y * X, YXZ)); + } + + LEFT_HANDED(setPitchYawRollRad); +} + SECTION("setRotationRadians") { SECTION("rotation order is ZYX (matrix notation)") { v3f rot{1, 2, 3}; @@ -35,36 +87,12 @@ SECTION("setRotationRadians") { CHECK(matrix_equals(Z * Y * X, ZYX)); } - const f32 quarter_turn = core::PI / 2; - // See https://en.wikipedia.org/wiki/Right-hand_rule#/media/File:Cartesian_coordinate_system_handedness.svg // for a visualization of what handedness means for rotations - SECTION("rotation is right-handed") { - SECTION("rotation around the X-axis is Z-up, counter-clockwise") { - matrix4 X; - X.setRotationRadians({quarter_turn, 0, 0}); - CHECK(X.transformVect(x).equals(x)); - CHECK(X.transformVect(y).equals(z)); - CHECK(X.transformVect(z).equals(-y)); - } - - SECTION("rotation around the Y-axis is Z-up, clockwise") { - matrix4 Y; - Y.setRotationRadians({0, quarter_turn, 0}); - CHECK(Y.transformVect(y).equals(y)); - CHECK(Y.transformVect(x).equals(-z)); - CHECK(Y.transformVect(z).equals(x)); - } - - SECTION("rotation around the Z-axis is Y-up, counter-clockwise") { - matrix4 Z; - Z.setRotationRadians({0, 0, quarter_turn}); - CHECK(Z.transformVect(z).equals(z)); - CHECK(Z.transformVect(x).equals(y)); - CHECK(Z.transformVect(y).equals(-x)); - } - } + LEFT_HANDED([](core::matrix4 &m, const v3f &rot_rad) { + m.setRotationRadians(rot_rad); + }); } SECTION("getScale") { diff --git a/src/util/numeric.h b/src/util/numeric.h index b79ef2aef..ac387f4b8 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -478,6 +478,7 @@ inline void wrappedApproachShortest(T ¤t, const T target, const T stepsize } } +/// @note Uses YXZ (matrix notation) rotation order, left-handed rotation void setPitchYawRollRad(core::matrix4 &m, v3f rot); inline void setPitchYawRoll(core::matrix4 &m, v3f rot) @@ -485,6 +486,7 @@ inline void setPitchYawRoll(core::matrix4 &m, v3f rot) setPitchYawRollRad(m, rot * core::DEGTORAD); } +/// @see setPitchYawRollRad v3f getPitchYawRollRad(const core::matrix4 &m); inline v3f getPitchYawRoll(const core::matrix4 &m)