From 4019c448991b27e6d1ec65629cba211eb0fa1da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 23 Dec 2010 23:19:52 +0100 Subject: [PATCH] Matrix4 class with matrix transform functions. --- src/Matrix4.h | 135 +++++++++++++++++++++++++++++++++++++++ src/Test/CMakeLists.txt | 1 + src/Test/Matrix4Test.cpp | 62 ++++++++++++++++++ src/Test/Matrix4Test.h | 33 ++++++++++ 4 files changed, 231 insertions(+) create mode 100644 src/Matrix4.h create mode 100644 src/Test/Matrix4Test.cpp create mode 100644 src/Test/Matrix4Test.h diff --git a/src/Matrix4.h b/src/Matrix4.h new file mode 100644 index 000000000..3c5192b58 --- /dev/null +++ b/src/Matrix4.h @@ -0,0 +1,135 @@ +#ifndef Magnum_Matrix4_h +#define Magnum_Matrix4_h +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Matrix4 + */ + +#include "Matrix.h" + +#include "Vector3.h" + +namespace Magnum { + +/** @brief Matrix 4x4 */ +template class Matrix4: public Matrix { + public: + /** + * @brief Translation matrix + * @param x Translation along X + * @param y Translation along Y + * @param z Translation along Z + */ + inline static Matrix4 translation(T x, T y, T z) { + return translation(Vector3(x, y, z)); + } + + /** + * @brief Translation matrix + * @param vec Translation vector + */ + static Matrix4 translation(const Vector3& vec) { + Matrix4 out; /* (Identity matrix) */ + out.set(3, 0, vec.x()); + out.set(3, 1, vec.y()); + out.set(3, 2, vec.z()); + return out; + } + + /** + * @brief Scaling matrix + * @param x Scaling along X + * @param y Scaling along Y + * @param z Scaling along Z + */ + inline static Matrix4 scaling(T x, T y, T z) { + return scaling(Vector3(x, y, z)); + } + + /** + * @brief Scaling matrix + * @param vec Scaling vector + */ + static Matrix4 scaling(const Vector3& vec) { + Matrix4 out; /* (Identity matrix) */ + out.set(0, 0, vec.x()); + out.set(1, 1, vec.y()); + out.set(2, 2, vec.z()); + return out; + } + + /** + * @brief Rotation matrix + * @param angle Rotation angle (counterclockwise, in radians) + * @param x Rotation axis X coordinates + * @param y Rotation axis Y coordinates + * @param z Rotation axis Z coordinates + */ + inline static Matrix4 rotation(T angle, T x, T y, T z) { + return rotation(angle, Vector3(x, y, z)); + } + + /** + * @brief Rotation matrix + * @param angle Rotation angle (counterclockwise, in radians) + * @param vec Rotation vector + */ + static Matrix4 rotation(T angle, const Vector3& vec) { + Vector3 vn = vec.normalized(); + + T sine = sin(angle); + T cosine = cos(angle); + T oneMinusCosine = 1 - cosine; + + T xx = vn.x()*vn.x(); + T xy = vn.x()*vn.y(); + T xz = vn.x()*vn.z(); + T yy = vn.y()*vn.y(); + T yz = vn.y()*vn.z(); + T zz = vn.z()*vn.z(); + + /* Don't creating identity matrix, as nearly all ones would be + overwritten */ + Matrix4 out(false); + out.set(3, 3, T(1)); + + out.set(0, 0, cosine + xx*oneMinusCosine); + out.set(1, 0, xy*oneMinusCosine - vn.z()*sine); + out.set(2, 0, xz*oneMinusCosine + vn.y()*sine); + out.set(0, 1, xy*oneMinusCosine + vn.z()*sine); + out.set(1, 1, cosine + yy*oneMinusCosine); + out.set(2, 1, yz*oneMinusCosine - vn.x()*sine); + out.set(0, 2, xz*oneMinusCosine - vn.y()*sine); + out.set(1, 2, yz*oneMinusCosine + vn.x()*sine); + out.set(2, 2, cosine + zz*oneMinusCosine); + + return out; + } + + /** @copydoc Matrix::Matrix(bool) */ + inline Matrix4(bool identity = true): Matrix(identity) {} + + /** @copydoc Matrix::Matrix(const T*) */ + inline Matrix4(const T* data): Matrix(data) {} + + /** @copydoc Matrix::Matrix(const Matrix&) */ + inline Matrix4(const Matrix& other): Matrix(other) {} +}; + +} + +#endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index f79fba1f6..b7cab2843 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -3,3 +3,4 @@ magnum_add_test(Vector3Test Vector3Test.h Vector3Test.cpp) magnum_add_test(Vector4Test Vector4Test.h Vector4Test.cpp) magnum_add_test(MatrixTest MatrixTest.h MatrixTest.cpp) +magnum_add_test(Matrix4Test Matrix4Test.h Matrix4Test.cpp) diff --git a/src/Test/Matrix4Test.cpp b/src/Test/Matrix4Test.cpp new file mode 100644 index 000000000..05f03a9d8 --- /dev/null +++ b/src/Test/Matrix4Test.cpp @@ -0,0 +1,62 @@ +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Matrix4Test.h" + +#include + +#include "Matrix4.h" +#include "constants.h" + +QTEST_APPLESS_MAIN(Magnum::Test::Matrix4Test) + +namespace Magnum { namespace Test { + +typedef Magnum::Matrix4 Matrix4; + +void Matrix4Test::translation() { + float matrix[] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 3.0f, 1.0f, 2.0f, 1.0f + }; + + QVERIFY(Matrix4::translation(3.0f, 1.0f, 2.0f) == Matrix4(matrix)); +} + +void Matrix4Test::scaling() { + float matrix[] = { + 3.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 2.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + QVERIFY(Matrix4::scaling(3.0f, 1.5f, 2.0f) == Matrix4(matrix)); +} + +void Matrix4Test::rotation() { + float matrix[] = { + 0.35612214f, -0.80181062f, 0.47987163f, 0.0f, + 0.47987163f, 0.59757638f, 0.6423595f, 0.0f, + -0.80181062f, 0.0015183985f, 0.59757638f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + QVERIFY(Matrix4::rotation(-74*PI/180.0f, -1.0f, 2.0f, 2.0f) == Matrix4(matrix)); +} + +}} diff --git a/src/Test/Matrix4Test.h b/src/Test/Matrix4Test.h new file mode 100644 index 000000000..f55a22ed1 --- /dev/null +++ b/src/Test/Matrix4Test.h @@ -0,0 +1,33 @@ +#ifndef Magnum_Test_Matrix4Test_h +#define Magnum_Test_Matrix4Test_h +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Test { + +class Matrix4Test: public QObject { + Q_OBJECT + + private slots: + void translation(); + void scaling(); + void rotation(); +}; + +}} + +#endif