Browse Source

"Initializer-list" constructor also for Matrix.

pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
b6ac0125dc
  1. 10
      src/Camera.cpp
  2. 9
      src/Math/Matrix.h
  3. 3
      src/Math/Matrix3.h
  4. 34
      src/Math/Matrix4.h
  5. 12
      src/Math/Test/Matrix3Test.cpp
  6. 32
      src/Math/Test/Matrix4Test.cpp
  7. 132
      src/Math/Test/MatrixTest.cpp
  8. 1
      src/Math/Test/MatrixTest.h

10
src/Camera.cpp

@ -45,11 +45,11 @@ void Camera::setPerspective(GLfloat fov, GLfloat near, GLfloat far) {
rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(2*far*near/(far+near))); rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(2*far*near/(far+near)));
/* Then apply magic perspective matrix (with reversed Z) */ /* Then apply magic perspective matrix (with reversed Z) */
static GLfloat a[] = { 1, 0, 0, 0, static Matrix4 a(1.0f, 0.0f, 0.0f, 0.0f,
0, 1, 0, 0, 0.0f, 1.0f, 0.0f, 0.0f,
0, 0, -1, -1, 0.0f, 0.0f, -1.0f, -1.0f,
0, 0, 0, 0 }; 0.0f, 0.0f, 0.0f, 0.0f);
rawProjectionMatrix = Matrix4(a)*rawProjectionMatrix; rawProjectionMatrix = a*rawProjectionMatrix;
/* Then scale the volume down so it fits in (-1, 1) in all directions */ /* Then scale the volume down so it fits in (-1, 1) in all directions */
GLfloat xyScale = 1/tan(fov/2); GLfloat xyScale = 1/tan(fov/2);

9
src/Math/Matrix.h

@ -41,6 +41,15 @@ template<class T, size_t size> class Matrix {
_data[size*i+i] = static_cast<T>(1); _data[size*i+i] = static_cast<T>(1);
} }
/**
* @brief Initializer-list constructor
* @param first First value
* @param next Next values
*
* Note that the values are in column-major order.
*/
template<class ...U> inline Matrix(T first, U&&... next): _data{first, std::forward<U>(next)...} {}
/** /**
* @brief Constructor * @brief Constructor
* @param data One-dimensional array of @c size*size length in column-major order. * @param data One-dimensional array of @c size*size length in column-major order.

3
src/Math/Matrix3.h

@ -30,6 +30,9 @@ template<class T> class Matrix3: public Matrix<T, 3> {
/** @copydoc Matrix::Matrix(bool) */ /** @copydoc Matrix::Matrix(bool) */
inline Matrix3(bool identity = true): Matrix<T, 3>(identity) {} inline Matrix3(bool identity = true): Matrix<T, 3>(identity) {}
/** @copydoc Matrix::Matrix(T, U&&...) */
template<class ...U> inline Matrix3(T first, U&&... next): Matrix<T, 3>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const T*) */ /** @copydoc Matrix::Matrix(const T*) */
inline Matrix3(const T* data): Matrix<T, 3>(data) {} inline Matrix3(const T* data): Matrix<T, 3>(data) {}

34
src/Math/Matrix4.h

@ -76,27 +76,29 @@ template<class T> class Matrix4: public Matrix<T, 4> {
T yz = vn.y()*vn.z(); T yz = vn.y()*vn.z();
T zz = vn.z()*vn.z(); T zz = vn.z()*vn.z();
/* Not creating identity matrix, as nearly all ones would be return Matrix4( /* Column-major! */
overwritten */ cosine + xx*oneMinusCosine,
Matrix4 out(false); xy*oneMinusCosine + vn.z()*sine,
out.set(3, 3, T(1)); xz*oneMinusCosine - vn.y()*sine,
T(0),
out.set(0, 0, cosine + xx*oneMinusCosine); xy*oneMinusCosine - vn.z()*sine,
out.set(0, 1, xy*oneMinusCosine - vn.z()*sine); cosine + yy*oneMinusCosine,
out.set(0, 2, xz*oneMinusCosine + vn.y()*sine); yz*oneMinusCosine + vn.x()*sine,
out.set(1, 0, xy*oneMinusCosine + vn.z()*sine); T(0),
out.set(1, 1, cosine + yy*oneMinusCosine); xz*oneMinusCosine + vn.y()*sine,
out.set(1, 2, yz*oneMinusCosine - vn.x()*sine); yz*oneMinusCosine - vn.x()*sine,
out.set(2, 0, xz*oneMinusCosine - vn.y()*sine); cosine + zz*oneMinusCosine,
out.set(2, 1, yz*oneMinusCosine + vn.x()*sine); T(0),
out.set(2, 2, cosine + zz*oneMinusCosine); T(0), T(0), T(0), T(1)
);
return out;
} }
/** @copydoc Matrix::Matrix(bool) */ /** @copydoc Matrix::Matrix(bool) */
inline Matrix4(bool identity = true): Matrix<T, 4>(identity) {} inline Matrix4(bool identity = true): Matrix<T, 4>(identity) {}
/** @copydoc Matrix::Matrix(T, U&&...) */
template<class ...U> inline Matrix4(T first, U&&... next): Matrix<T, 4>(first, std::forward<U>(next)...) {}
/** @copydoc Matrix::Matrix(const T*) */ /** @copydoc Matrix::Matrix(const T*) */
inline Matrix4(const T* data): Matrix<T, 4>(data) {} inline Matrix4(const T* data): Matrix<T, 4>(data) {}

