diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index e539b5fc7..0ade48c5a 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -73,6 +73,8 @@ template class Matrix4: public Matrix<4, T> { * @param angle Rotation angle (counterclockwise, in radians) * @param vec Normalized rotation axis * + * If possible, use faster alternatives like xRotation(), yRotation() + * or zRotation(). * @see rotation() const, Matrix3::rotation(T), Vector3::xAxis(), * Vector3::yAxis(), Vector3::zAxis(), deg(), rad() * @attention Assertion fails on non-normalized rotation vector and @@ -110,6 +112,66 @@ template class Matrix4: public Matrix<4, T> { ); } + /** + * @brief 3D rotation around X axis + * @param angle Rotation angle (counterclockwise, in radians) + * + * Faster than calling `Matrix4::rotation(angle, Vector3::xAxis())`. + * @see rotation(T, const Vector3&), yRotation(), zRotation(), + * rotation() const, Matrix3::rotation(T), deg(), rad() + */ + static Matrix4 xRotation(T angle) { + T sine = std::sin(angle); + T cosine = std::cos(angle); + + return Matrix4( /* Column-major! */ + T(1), T(0), T(0), T(0), + T(0), cosine, sine, T(0), + T(0), -sine, cosine, T(0), + T(0), T(0), T(0), T(1) + ); + } + + /** + * @brief 3D rotation around Y axis + * @param angle Rotation angle (counterclockwise, in radians) + * + * Faster than calling `Matrix4::rotation(angle, Vector3::yAxis())`. + * @see rotation(T, const Vector3&), xRotation(), zRotation(), + * rotation() const, Matrix3::rotation(T), deg(), rad() + */ + static Matrix4 yRotation(T angle) { + T sine = std::sin(angle); + T cosine = std::cos(angle); + + return Matrix4( /* Column-major! */ + cosine, T(0), -sine, T(0), + T(0), T(1), T(0), T(0), + sine, T(0), cosine, T(0), + T(0), T(0), T(0), T(1) + ); + } + + /** + * @brief 3D rotation matrix around Z axis + * @param angle Rotation angle (counterclockwise, in radians) + * + * Faster than calling `Matrix4::rotation(angle, Vector3::zAxis())`. + * @see rotation(T, const Vector3&), xRotation(), yRotation(), + * rotation() const, Matrix3::rotation(T), deg(), rad() + */ + static Matrix4 zRotation(T angle) { + T sine = std::sin(angle); + T cosine = std::cos(angle); + + return Matrix4( /* Column-major! */ + cosine, sine, T(0), T(0), + -sine, cosine, T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1) + ); + } + /** @copydoc Matrix::Matrix(ZeroType) */ inline constexpr explicit Matrix4(typename Matrix<4, T>::ZeroType): Matrix<4, T>(Matrix<4, T>::Zero) {} diff --git a/src/Math/Test/Matrix4Test.cpp b/src/Math/Test/Matrix4Test.cpp index 496cb5627..fbcc08e4d 100644 --- a/src/Math/Test/Matrix4Test.cpp +++ b/src/Math/Test/Matrix4Test.cpp @@ -36,6 +36,9 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::translation, &Matrix4Test::scaling, &Matrix4Test::rotation, + &Matrix4Test::xRotation, + &Matrix4Test::yRotation, + &Matrix4Test::zRotation, &Matrix4Test::rotationScalingPart, &Matrix4Test::rotationPart, &Matrix4Test::translationPart, @@ -105,6 +108,33 @@ void Matrix4Test::rotation() { CORRADE_COMPARE(Matrix4::rotation(deg(-74.0f), Vector3(-1.0f, 2.0f, 2.0f).normalized()), matrix); } +void Matrix4Test::xRotation() { + Matrix4 matrix(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.90096887f, 0.43388374f, 0.0f, + 0.0f, -0.43388374f, 0.90096887f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Matrix4::rotation(rad(Math::Constants::pi()/7), Vector3::xAxis()), matrix); + CORRADE_COMPARE(Matrix4::xRotation(rad(Math::Constants::pi()/7)), matrix); +} + +void Matrix4Test::yRotation() { + Matrix4 matrix(0.90096887f, 0.0f, -0.43388374f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.43388374f, 0.0f, 0.90096887f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Matrix4::rotation(rad(Math::Constants::pi()/7), Vector3::yAxis()), matrix); + CORRADE_COMPARE(Matrix4::yRotation(rad(Math::Constants::pi()/7)), matrix); +} + +void Matrix4Test::zRotation() { + Matrix4 matrix( 0.90096887f, 0.43388374f, 0.0f, 0.0f, + -0.43388374f, 0.90096887f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Matrix4::rotation(rad(Math::Constants::pi()/7), Vector3::zAxis()), matrix); + CORRADE_COMPARE(Matrix4::zRotation(rad(Math::Constants::pi()/7)), matrix); +} + void Matrix4Test::rotationScalingPart() { Matrix4 m( 3.0f, 5.0f, 8.0f, 4.0f, diff --git a/src/Math/Test/Matrix4Test.h b/src/Math/Test/Matrix4Test.h index 9bc8dbe2b..7e22e979a 100644 --- a/src/Math/Test/Matrix4Test.h +++ b/src/Math/Test/Matrix4Test.h @@ -28,6 +28,9 @@ class Matrix4Test: public Corrade::TestSuite::Tester { void translation(); void scaling(); void rotation(); + void xRotation(); + void yRotation(); + void zRotation(); void rotationScalingPart(); void rotationPart(); void translationPart();