Browse Source

Math: ability to convert matrices from/to external representation.

pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
a21fd0df07
  1. 3
      src/Math/Matrix.h
  2. 3
      src/Math/Matrix3.h
  3. 3
      src/Math/Matrix4.h
  4. 19
      src/Math/RectangularMatrix.h
  5. 55
      src/Math/Test/Matrix3Test.cpp
  6. 58
      src/Math/Test/Matrix4Test.cpp
  7. 54
      src/Math/Test/MatrixTest.cpp
  8. 52
      src/Math/Test/RectangularMatrixTest.cpp

3
src/Math/Matrix.h

@ -97,6 +97,9 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
*/
template<class U> inline constexpr explicit Matrix(const RectangularMatrix<size, size, U>& other): RectangularMatrix<size, size, T>(other) {}
/** @brief Construct matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<size, size, T, U>::from(std::declval<U>()))> inline constexpr explicit Matrix(const U& other): RectangularMatrix<size, size, T>(Implementation::RectangularMatrixConverter<size, size, T, U>::from(other)) {}
/** @brief Copy constructor */
inline constexpr Matrix(const RectangularMatrix<size, size, T>& other): RectangularMatrix<size, size, T>(other) {}

3
src/Math/Matrix3.h

@ -149,6 +149,9 @@ template<class T> class Matrix3: public Matrix<3, T> {
/** @copydoc Matrix::Matrix(const RectangularMatrix<size, size, U>&) */
template<class U> inline constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other): Matrix<3, T>(other) {}
/** @brief Construct matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(std::declval<U>()))> inline constexpr explicit Matrix3(const U& other): Matrix<3, T>(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {}
/** @brief Copy constructor */
inline constexpr Matrix3(const RectangularMatrix<3, 3, T>& other): Matrix<3, T>(other) {}

3
src/Math/Matrix4.h

@ -280,6 +280,9 @@ template<class T> class Matrix4: public Matrix<4, T> {
/** @copydoc Matrix::Matrix(const RectangularMatrix<size, size, U>&) */
template<class U> inline constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other): Matrix<4, T>(other) {}
/** @brief Construct matrix from external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(std::declval<U>()))> inline constexpr explicit Matrix4(const U& other): Matrix<4, T>(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {}
/** @brief Copy constructor */
inline constexpr Matrix4(const RectangularMatrix<4, 4, T>& other): Matrix<4, T>(other) {}

19
src/Math/RectangularMatrix.h

