Browse Source

Implemented reflection matrices.

Long-standing TODO, can be used for in-game mirrors etc. I give up with
shearing, as I think that it makes sense only in 2D and I can't find any
reasonable use case for that yet.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
e9e0de70d7
  1. 18
      src/Math/Matrix3.h
  2. 20
      src/Math/Matrix4.h
  3. 2
      src/Math/Test/CMakeLists.txt
  4. 30
      src/Math/Test/Matrix3Test.cpp
  5. 1
      src/Math/Test/Matrix3Test.h
  6. 32
      src/Math/Test/Matrix4Test.cpp
  7. 1
      src/Math/Test/Matrix4Test.h

18
src/Math/Matrix3.h

@ -83,6 +83,19 @@ template<class T> class Matrix3: public Matrix<3, T> {
);
}
/**
* @brief 2D reflection matrix
* @param normal Normal of the line through which to reflect
* (normalized)
*
* @see Matrix4::reflection()
*/
static Matrix3<T> reflection(const Vector2<T>& normal) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normal.dot(), T(1)),
"Math::Matrix3::reflection(): normal must be normalized", {});
return from(Matrix<2, T>() - T(2)*normal*normal.transposed(), {});
}
/**
* @brief Create matrix from rotation/scaling part and translation part
* @param rotationScaling Rotation/scaling part (upper-left 2x2
@ -92,7 +105,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
*
* @see rotationScaling() const, translation() const
*/
static Matrix3<T> from(const Matrix<2, T>& rotationScaling, const Vector2<T>& translation = Vector2<T>()) {
static Matrix3<T> from(const Matrix<2, T>& rotationScaling, const Vector2<T>& translation) {
return from(
Vector3<T>(rotationScaling[0], T(0)),
Vector3<T>(rotationScaling[1], T(0)),
@ -167,7 +180,8 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D translation part of the matrix
*
* First two elements of third column.
* @see translation(const Vector2&), Matrix4::translation()
* @see from(const Matrix<2, T>&, const Vector2&),
* translation(const Vector2&), Matrix4::translation()
*/
inline Vector2<T>& translation() { return (*this)[2].xy(); }
inline constexpr Vector2<T> translation() const { return (*this)[2].xy(); } /**< @overload */

20
src/Math/Matrix4.h

@ -32,8 +32,6 @@ Provides functions for transformations in 3D. See Matrix3 for 2D
transformations. See also @ref matrix-vector for brief introduction.
@see Magnum::Matrix4, SceneGraph::MatrixTransformation3D
@configurationvalueref{Magnum::Math::Matrix4}
@todo Shearing
@todo Reflection
*/
template<class T> class Matrix4: public Matrix<4, T> {
public:
@ -173,6 +171,19 @@ template<class T> class Matrix4: public Matrix<4, T> {
);
}
/**
* @brief 3D reflection matrix
* @param normal Normal of the plane through which to reflect
* (normalized)
*
* @see Matrix3::reflection()
*/
static Matrix4<T> reflection(const Vector3<T>& normal) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normal.dot(), T(1)),
"Math::Matrix4::reflection(): normal must be normalized", {});
return from(Matrix<3, T>() - T(2)*normal*normal.transposed(), {});
}
/**
* @brief Create matrix from rotation/scaling part and translation part
* @param rotationScaling Rotation/scaling part (upper-left 3x3
@ -182,7 +193,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
*
* @see rotationScaling() const, translation() const
*/
static Matrix4<T> from(const Matrix<3, T>& rotationScaling, const Vector3<T>& translation = Vector3<T>()) {
static Matrix4<T> from(const Matrix<3, T>& rotationScaling, const Vector3<T>& translation) {
return from(
Vector4<T>(rotationScaling[0], T(0)),
Vector4<T>(rotationScaling[1], T(0)),
@ -273,7 +284,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D translation part of the matrix
*
* First three elements of fourth column.
* @see translation(const Vector3&), Matrix3::translation()
* @see from(const Matrix<3, T>&, const Vector3&),
* translation(const Vector3&), Matrix3::translation()
*/
inline Vector3<T>& translation() { return (*this)[3].xyz(); }
inline constexpr Vector3<T> translation() const { return (*this)[3].xyz(); } /**< @overload */

2
src/Math/Test/CMakeLists.txt

@ -18,4 +18,4 @@ corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
set_target_properties(MathVectorTest MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)
set_target_properties(MathVectorTest MathMatrix3Test MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

30
src/Math/Test/Matrix3Test.cpp

@ -36,6 +36,7 @@ Matrix3Test::Matrix3Test() {
&Matrix3Test::translation,
&Matrix3Test::scaling,
&Matrix3Test::rotation,
&Matrix3Test::reflection,
&Matrix3Test::fromParts,
&Matrix3Test::rotationScalingPart,
&Matrix3Test::rotationPart,
@ -96,6 +97,27 @@ void Matrix3Test::rotation() {
CORRADE_COMPARE(Matrix3::rotation(deg(15.0f)), matrix);
}
void Matrix3Test::reflection() {
std::ostringstream o;
Error::setOutput(&o);
Vector2 normal(-1.0f, 2.0f);
CORRADE_COMPARE(Matrix3::reflection(normal), Matrix3());
CORRADE_COMPARE(o.str(), "Math::Matrix3::reflection(): normal must be normalized\n");
Matrix3 actual = Matrix3::reflection(normal.normalized());
Matrix3 expected(
0.6f, 0.8f, 0.0f,
0.8f, -0.6f, 0.0f,
0.0f, 0.0f, 1.0f
);
CORRADE_COMPARE(actual*actual, Matrix3());
CORRADE_COMPARE(actual*normal, -normal);
CORRADE_COMPARE(actual, expected);
}
void Matrix3Test::fromParts() {
Matrix2 rotationScaling(
3.0f, 5.0f,
@ -109,14 +131,8 @@ void Matrix3Test::fromParts() {
4.0f, 4.0f, 0.0f,
7.0f, -1.0f, 1.0f
);
CORRADE_COMPARE(Matrix3::from(rotationScaling, translation), expected);
Matrix3 expectedNoRotation(
3.0f, 5.0f, 0.0f,
4.0f, 4.0f, 0.0f,
0.0f, 0.0f, 1.0f
);
CORRADE_COMPARE(Matrix3::from(rotationScaling), expectedNoRotation);
CORRADE_COMPARE(Matrix3::from(rotationScaling, translation), expected);
}
void Matrix3Test::rotationScalingPart() {

1
src/Math/Test/Matrix3Test.h

@ -28,6 +28,7 @@ class Matrix3Test: public Corrade::TestSuite::Tester {
void translation();
void scaling();
void rotation();
void reflection();
void fromParts();
void rotationScalingPart();
void rotationPart();

32
src/Math/Test/Matrix4Test.cpp

@ -39,6 +39,7 @@ Matrix4Test::Matrix4Test() {
&Matrix4Test::rotationX,
&Matrix4Test::rotationY,
&Matrix4Test::rotationZ,
&Matrix4Test::reflection,
&Matrix4Test::fromParts,
&Matrix4Test::rotationScalingPart,
&Matrix4Test::rotationPart,
@ -136,6 +137,28 @@ void Matrix4Test::rotationZ() {
CORRADE_COMPARE(Matrix4::rotationZ(rad(Math::Constants<float>::pi()/7)), matrix);
}
void Matrix4Test::reflection() {
std::ostringstream o;
Error::setOutput(&o);
Vector3 normal(-1.0f, 2.0f, 2.0f);
CORRADE_COMPARE(Matrix4::reflection(normal), Matrix4());
CORRADE_COMPARE(o.str(), "Math::Matrix4::reflection(): normal must be normalized\n");
Matrix4 actual = Matrix4::reflection(normal.normalized());
Matrix4 expected(
0.777778f, 0.444444f, 0.444444f, 0.0f,
0.444444f, 0.111111f, -0.888889f, 0.0f,
0.444444f, -0.888889f, 0.111111f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
CORRADE_COMPARE(actual*actual, Matrix4());
CORRADE_COMPARE(actual*normal, -normal);
CORRADE_COMPARE(actual, expected);
}
void Matrix4Test::fromParts() {
Matrix3 rotationScaling(
3.0f, 5.0f, 8.0f,
@ -151,15 +174,8 @@ void Matrix4Test::fromParts() {
7.0f, -1.0f, 8.0f, 0.0f,
9.0f, 4.0f, 5.0f, 1.0f
);
CORRADE_COMPARE(Matrix4::from(rotationScaling, translation), expected);
Matrix4 expectedNoTranslation(
3.0f, 5.0f, 8.0f, 0.0f,
4.0f, 4.0f, 7.0f, 0.0f,
7.0f, -1.0f, 8.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
CORRADE_COMPARE(Matrix4::from(rotationScaling), expectedNoTranslation);
CORRADE_COMPARE(Matrix4::from(rotationScaling, translation), expected);
}
void Matrix4Test::rotationScalingPart() {

1
src/Math/Test/Matrix4Test.h

@ -31,6 +31,7 @@ class Matrix4Test: public Corrade::TestSuite::Tester {
void rotationX();
void rotationY();
void rotationZ();
void reflection();
void fromParts();
void rotationScalingPart();
void rotationPart();

Loading…
Cancel
Save