From 71784a777c922f932a45e1d0e4416a099ae6e1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 22 Sep 2012 12:28:32 +0200 Subject: [PATCH] Functions for getting 2D rotation and scaling part of 3x3 matrix. Crosslinked the documentation with 2D/3D alternatives and "setters"/"getters". --- src/Math/Matrix3.h | 30 ++++++++++++++++++++++++++++-- src/Math/Matrix4.h | 23 ++++++++++++++++++----- src/Math/Test/Matrix3Test.cpp | 32 ++++++++++++++++++++++++++++++++ src/Math/Test/Matrix3Test.h | 2 ++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 09dacfddb..2b00d3239 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -52,7 +52,8 @@ template class Matrix3: public Matrix<3, T> { * @brief 2D scaling matrix * @param vec Scaling vector * - * @see Matrix4::scaling(), Vector2::xScale(), Vector2::yScale() + * @see rotationScaling() const, Matrix4::scaling(const Vector3&), + * Vector2::xScale(), Vector2::yScale() */ inline constexpr static Matrix3 scaling(const Vector2& vec) { return Matrix3( /* Column-major! */ @@ -66,7 +67,8 @@ template class Matrix3: public Matrix<3, T> { * @brief 3D rotation matrix * @param angle Rotation angle (counterclockwise, in radians) * - * @see Matrix4::rotation(), deg(), rad() + * @see rotation() const, Matrix4::rotation(T, const Vector3&), deg(), + * rad() */ static Matrix3 rotation(T angle) { return Matrix3( /* Column-major! */ @@ -96,6 +98,30 @@ template class Matrix3: public Matrix<3, T> { /** @brief Copy constructor */ inline constexpr Matrix3(const RectangularMatrix<3, 3, T>& other): Matrix<3, T>(other) {} + /** + * @brief 2D rotation and scaling part of the matrix + * + * Upper-left 2x2 part of the matrix. + * @see rotation() const, rotation(T), Matrix4::rotationScaling() const + */ + inline Matrix<2, T> rotationScaling() const { + return Matrix<2, T>::from( + (*this)[0].xy(), + (*this)[1].xy()); + } + + /** + * @brief 2D rotation part of the matrix + * + * Normalized upper-left 2x2 part of the matrix. + * @see rotationScaling() const, rotation(T), Matrix4::rotation() const + */ + inline Matrix<2, T> rotation() const { + return Matrix<2, T>::from( + (*this)[0].xy().normalized(), + (*this)[1].xy().normalized()); + } + MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix3, Vector3, 3) MAGNUM_RECTANGULARMATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(3, 3, Matrix3) }; diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index ac4ad1639..1090974db 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -55,7 +55,8 @@ template class Matrix4: public Matrix<4, T> { * @brief 3D scaling matrix * @param vec Scaling vector * - * @see Matrix3::scaling(), Vector3::xScale(), Vector3::yScale(), Vector3::zScale() + * @see rotationScaling() const, Matrix3::scaling(const Vector2&), + * Vector3::xScale(), Vector3::yScale(), Vector3::zScale() */ inline constexpr static Matrix4 scaling(const Vector3& vec) { return Matrix4( /* Column-major! */ @@ -71,8 +72,8 @@ template class Matrix4: public Matrix<4, T> { * @param angle Rotation angle (counterclockwise, in radians) * @param vec Normalized rotation vector * - * @see Matrix3::rotation(), Vector3::xAxis(), Vector3::yAxis(), - * Vector3::zAxis(), deg(), rad() + * @see rotation() const, Matrix3::rotation(T), Vector3::xAxis(), + * Vector3::yAxis(), Vector3::zAxis(), deg(), rad() * @attention Assertion fails on non-normalized rotation vector and * identity matrix is returned. */ @@ -132,7 +133,13 @@ template class Matrix4: public Matrix<4, T> { /** @copydoc Matrix::ij() */ inline Matrix3 ij(size_t skipRow, size_t skipCol) const { return Matrix<4, T>::ij(skipRow, skipCol); } - /** @brief Rotation and scaling part of the matrix */ + /** + * @brief 3D rotation and scaling part of the matrix + * + * Upper-left 3x3 part of the matrix. + * @see rotation() const, rotation(T, const Vector3&), + * Matrix3::rotationScaling() const + */ inline Matrix3 rotationScaling() const { return Matrix3::from( (*this)[0].xyz(), @@ -140,7 +147,13 @@ template class Matrix4: public Matrix<4, T> { (*this)[2].xyz()); } - /** @brief Rotation part of the matrix */ + /** + * @brief 3D rotation part of the matrix + * + * Normalized upper-left 3x3 part of the matrix. + * @see rotationScaling() const, rotation(T, const Vector3&), + * Matrix3::rotation() const + */ inline Matrix3 rotation() const { return Matrix3::from( (*this)[0].xyz().normalized(), diff --git a/src/Math/Test/Matrix3Test.cpp b/src/Math/Test/Matrix3Test.cpp index 225b62171..cdffde3bf 100644 --- a/src/Math/Test/Matrix3Test.cpp +++ b/src/Math/Test/Matrix3Test.cpp @@ -28,12 +28,16 @@ using namespace Corrade::Utility; namespace Magnum { namespace Math { namespace Test { typedef Math::Matrix3 Matrix3; +typedef Math::Matrix<2, float> Matrix2; +typedef Math::Vector2 Vector2; Matrix3Test::Matrix3Test() { addTests(&Matrix3Test::constructIdentity, &Matrix3Test::translation, &Matrix3Test::scaling, &Matrix3Test::rotation, + &Matrix3Test::rotationScalingPart, + &Matrix3Test::rotationPart, &Matrix3Test::debug, &Matrix3Test::configuration); } @@ -90,6 +94,34 @@ void Matrix3Test::rotation() { CORRADE_COMPARE(Matrix3::rotation(deg(15.0f)), matrix); } +void Matrix3Test::rotationScalingPart() { + Matrix3 m( + 3.0f, 5.0f, 8.0f, + 4.0f, 4.0f, 7.0f, + 7.0f, -1.0f, 8.0f + ); + + Matrix2 expected( + 3.0f, 5.0f, + 4.0f, 4.0f + ); + + CORRADE_COMPARE(m.rotationScaling(), expected); +} + +void Matrix3Test::rotationPart() { + Matrix2 expectedRotationPart( + 0.965926f, 0.258819f, + -0.258819f, 0.965926f + ); + + Matrix3 rotation = Matrix3::rotation(deg(15.0f)); + CORRADE_COMPARE(rotation.rotation(), expectedRotationPart); + + Matrix3 rotationTransformed = Matrix3::translation({2.0f, 5.0f})*rotation*Matrix3::scaling(Vector2(9.0f)); + CORRADE_COMPARE(rotationTransformed.rotation(), expectedRotationPart); +} + void Matrix3Test::debug() { Matrix3 m( 3.0f, 5.0f, 8.0f, diff --git a/src/Math/Test/Matrix3Test.h b/src/Math/Test/Matrix3Test.h index 2402fbc93..6f71f41e3 100644 --- a/src/Math/Test/Matrix3Test.h +++ b/src/Math/Test/Matrix3Test.h @@ -28,6 +28,8 @@ class Matrix3Test: public Corrade::TestSuite::Tester { void translation(); void scaling(); void rotation(); + void rotationScalingPart(); + void rotationPart(); void debug(); void configuration();