Browse Source

Better (hopefully) way to distinguish between Matrix constructors.

Before it was one constructor using bool parameter, which is massive
antipattern:

    Matrix4 m(false); // Huh? No Matrix4 then or what?

Iẗ́'s now separated into two distinct constructors, of them one can be
already declared as constexpr (hooray). The usage is as follows:

    Matrix4 a;                    // Default (identity matrix)
    Matrix4 b(Matrix4::Identity); // Explicitly identity matrix
    Matrix4 c(Matrix4::Zero);     // Zero-filled matrix

Also deleted constructor from one parameter, so following mistakes
now cannot compile:

    Matrix4 d(true);          // Both would set element at [0][0] to 1,
    Matrix4 e(Matrix3::Zero); // and other to 0
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
4f1c7ccfa0
  1. 33
      src/Math/Matrix.h
  2. 17
      src/Math/Matrix3.h
  3. 19
      src/Math/Matrix4.h
  4. 10
      src/Math/Test/MatrixTest.cpp

33
src/Math/Matrix.h

@ -73,16 +73,35 @@ template<class T, size_t size> class Matrix {
return from(typename Implementation::GenerateSequence<size>::Type(), first, next...);
}
/** @brief Pass to constructor to create zero-filled matrix */
enum ZeroType { Zero };
/**
* @brief Zero-filled matrix constructor
*
* Use this constructor by calling `Matrix m(Matrix::Zero);`.
*/
inline constexpr explicit Matrix(ZeroType): _data() {}
/** @brief Pass to constructor to create identity matrix */
enum IdentityType { Identity };
/**
* @brief Default constructor
* @param identity Create identity matrix instead of zero matrix.
*
* You can also explicitly call this constructor with
* `Matrix m(Matrix::Identity);`.
*/
inline explicit Matrix(bool identity = true): _data() {
inline explicit Matrix(IdentityType = Identity): _data() {
/** @todo constexpr how? */
if(identity) for(size_t i = 0; i != size; ++i)
for(size_t i = 0; i != size; ++i)
_data[size*i+i] = static_cast<T>(1);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> explicit Matrix(U) = delete;
#endif
/**
* @brief Initializer-list constructor
* @param first First value
@ -136,7 +155,7 @@ template<class T, size_t size> class Matrix {
/** @brief Multiply matrix operator */
Matrix<T, size> operator*(const Matrix<T, size>& other) const {
Matrix<T, size> out(false);
Matrix<T, size> out(Zero);
for(size_t row = 0; row != size; ++row)
for(size_t col = 0; col != size; ++col)
@ -164,7 +183,7 @@ template<class T, size_t size> class Matrix {
/** @brief Transposed matrix */
Matrix<T, size> transposed() const {
Matrix<T, size> out(false);
Matrix<T, size> out(Zero);
for(size_t row = 0; row != size; ++row)
for(size_t col = 0; col != size; ++col)
@ -175,7 +194,7 @@ template<class T, size_t size> class Matrix {
/** @brief %Matrix without given column and row */
Matrix<T, size-1> ij(size_t skipCol, size_t skipRow) const {
Matrix<T, size-1> out(false);
Matrix<T, size-1> out(Matrix<T, size-1>::Zero);
for(size_t row = 0; row != size-1; ++row)
for(size_t col = 0; col != size-1; ++col)
@ -198,7 +217,7 @@ template<class T, size_t size> class Matrix {
* @brief Inverse matrix
*/
Matrix<T, size> inversed() const {
Matrix<T, size> out(false);
Matrix<T, size> out(Zero);
T _determinant = determinant();

17
src/Math/Matrix3.h

@ -42,14 +42,21 @@ template<class T> class Matrix3: public Matrix<T, 3> {
return Matrix<T, 3>::from(first, next...);
}
/** @copydoc Matrix::Matrix(bool) */
inline constexpr explicit Matrix3(bool identity = true): Matrix<T, 3>{
/** @copydoc Matrix::Matrix(ZeroType) */
inline constexpr explicit Matrix3(typename Matrix<T, 3>::ZeroType): Matrix<T, 3>(Matrix<T, 3>::Zero) {}
/** @copydoc Matrix::Matrix(IdentityType) */
inline constexpr explicit Matrix3(typename Matrix<T, 3>::IdentityType = Matrix<T, 3>::Identity): Matrix<T, 3>{
/** @todo Make this in Matrix itself, after it will be constexpr */
identity ? 1.0f : 0.0f, 0.0f, 0.0f,
0.0f, identity ? 1.0f : 0.0f, 0.0f,
0.0f, 0.0f, identity ? 1.0f : 0.0f
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
} {}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> explicit Matrix3(U) = delete;
#endif
/** @copydoc Matrix::Matrix(T, U...) */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class ...U> inline constexpr Matrix3(T first, U... next): Matrix<T, 3>(first, next...) {}

19
src/Math/Matrix4.h

@ -110,15 +110,22 @@ template<class T> class Matrix4: public Matrix<T, 4> {
);
}
/** @copydoc Matrix::Matrix(bool) */
inline constexpr explicit Matrix4(bool identity = true): Matrix<T, 4>{
/** @copydoc Matrix::Matrix(ZeroType) */
inline constexpr explicit Matrix4(typename Matrix<T, 4>::ZeroType): Matrix<T, 3>(Matrix<T, 3>::Zero) {}
/** @copydoc Matrix::Matrix(IdentityType) */
inline constexpr explicit Matrix4(typename Matrix<T, 4>::IdentityType = Matrix<T, 4>::Identity): Matrix<T, 4>{
/** @todo Make this in Matrix itself, after it will be constexpr */
identity ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, identity ? 1.0f : 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, identity ? 1.0f : 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, identity ? 1.0f : 0.0f
1.0f, 0.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, 0.0f, 1.0f
} {}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U> explicit Matrix4(U) = delete;
#endif
/** @copydoc Matrix::Matrix(T, U...) */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class ...U> inline constexpr Matrix4(T first, U... next): Matrix<T, 4>(first, next...) {}

10
src/Math/Test/MatrixTest.cpp

@ -65,6 +65,7 @@ void MatrixTest::constructFromVectors() {
void MatrixTest::constructIdentity() {
Matrix4 identity;
Matrix4 identity2(Matrix4::Identity);
Matrix4 identityExpected(
1.0f, 0.0f, 0.0f, 0.0f,
@ -74,10 +75,11 @@ void MatrixTest::constructIdentity() {
);
QVERIFY(identity == identityExpected);
QVERIFY(identity2 == identityExpected);
}
void MatrixTest::constructZero() {
Matrix4 zero(false);
Matrix4 zero(Matrix4::Zero);
Matrix4 zeroExpected(
0.0f, 0.0f, 0.0f, 0.0f,
@ -90,7 +92,7 @@ void MatrixTest::constructZero() {
}
void MatrixTest::data() {
Matrix4 m(false);
Matrix4 m(Matrix4::Zero);
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f);
@ -113,7 +115,7 @@ void MatrixTest::data() {
}
void MatrixTest::copy() {
Matrix4 m1(false);
Matrix4 m1(Matrix4::Zero);
m1[2][3] = 1.0f;
@ -127,7 +129,7 @@ void MatrixTest::copy() {
m1[3][2] = 1.0f;
/* Verify the copy is the same as original */
Matrix4 original(false);
Matrix4 original(Matrix4::Zero);
original[2][3] = 1.0f;
QVERIFY(m2 == original);

Loading…
Cancel
Save