diff --git a/matrix.cpp b/matrix.cpp index e83641da..45af099f 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2011-2014 Danny Robson + * Copyright 2011-2015 Danny Robson */ #include "matrix.hpp" @@ -26,25 +26,25 @@ using namespace util; //----------------------------------------------------------------------------- -template -matrix -matrix::transposed (void) const +template +matrix +matrix::transposed (void) const { - matrix m; - for (size_t i = 0; i < 4; ++i) - for (size_t j = 0; j < 4; ++j) + matrix m; + for (size_t i = 0; i < S; ++i) + for (size_t j = 0; j < S; ++j) m.values[i][j] = values[j][i]; return m; } //----------------------------------------------------------------------------- -template -matrix& -matrix::transpose (void) +template +matrix& +matrix::transpose (void) { - for (size_t i = 0; i < 4; ++i) - for (size_t j = i + 1; j < 4; ++j) + for (size_t i = 0; i < S; ++i) + for (size_t j = i + 1; j < S; ++j) std::swap (values[i][j], values[j][i]); return *this; @@ -52,9 +52,11 @@ matrix::transpose (void) //----------------------------------------------------------------------------- -template -matrix -matrix::inverse (void) const { +template +matrix +matrix::inverse (void) const { + static_assert (S == 4, "assuming 4x4 matrices"); + // GLM's implementation of 4x4 matrix inversion. Should allow use of // vector instructions. const auto &m = values; @@ -104,10 +106,10 @@ matrix::inverse (void) const { vector<4,T> SignA(+1, -1, +1, -1); vector<4,T> SignB(-1, +1, -1, +1); //matrix Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); - matrix Inverse = { { { Inv0.x * SignA.x, Inv0.y * SignA.y, Inv0.z * SignA.z, Inv0.w * SignA.w }, - { Inv1.x * SignB.x, Inv1.y * SignB.y, Inv1.z * SignB.z, Inv1.w * SignB.w }, - { Inv2.x * SignA.x, Inv2.y * SignA.y, Inv2.z * SignA.z, Inv2.w * SignA.w }, - { Inv3.x * SignB.x, Inv3.y * SignB.y, Inv3.z * SignB.z, Inv3.w * SignB.w } } }; + matrix<4,T> Inverse = { { { Inv0.x * SignA.x, Inv0.y * SignA.y, Inv0.z * SignA.z, Inv0.w * SignA.w }, + { Inv1.x * SignB.x, Inv1.y * SignB.y, Inv1.z * SignB.z, Inv1.w * SignB.w }, + { Inv2.x * SignA.x, Inv2.y * SignA.y, Inv2.z * SignA.z, Inv2.w * SignA.w }, + { Inv3.x * SignB.x, Inv3.y * SignB.y, Inv3.z * SignB.z, Inv3.w * SignB.w } } }; vector<4,T> Row0(Inverse.values[0][0], Inverse.values[1][0], Inverse.values[2][0], Inverse.values[3][0]); @@ -127,25 +129,25 @@ matrix::inverse (void) const { //----------------------------------------------------------------------------- -template -matrix& -matrix::invert (void) { +template +matrix& +matrix::invert (void) { return *this = inverse (); } //----------------------------------------------------------------------------- -template -matrix -matrix::inverse_affine (void) const { - return matrix(*this).invert_affine (); +template +matrix +matrix::inverse_affine (void) const { + return matrix(*this).invert_affine (); } //----------------------------------------------------------------------------- -template -matrix& -matrix::invert_affine (void) { +template +matrix& +matrix::invert_affine (void) { CHECK (is_affine ()); // inv ([ M b ] == [ inv(M) -inv(M).b ] @@ -191,9 +193,9 @@ matrix::invert_affine (void) { //----------------------------------------------------------------------------- -template +template T -matrix::det (void) const { +matrix::det (void) const { return values[0][3] * values[1][2] * values[2][1] * values[3][0] - values[0][2] * values[1][3] * values[2][1] * values[3][0] - values[0][3] * values[1][1] * values[2][2] * values[3][0] + @@ -225,16 +227,16 @@ matrix::det (void) const { //----------------------------------------------------------------------------- -template -matrix -matrix::operator* (const matrix &rhs) const { - matrix m; +template +matrix +matrix::operator* (const matrix &rhs) const { + matrix m; - for (unsigned row = 0; row < 4; ++row) { - for (unsigned col = 0; col < 4; ++col) { + for (unsigned row = 0; row < S; ++row) { + for (unsigned col = 0; col < S; ++col) { m.values[row][col] = T {0}; - for (unsigned inner = 0; inner < 4; ++inner) + for (unsigned inner = 0; inner < S; ++inner) m.values[row][col] += values[row][inner] * rhs.values[inner][col]; } } @@ -244,38 +246,38 @@ matrix::operator* (const matrix &rhs) const { //----------------------------------------------------------------------------- -template -matrix& -matrix::operator*=(const matrix &rhs) { +template +matrix& +matrix::operator*=(const matrix &rhs) { return *this = *this * rhs; } /////////////////////////////////////////////////////////////////////////////// -template -vector<3,T> -matrix::operator* (vector<3,T> v) const -{ - return ( - *this * v.template homog<4> () - ).template redim<3> (); -} +//template +//vector<3,T> +//matrix::operator* (vector<3,T> v) const +//{ +// return ( +// *this * v.template homog () +// ).template redim<3> (); +//} +// +// +////----------------------------------------------------------------------------- +//template +//point<3,T> +//matrix::operator* (point<3,T> p) const +//{ +// return (*this * p.template homog ()).template redim<3> (); +//} //----------------------------------------------------------------------------- -template -point<3,T> -matrix::operator* (point<3,T> p) const -{ - return (*this * p.template homog<4> ()).template redim<3> (); -} - - -//----------------------------------------------------------------------------- -template -vector<4,T> -matrix::operator* (const vector<4,T> &rhs) const { - return vector<4,T> { +template +vector +matrix::operator* (const vector &rhs) const { + return vector { values[0][0] * rhs.x + values[0][1] * rhs.y + values[0][2] * rhs.z + values[0][3] * rhs.w, values[1][0] * rhs.x + values[1][1] * rhs.y + values[1][2] * rhs.z + values[1][3] * rhs.w, values[2][0] * rhs.x + values[2][1] * rhs.y + values[2][2] * rhs.z + values[2][3] * rhs.w, @@ -285,11 +287,11 @@ matrix::operator* (const vector<4,T> &rhs) const { //----------------------------------------------------------------------------- -template -point<4,T> -matrix::operator* (const point<4,T> &rhs) const +template +point +matrix::operator* (const point &rhs) const { - return point<4,T> { + return point { values[0][0] * rhs.x + values[0][1] * rhs.y + values[0][2] * rhs.z + values[0][3] * rhs.w, values[1][0] * rhs.x + values[1][1] * rhs.y + values[1][2] * rhs.z + values[1][3] * rhs.w, values[2][0] * rhs.x + values[2][1] * rhs.y + values[2][2] * rhs.z + values[2][3] * rhs.w, @@ -299,14 +301,14 @@ matrix::operator* (const point<4,T> &rhs) const //----------------------------------------------------------------------------- -template -matrix -matrix::operator* (T f) const +template +matrix +matrix::operator* (T f) const { - matrix out; + matrix out; - for (size_t i = 0; i < 4; ++i) - for (size_t j = 0; j < 4; ++j) + for (size_t i = 0; i < S; ++i) + for (size_t j = 0; j < S; ++j) out.values[i][j] = values[i][j] * f; return out; @@ -314,11 +316,11 @@ matrix::operator* (T f) const //----------------------------------------------------------------------------- -template -matrix& -matrix::operator*= (T f){ - for (size_t i = 0; i < 4; ++i) - for (size_t j = 0; j < 4; ++j) +template +matrix& +matrix::operator*= (T f){ + for (size_t i = 0; i < S; ++i) + for (size_t j = 0; j < S; ++j) values[i][j] *= f; return *this; @@ -326,10 +328,10 @@ matrix::operator*= (T f){ //----------------------------------------------------------------------------- -template -matrix -matrix::operator/ (T s) const { - matrix m; +template +matrix +matrix::operator/ (T s) const { + matrix m; for (size_t r = 0; r < m.rows; ++r) for (size_t c = 0; c < m.cols; ++c) @@ -340,9 +342,9 @@ matrix::operator/ (T s) const { //----------------------------------------------------------------------------- -template -matrix& -matrix::operator/= (T s) { +template +matrix& +matrix::operator/= (T s) { for (size_t r = 0; r < rows; ++r) for (size_t c = 0; c < cols; ++c) values[r][c] /= s; @@ -352,9 +354,9 @@ matrix::operator/= (T s) { //----------------------------------------------------------------------------- -template +template bool -matrix::operator== (const matrix &rhs) const { +matrix::operator== (const matrix &rhs) const { for (size_t r = 0; r < rows; ++r) for (size_t c = 0; c < cols; ++c) if (!almost_equal (rhs.values[r][c], values[r][c])) @@ -364,9 +366,9 @@ matrix::operator== (const matrix &rhs) const { //----------------------------------------------------------------------------- -template +template bool -matrix::is_affine (void) const { +matrix::is_affine (void) const { return exactly_equal (values[3][0], T {0}) && exactly_equal (values[3][1], T {0}) && exactly_equal (values[3][2], T {0}) && @@ -375,11 +377,11 @@ matrix::is_affine (void) const { //----------------------------------------------------------------------------- -template -matrix -matrix::ortho (T left, T right, - T bottom, T top, - T near, T far) +template +matrix4 +matrix::ortho (T left, T right, + T bottom, T top, + T near, T far) { CHECK_GT (far, near); @@ -401,19 +403,19 @@ matrix::ortho (T left, T right, //----------------------------------------------------------------------------- -template -matrix -matrix::ortho2D (T left, T right, - T bottom, T top) +template +matrix4 +matrix::ortho2D (T left, T right, + T bottom, T top) { return ortho (left, right, bottom, top, -1, 1); } //----------------------------------------------------------------------------- -template -matrix -matrix::perspective (T fov, T aspect, T near, T far) +template +matrix4 +matrix::perspective (T fov, T aspect, T near, T far) { T f = std::tan (fov / 2); @@ -433,11 +435,11 @@ matrix::perspective (T fov, T aspect, T near, T far) //----------------------------------------------------------------------------- // Emulates gluLookAt -template -matrix -matrix::look_at (util::point<3,T> eye, - util::point<3,T> centre, - util::vector<3,T> up) +template +matrix4 +matrix::look_at (util::point<3,T> eye, + util::point<3,T> centre, + util::vector<3,T> up) { const auto f = (centre - eye).normalise (); const auto s = cross (f, up).normalise (); @@ -453,18 +455,18 @@ matrix::look_at (util::point<3,T> eye, //----------------------------------------------------------------------------- -template -matrix -matrix::translate (util::vector<2,T> v) +template +matrix4 +matrix::translate (util::vector<2,T> v) { return translate ({v.x, v.y, 0}); } //----------------------------------------------------------------------------- -template -matrix -matrix::translate (util::vector<3,T> v) +template +matrix4 +matrix::translate (util::vector<3,T> v) { return { { { 1.f, 0.f, 0.f, v.x }, @@ -476,17 +478,17 @@ matrix::translate (util::vector<3,T> v) //----------------------------------------------------------------------------- -template -matrix -matrix::scale (T mag) +template +matrix4 +matrix::scale (T mag) { return scale (vector<3,T> (mag)); } //----------------------------------------------------------------------------- -template -matrix -matrix::scale (util::vector<3,T> v) +template +matrix4 +matrix::scale (util::vector<3,T> v) { return { { { v.x, 0.f, 0.f, 0.f }, @@ -498,9 +500,9 @@ matrix::scale (util::vector<3,T> v) //----------------------------------------------------------------------------- -template -matrix -matrix::rotate (T angle, util::vector<3,T> about) +template +matrix4 +matrix::rotate (T angle, util::vector<3,T> about) { about.normalise (); @@ -534,33 +536,33 @@ matrix::rotate (T angle, util::vector<3,T> about) } //----------------------------------------------------------------------------- -template -const matrix -matrix::IDENTITY = { { { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 1, 0 }, - { 0, 0, 0, 1 } } }; +template +const matrix +matrix::IDENTITY = { { { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } } }; -template -const matrix -matrix::ZEROES = { { { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 } } }; +template +const matrix +matrix::ZEROES = { { { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } } }; //----------------------------------------------------------------------------- namespace util { - template struct matrix; - template struct matrix; + template struct matrix<4,float>; + template struct matrix<4,double>; } //----------------------------------------------------------------------------- namespace util { - template + template std::ostream& - operator<< (std::ostream &os, const matrix &m) { + operator<< (std::ostream &os, const matrix &m) { os << "{ {" << m.values[0][0] << ", " << m.values[0][1] << ", " << m.values[0][2] << ", " @@ -582,5 +584,5 @@ namespace util { } } -template std::ostream& util::operator<< (std::ostream&, const matrix&); -template std::ostream& util::operator<< (std::ostream&, const matrix&); +template std::ostream& util::operator<< (std::ostream&, const matrix<4,float>&); +template std::ostream& util::operator<< (std::ostream&, const matrix<4,double>&); diff --git a/matrix.hpp b/matrix.hpp index 473eaaf1..19a9d358 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2011-2014 Danny Robson + * Copyright 2011-2015 Danny Robson */ #ifndef __UTIL_MATRIX_HPP @@ -22,69 +22,73 @@ #include namespace util { - template + template struct matrix { - T values[4][4]; + T values[S][S]; - static const size_t rows = 4; - static const size_t cols = 4; + static const size_t rows = S; + static const size_t cols = S; matrix& transpose (void); matrix transposed (void) const; - matrix inverse (void) const; - matrix& invert (void); - matrix inverse_affine (void) const; - matrix& invert_affine (void); + matrix inverse (void) const; + matrix& invert (void); + matrix inverse_affine (void) const; + matrix& invert_affine (void); T det (void) const; - matrix operator* (const matrix&) const; - matrix& operator*=(const matrix&); + matrix operator* (const matrix&) const; + matrix& operator*=(const matrix&); - vector<3,T> operator* (vector<3,T>) const; - point<3,T> operator* (point<3,T>) const; + //vector<3,T> operator* (vector<3,T>) const; + //point<3,T> operator* (point<3,T>) const; - vector<4,T> operator* (const vector<4,T>&) const; - point<4,T> operator* (const point<4,T> &) const; + vector operator* (const vector&) const; + point operator* (const point &) const; - matrix operator* (T) const; - matrix& operator*= (T); - matrix operator/ (T) const; - matrix& operator/= (T); + matrix operator* (T) const; + matrix& operator*= (T); + matrix operator/ (T) const; + matrix& operator/= (T); - bool operator== (const matrix&) const; + bool operator== (const matrix&) const; bool is_affine (void) const; template - matrix cast (void) const; + matrix cast (void) const; // Perspective matrices - static matrix ortho (T left, T right, T bottom, T top, T near, T far); - static matrix ortho2D (T left, T right, T bottom, T top); - static matrix perspective (T fov, T aspect, T near, T far); - static matrix look_at (point<3,T> eye, point<3,T> centre, vector<3,T> up); + static matrix<4,T> ortho (T left, T right, T bottom, T top, T near, T far); + static matrix<4,T> ortho2D (T left, T right, T bottom, T top); + static matrix<4,T> perspective (T fov, T aspect, T near, T far); + static matrix<4,T> look_at (point<3,T> eye, point<3,T> centre, vector<3,T> up); // Affine matrices - static matrix translate (util::vector<2,T>); - static matrix translate (util::vector<3,T>); - static matrix scale (util::vector<3,T>); - static matrix scale (T); - static matrix rotate (T angle, util::vector<3,T> about); + static matrix<4,T> translate (util::vector<2,T>); + static matrix<4,T> translate (util::vector<3,T>); + static matrix<4,T> scale (util::vector<3,T>); + static matrix<4,T> scale (T); + static matrix<4,T> rotate (T angle, util::vector<3,T> about); // Constant matrices - static const matrix IDENTITY; - static const matrix ZEROES; + static const matrix IDENTITY; + static const matrix ZEROES; }; - template using matrix4 = matrix; + template using matrix3 = matrix<3,T>; + template using matrix4 = matrix<4,T>; - typedef matrix matrixf; - typedef matrix matrix4f; + template using matrixf = matrix; + template using matrixd = matrix; - template - std::ostream& operator<< (std::ostream&, const matrix&); + typedef matrix<4,float> matrix4f; + typedef matrix<4,double> matrix4d; + + template + std::ostream& operator<< (std::ostream&, const matrix&); } #include "matrix.ipp" diff --git a/matrix.ipp b/matrix.ipp index 4cfafe5f..40c31c7b 100644 --- a/matrix.ipp +++ b/matrix.ipp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2011-2014 Danny Robson + * Copyright 2011-2015 Danny Robson */ @@ -21,12 +21,12 @@ #define __UTIL_MATRIX_IPP -template +template template -util::matrix -util::matrix::cast (void) const +util::matrix +util::matrix::cast (void) const { - util::matrix out; + util::matrix out; for (size_t i = 0; i < rows; ++i) for (size_t j = 0; j < cols; ++j) diff --git a/test/matrix.cpp b/test/matrix.cpp index 8ce64810..b85a75ea 100644 --- a/test/matrix.cpp +++ b/test/matrix.cpp @@ -13,14 +13,14 @@ main (void) { // Identity matrix-vector multiplication - auto v = util::vector<4,float> { 1.f, 2.f, 3.f, 4.f }; - auto r = util::matrix::IDENTITY * v; + auto v = util::vector4f { 1.f, 2.f, 3.f, 4.f }; + auto r = util::matrix4f::IDENTITY * v; tap.expect_eq (r, v, "identity matrix-vector multiplication"); } { // Simple matrix-vector multiplication - util::matrix m { { + util::matrix4f m { { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, @@ -42,28 +42,28 @@ main (void) { // Simple matrix-matrix multiplication - util::matrix a { { + util::matrix4f a { { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 }, } }; - util::matrix b { { + util::matrix4f b { { { 17, 18, 19, 20 }, { 21, 22, 23, 24 }, { -1, -2, -3, -4 }, { -5, -6, -7, -8 } } }; - util::matrix ab { { + util::matrix4f ab { { { 9, 8, 7, 6 }, { 41, 40, 39, 38 }, { 73, 72, 71, 70 }, { 105, 104, 103, 102 }, } }; - ab *= 4; + ab *= 4.f; auto res = a * b; @@ -75,7 +75,7 @@ main (void) bool success = true; // Ensure identity inverts to identity - auto m = util::matrix::IDENTITY.inverse (); + auto m = util::matrix4f::IDENTITY.inverse (); for (size_t r = 0; r < m.rows; ++r) for (size_t c = 0; c < m.cols; ++c) if (r == c) @@ -88,14 +88,14 @@ main (void) { // Simple inversion test - util::matrix m { { + util::matrix4f m { { { 4, 1, 2, 3 }, { 2, 3, 4, 1 }, { 3, 4, 1, 2 }, { 1, 2, 3, 4 } } }; - util::matrix r { { + util::matrix4f r { { { 11, 1, 1, -9 }, { -9, 1, 11, 1 }, { 1, 11, -9, 1 },