12
src/Math/Test/Matrix3Test.cpp

@ -30,14 +30,14 @@ namespace Magnum { namespace Math { namespace Test {
typedef Math::Matrix3<float> Matrix3; typedef Math::Matrix3<float> Matrix3;
void Matrix3Test::debug() { void Matrix3Test::debug() {
float m[] = { Matrix3 m(
3, 5, 8, 3.0f, 5.0f, 8.0f,
4, 4, 7, 4.0f, 4.0f, 7.0f,
7, -1, 8, 7.0f, -1.0f, 8.0f
}; );
ostringstream o; ostringstream o;
Debug(&o) << Matrix3(m); Debug(&o) << m;
QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7,\n" QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7,\n"
" 5, 4, -1,\n" " 5, 4, -1,\n"
" 8, 7, 8)\n")); " 8, 7, 8)\n"));

32
src/Math/Test/Matrix4Test.cpp

@ -31,48 +31,48 @@ namespace Magnum { namespace Math { namespace Test {
typedef Math::Matrix4<float> Matrix4; typedef Math::Matrix4<float> Matrix4;
void Matrix4Test::translation() { void Matrix4Test::translation() {
float matrix[] = { Matrix4 matrix(
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
3.0f, 1.0f, 2.0f, 1.0f 3.0f, 1.0f, 2.0f, 1.0f
}; );
QVERIFY(Matrix4::translation({3.0f, 1.0f, 2.0f}) == Matrix4(matrix)); QVERIFY(Matrix4::translation({3.0f, 1.0f, 2.0f}) == matrix);
} }
void Matrix4Test::scaling() { void Matrix4Test::scaling() {
float matrix[] = { Matrix4 matrix(
3.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.5f, 0.0f, 0.0f, 0.0f, 1.5f, 0.0f, 0.0f,
0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f, 0.0f, 1.0f
}; );
QVERIFY(Matrix4::scaling({3.0f, 1.5f, 2.0f}) == Matrix4(matrix)); QVERIFY(Matrix4::scaling({3.0f, 1.5f, 2.0f}) == matrix);
} }
void Matrix4Test::rotation() { void Matrix4Test::rotation() {
float matrix[] = { Matrix4 matrix(
0.35612214f, -0.80181062f, 0.47987163f, 0.0f, 0.35612214f, -0.80181062f, 0.47987163f, 0.0f,
0.47987163f, 0.59757638f, 0.6423595f, 0.0f, 0.47987163f, 0.59757638f, 0.6423595f, 0.0f,
-0.80181062f, 0.0015183985f, 0.59757638f, 0.0f, -0.80181062f, 0.0015183985f, 0.59757638f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f, 0.0f, 1.0f
}; );
QVERIFY(Matrix4::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f}) == Matrix4(matrix)); QVERIFY(Matrix4::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f}) == matrix);
} }
void Matrix4Test::debug() { void Matrix4Test::debug() {
float m[] = { Matrix4 m(
3, 5, 8, 4, 3.0f, 5.0f, 8.0f, 4.0f,
4, 4, 7, 3, 4.0f, 4.0f, 7.0f, 3.0f,
7, -1, 8, 0, 7.0f, -1.0f, 8.0f, 0.0f,
9, 4, 5, 9 9.0f, 4.0f, 5.0f, 9.0f
}; );
ostringstream o; ostringstream o;
Debug(&o) << Matrix4(m); Debug(&o) << m;
QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7, 9,\n" QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7, 9,\n"
" 5, 4, -1, 4,\n" " 5, 4, -1, 4,\n"
" 8, 7, 8, 5,\n" " 8, 7, 8, 5,\n"

132
src/Math/Test/MatrixTest.cpp

@ -31,30 +31,48 @@ typedef Matrix<float, 4> Matrix4;
typedef Matrix<float, 3> Matrix3; typedef Matrix<float, 3> Matrix3;
typedef Vector<float, 4> Vector4; typedef Vector<float, 4> Vector4;
void MatrixTest::construct() {
float m[] = {
3.0f, 5.0f, 8.0f, 4.0f,
4.0f, 4.0f, 7.0f, 3.0f,
7.0f, -1.0f, 8.0f, 0.0f,
9.0f, 4.0f, 5.0f, 9.0f
};
Matrix4 expected(
3.0f, 5.0f, 8.0f, 4.0f,
4.0f, 4.0f, 7.0f, 3.0f,
7.0f, -1.0f, 8.0f, 0.0f,
9.0f, 4.0f, 5.0f, 9.0f
);
QVERIFY(Matrix4(m) == expected);
}
void MatrixTest::constructIdentity() { void MatrixTest::constructIdentity() {
Matrix4 identity; Matrix4 identity;
float identityExpected[] = { Matrix4 identityExpected(
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f, 0.0f, 1.0f
}; );
QVERIFY(identity == Matrix4(identityExpected)); QVERIFY(identity == identityExpected);
} }
void MatrixTest::constructZero() { void MatrixTest::constructZero() {
Matrix4 zero(false); Matrix4 zero(false);
float zeroExpected[] = { Matrix4 zeroExpected(
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f 0.0f, 0.0f, 0.0f, 0.0f
}; );
QVERIFY(zero == Matrix4(zeroExpected)); QVERIFY(zero == zeroExpected);
} }
void MatrixTest::data() { void MatrixTest::data() {
@ -71,14 +89,14 @@ void MatrixTest::data() {
QVERIFY(m.at(1, 2) == 1.0f); QVERIFY(m.at(1, 2) == 1.0f);
QVERIFY(m.at(3) == vector); QVERIFY(m.at(3) == vector);
float expected[] = { Matrix4 expected(
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.5f, 0.0f, 0.0f, 0.0f, 1.5f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4.0f, 5.0f, 6.0f, 7.0f 4.0f, 5.0f, 6.0f, 7.0f
}; );
QVERIFY(m == Matrix4(expected)); QVERIFY(m == expected);
} }
void MatrixTest::copy() { void MatrixTest::copy() {
@ -104,141 +122,137 @@ void MatrixTest::copy() {
} }
void MatrixTest::multiplyIdentity() { void MatrixTest::multiplyIdentity() {
float values[] = { Matrix4 values(
0.0f, 1.0f, 2.0f, 3.0f, 0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, 7.0f, 4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f, 8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f 12.0f, 13.0f, 14.0f, 15.0f
}; );
QVERIFY(Matrix4()*Matrix4(values) == Matrix4(values)); QVERIFY(Matrix4()*values == values);
QVERIFY(Matrix4(values)*Matrix4() == Matrix4(values)); QVERIFY(values*Matrix4() == values);
} }
void MatrixTest::multiply() { void MatrixTest::multiply() {
int left[] = { Matrix<int, 5> left(
-3, -3, -1, 3, -5, -3, -3, -1, 3, -5,
-1, -3, -5, 2, 3, -1, -3, -5, 2, 3,
-1, -4, 3, -1, -2, -1, -4, 3, -1, -2,
-5, -5, -1, -4, -1, -5, -5, -1, -4, -1,
1, 3, -3, -4, -1 1, 3, -3, -4, -1
}; );
int right[] = { Matrix<int, 5> right(
0, 5, 3, 4, 4, 0, 5, 3, 4, 4,
5, 5, 0, 0, -2, 5, 5, 0, 0, -2,
3, 2, -4, -3, 0, 3, 2, -4, -3, 0,
-3, 0, -1, 2, -1, -3, 0, -1, 2, -1,
0, -1, -4, 4, 3 0, -1, -4, 4, 3
}; );
int expected[] = { Matrix<int, 5> expected(
-24, -35, -32, -25, 1, -24, -35, -32, -25, 1,
-22, -36, -24, 33, -8, -22, -36, -24, 33, -8,
8, 16, -22, 29, 2, 8, 16, -22, 29, 2,
-1, 0, 1, -12, 16, -1, 0, 1, -12, 16,
-12, 8, -20, -26, -2 -12, 8, -20, -26, -2
}; );
bool is = (Matrix<int, 5>(left)*Matrix<int, 5>(right) == Matrix<int, 5>(expected));
QVERIFY(is); QVERIFY(left*right == expected);
} }
void MatrixTest::multiplyVector() { void MatrixTest::multiplyVector() {
int matrix[] = { Matrix<int, 5> matrix(
-3, -3, -1, 3, -5, -3, -3, -1, 3, -5,
-1, -3, -5, 2, 3, -1, -3, -5, 2, 3,
-1, -4, 3, -1, -2, -1, -4, 3, -1, -2,
-5, -5, -1, -4, -1, -5, -5, -1, -4, -1,
1, 3, -3, -4, -1 1, 3, -3, -4, -1
}; );
bool is = (Matrix<int, 5>(matrix)*Vector<int, 5>(0, 5, 3, 4, 4) == Vector<int, 5>(-24, -35, -32, -25, 1)); bool is = (matrix*Vector<int, 5>(0, 5, 3, 4, 4) == Vector<int, 5>(-24, -35, -32, -25, 1));
QVERIFY(is); QVERIFY(is);
} }
void MatrixTest::transposed() { void MatrixTest::transposed() {
float original[] = { Matrix4 original(
0.0f, 1.0f, 2.0f, 3.0f, 0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, 7.0f, 4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f, 8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f 12.0f, 13.0f, 14.0f, 15.0f
}; );
float transposed[] = { Matrix4 transposed(
0.0f, 4.0f, 8.0f, 12.0f, 0.0f, 4.0f, 8.0f, 12.0f,
1.0f, 5.0f, 9.0f, 13.0f, 1.0f, 5.0f, 9.0f, 13.0f,
2.0f, 6.0f, 10.0f, 14.0f, 2.0f, 6.0f, 10.0f, 14.0f,
3.0f, 7.0f, 11.0f, 15.0f 3.0f, 7.0f, 11.0f, 15.0f
}; );
QVERIFY(Matrix4(original).transposed() == Matrix4(transposed)); QVERIFY(original.transposed() == transposed);
} }
void MatrixTest::ij() { void MatrixTest::ij() {
float original[] = { Matrix4 original(
0.0f, 1.0f, 2.0f, 3.0f, 0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, 7.0f, 4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f, 8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f 12.0f, 13.0f, 14.0f, 15.0f
}; );
float skipped[] = { Matrix3 skipped(
0.0f, 1.0f, 3.0f, 0.0f, 1.0f, 3.0f,
8.0f, 9.0f, 11.0f, 8.0f, 9.0f, 11.0f,
12.0f, 13.0f, 15.0f 12.0f, 13.0f, 15.0f
}; );
QVERIFY(Matrix4(original).ij(2, 1) == Matrix3(skipped)); QVERIFY(original.ij(2, 1) == skipped);
} }
void MatrixTest::determinant() { void MatrixTest::determinant() {
int m[] = { Matrix<int, 5> m(
1, 2, 2, 1, 0, 1, 2, 2, 1, 0,
2, 3, 2, 1, -2, 2, 3, 2, 1, -2,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
2, 0, 0, 1, 2, 2, 0, 0, 1, 2,
3, 1, 0, 1, -2 3, 1, 0, 1, -2
}; );
int d = Matrix<int, 5>(m).determinant(); QVERIFY(m.determinant() == -2);
QVERIFY(d == -2);
} }
void MatrixTest::inverse() { void MatrixTest::inverse() {
float m[] = { Matrix4 m(
3, 5, 8, 4, 3.0f, 5.0f, 8.0f, 4.0f,
4, 4, 7, 3, 4.0f, 4.0f, 7.0f, 3.0f,
7, -1, 8, 0, 7.0f, -1.0f, 8.0f, 0.0f,
9, 4, 5, 9 9.0f, 4.0f, 5.0f, 9.0f
}; );
float inverse[] = { Matrix4 inverse(
-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f, -60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f,
-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f, -66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f,
177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f, 177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f,
259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f 259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f
}; );
Matrix4 _inverse = Matrix4(m).inverse(); Matrix4 _inverse = m.inverse();
QVERIFY(_inverse == Matrix4(inverse)); QVERIFY(_inverse == inverse);
QVERIFY(_inverse*Matrix4(m) == Matrix4()); QVERIFY(_inverse*m == Matrix4());
} }
void MatrixTest::debug() { void MatrixTest::debug() {
float m[] = { Matrix4 m(
3, 5, 8, 4, 3.0f, 5.0f, 8.0f, 4.0f,
4, 4, 7, 3, 4.0f, 4.0f, 7.0f, 3.0f,
7, -1, 8, 0, 7.0f, -1.0f, 8.0f, 0.0f,
9, 4, 5, 9 9.0f, 4.0f, 5.0f, 9.0f
}; );
ostringstream o; ostringstream o;
Debug(&o) << Matrix4(m); Debug(&o) << m;
QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7, 9,\n" QCOMPARE(QString::fromStdString(o.str()), QString("Matrix(3, 4, 7, 9,\n"
" 5, 4, -1, 4,\n" " 5, 4, -1, 4,\n"
" 8, 7, 8, 5,\n" " 8, 7, 8, 5,\n"

1
src/Math/Test/MatrixTest.h

@ -23,6 +23,7 @@ class MatrixTest: public QObject {
Q_OBJECT Q_OBJECT
private slots: private slots:
void construct();
void constructIdentity(); void constructIdentity();
void constructZero(); void constructZero();
void data(); void data();

Loading…
Cancel
Save