@ -32,6 +32,10 @@
namespace Magnum { namespace Math {
namespace Implementation {
template<std::size_t, std::size_t, class, class> struct RectangularMatrixConverter;
}
/**
@brief Rectangular matrix
@tparam cols Column count
@ -140,12 +144,27 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
}
#endif
/** @brief Construct matrix from external representation */
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(std::declval<U>()))> inline constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(other)) {}
#else
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(std::declval<U>()))> inline explicit RectangularMatrix(const U& other) {
*this = Implementation::RectangularMatrixConverter<cols, rows, T, U>::from(other);
}
#endif
/** @brief Copy constructor */
inline constexpr RectangularMatrix(const RectangularMatrix<cols, rows, T>&) = default;
/** @brief Assignment operator */
inline RectangularMatrix<cols, rows, T>& operator=(const RectangularMatrix<cols, rows, T>&) = default;
/** @brief Convert matrix to external representation */
template<class U, class V = decltype(Implementation::RectangularMatrixConverter<cols, rows, T, U>::to(std::declval<RectangularMatrix<cols, rows, T>>()))> inline constexpr explicit operator U() const {
/** @bug Why this is not constexpr under GCC 4.6? */
return Implementation::RectangularMatrixConverter<cols, rows, T, U>::to(*this);
}
/**
* @brief Raw data
* @return One-dimensional array of `size*size` length in column-major

55
src/Math/Test/Matrix3Test.cpp

@ -28,7 +28,32 @@
#include "Math/Matrix3.h"
namespace Magnum { namespace Math { namespace Test {
struct Mat3 {
float a[9];
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct RectangularMatrixConverter<3, 3, float, Mat3> {
inline constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) {
return RectangularMatrix<3, 3, Float>(
Vector<3, Float>(other.a[0], other.a[1], other.a[2]),
Vector<3, Float>(other.a[3], other.a[4], other.a[5]),
Vector<3, Float>(other.a[6], other.a[7], other.a[8]));
}
inline constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) {
return Mat3{other[0][0], other[0][1], other[0][2],
other[1][0], other[1][1], other[1][2],
other[2][0], other[2][1], other[2][2]};
}
};
}
namespace Test {
class Matrix3Test: public Corrade::TestSuite::Tester {
public:
@ -40,6 +65,8 @@ class Matrix3Test: public Corrade::TestSuite::Tester {
void constructConversion();
void constructCopy();
void convert();
void isRigidTransformation();
void translation();
@ -62,6 +89,7 @@ typedef Math::Deg<Float> Deg;
typedef Math::Matrix3<Float> Matrix3;
typedef Math::Matrix3<Int> Matrix3i;
typedef Math::Matrix<2, Float> Matrix2;
typedef Math::Vector3<Float> Vector3;
typedef Math::Vector2<Float> Vector2;
Matrix3Test::Matrix3Test() {
@ -71,6 +99,8 @@ Matrix3Test::Matrix3Test() {
&Matrix3Test::constructConversion,
&Matrix3Test::constructCopy,
&Matrix3Test::convert,
&Matrix3Test::isRigidTransformation,
&Matrix3Test::translation,
@ -150,6 +180,29 @@ void Matrix3Test::constructCopy() {
{7.9f, -1.0f, 8.0f}));
}
void Matrix3Test::convert() {
constexpr Mat3 a{1.5f, 2.0f, -3.5f,
2.0f, -3.1f, 0.4f,
9.5f, -1.5f, 0.1f};
constexpr Matrix3 b(Vector3(1.5f, 2.0f, -3.5f),
Vector3(2.0f, -3.1f, 0.4f),
Vector3(9.5f, -1.5f, 0.1f));
constexpr Matrix3 c(b);
CORRADE_COMPARE(c, b);
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr /* Not constexpr under GCC < 4.7 */
#endif
Mat3 d(b);
for(std::size_t i = 0; i != 9; ++i)
CORRADE_COMPARE(d.a[0], a.a[0]);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Mat3, Matrix3>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix3, Mat3>::value));
}
void Matrix3Test::isRigidTransformation() {
CORRADE_VERIFY(!Matrix3({1.0f, 0.0f, 0.0f},
{0.1f, 1.0f, 0.0f},

58
src/Math/Test/Matrix4Test.cpp

@ -28,7 +28,34 @@
#include "Math/Matrix4.h"
namespace Magnum { namespace Math { namespace Test {
struct Mat4 {
float a[16];
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct RectangularMatrixConverter<4, 4, float, Mat4> {
inline constexpr static RectangularMatrix<4, 4, Float> from(const Mat4& other) {
return RectangularMatrix<4, 4, Float>(
Vector<4, Float>(other.a[0], other.a[1], other.a[2], other.a[3]),
Vector<4, Float>(other.a[4], other.a[5], other.a[6], other.a[7]),
Vector<4, Float>(other.a[8], other.a[9], other.a[10], other.a[11]),
Vector<4, Float>(other.a[12], other.a[13], other.a[14], other.a[15]));
}
inline constexpr static Mat4 to(const RectangularMatrix<4, 4, Float>& other) {
return Mat4{other[0][0], other[0][1], other[0][2], other[0][3],
other[1][0], other[1][1], other[1][2], other[1][3],
other[2][0], other[2][1], other[2][2], other[2][3],
other[3][0], other[3][1], other[3][2], other[3][3]};
}
};
}
namespace Test {
class Matrix4Test: public Corrade::TestSuite::Tester {
public:
@ -40,6 +67,8 @@ class Matrix4Test: public Corrade::TestSuite::Tester {
void constructConversion();
void constructCopy();
void convert();
void isRigidTransformation();
void translation();
@ -77,6 +106,8 @@ Matrix4Test::Matrix4Test() {
&Matrix4Test::constructConversion,
&Matrix4Test::constructCopy,
&Matrix4Test::convert,
&Matrix4Test::isRigidTransformation,
&Matrix4Test::translation,
@ -171,6 +202,31 @@ void Matrix4Test::constructCopy() {
{7.9f, -1.0f, 8.0f, -1.5f}));
}
void Matrix4Test::convert() {
constexpr Mat4 a{3.0f, 5.0f, 8.0f, -3.0f,
4.5f, 4.0f, 7.0f, 2.0f,
1.0f, 2.0f, 3.0f, -1.0f,
7.9f, -1.0f, 8.0f, -1.5f};
constexpr Matrix4 b({3.0f, 5.0f, 8.0f, -3.0f},
{4.5f, 4.0f, 7.0f, 2.0f},
{1.0f, 2.0f, 3.0f, -1.0f},
{7.9f, -1.0f, 8.0f, -1.5f});
constexpr Matrix4 c(b);
CORRADE_COMPARE(c, b);
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr /* Not constexpr under GCC < 4.7 */
#endif
Mat4 d(b);
for(std::size_t i = 0; i != 16; ++i)
CORRADE_COMPARE(d.a[i], a.a[i]);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Mat4, Matrix4>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix4, Mat4>::value));
}
void Matrix4Test::isRigidTransformation() {
CORRADE_VERIFY(!Matrix4({1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},

54
src/Math/Test/MatrixTest.cpp

@ -28,7 +28,32 @@
#include "Math/Matrix.h"
namespace Magnum { namespace Math { namespace Test {
struct Mat3 {
float a[9];
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct RectangularMatrixConverter<3, 3, float, Mat3> {
inline constexpr static RectangularMatrix<3, 3, Float> from(const Mat3& other) {
return RectangularMatrix<3, 3, Float>(
Vector<3, Float>(other.a[0], other.a[1], other.a[2]),
Vector<3, Float>(other.a[3], other.a[4], other.a[5]),
Vector<3, Float>(other.a[6], other.a[7], other.a[8]));
}
inline constexpr static Mat3 to(const RectangularMatrix<3, 3, Float>& other) {
return Mat3{other[0][0], other[0][1], other[0][2],
other[1][0], other[1][1], other[1][2],
other[2][0], other[2][1], other[2][2]};
}
};
}
namespace Test {
class MatrixTest: public Corrade::TestSuite::Tester {
public:
@ -40,6 +65,8 @@ class MatrixTest: public Corrade::TestSuite::Tester {
void constructConversion();
void constructCopy();
void convert();
void isOrthogonal();
void trace();
@ -67,6 +94,8 @@ MatrixTest::MatrixTest() {
&MatrixTest::constructConversion,
&MatrixTest::constructCopy,
&MatrixTest::convert,
&MatrixTest::isOrthogonal,
&MatrixTest::trace,
@ -149,6 +178,29 @@ void MatrixTest::constructCopy() {
Vector4(7.9f, -1.0f, 8.0f, -1.5f)));
}
void MatrixTest::convert() {
constexpr Mat3 a{1.5f, 2.0f, -3.5f,
2.0f, -3.1f, 0.4f,
9.5f, -1.5f, 0.1f};
constexpr Matrix3 b(Vector3(1.5f, 2.0f, -3.5f),
Vector3(2.0f, -3.1f, 0.4f),
Vector3(9.5f, -1.5f, 0.1f));
constexpr Matrix3 c(b);
CORRADE_COMPARE(c, b);
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr /* Not constexpr under GCC < 4.7 */
#endif
Mat3 d(b);
for(std::size_t i = 0; i != 9; ++i)
CORRADE_COMPARE(d.a[i], a.a[i]);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Mat3, Matrix3>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix3, Mat3>::value));
}
void MatrixTest::isOrthogonal() {
CORRADE_VERIFY(!Matrix3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),

52
src/Math/Test/RectangularMatrixTest.cpp

@ -28,7 +28,30 @@
#include "Math/RectangularMatrix.h"
namespace Magnum { namespace Math { namespace Test {
struct Mat2x3 {
float a[6];
};
namespace Magnum { namespace Math {
namespace Implementation {
template<> struct RectangularMatrixConverter<2, 3, float, Mat2x3> {
inline constexpr static RectangularMatrix<2, 3, Float> from(const Mat2x3& other) {
return RectangularMatrix<2, 3, Float>(
Vector<3, Float>(other.a[0], other.a[1], other.a[2]),
Vector<3, Float>(other.a[3], other.a[4], other.a[5]));
}
inline constexpr static Mat2x3 to(const RectangularMatrix<2, 3, Float>& other) {
return Mat2x3{other[0][0], other[0][1], other[0][2],
other[1][0], other[1][1], other[1][2]};
}
};
}
namespace Test {
class RectangularMatrixTest: public Corrade::TestSuite::Tester {
public:
@ -41,6 +64,7 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester {
void constructFromDiagonal();
void constructCopy();
void convert();
void data();
void row();
@ -77,6 +101,7 @@ RectangularMatrixTest::RectangularMatrixTest() {
&RectangularMatrixTest::constructFromDiagonal,
&RectangularMatrixTest::constructCopy,
&RectangularMatrixTest::convert,
&RectangularMatrixTest::data,
&RectangularMatrixTest::row,
@ -168,6 +193,31 @@ void RectangularMatrixTest::constructCopy() {
Vector4(9.0f, 10.0f, 11.0f, 12.0f)));
}
void RectangularMatrixTest::convert() {
typedef RectangularMatrix<2, 3, Float> Matrix2x3;
constexpr Mat2x3 a{1.5f, 2.0f, -3.5f,
2.0f, -3.1f, 0.4f};
constexpr Matrix2x3 b(Vector3(1.5f, 2.0f, -3.5f),
Vector3(2.0f, -3.1f, 0.4f));
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr /* Not constexpr under GCC < 4.7 */
#endif
Matrix2x3 c(b);
CORRADE_COMPARE(c, b);
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr /* Not constexpr under GCC < 4.7 */
#endif
Mat2x3 d(b);
for(std::size_t i = 0; i != 5; ++i)
CORRADE_COMPARE(d.a[i], a.a[i]);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Mat2x3, Matrix2x3>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix2x3, Mat2x3>::value));
}
void RectangularMatrixTest::data() {
Matrix3x4 m;
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f);

Loading…
Cancel
Save