/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __NMATRIX3__ #define __NMATRIX3__ #include "math/vector.h" namespace GS { struct Quaternion; class Matrix4; /*! @short 3x3 Matrix. This matrix class is column major. @author Emmanuel Julien (ejulien@gsworks.fr) */ class Matrix3 { static Matrix3 static_identity; public: NPLACEMENT_NEW(Matrix) /// The matrix values. float m[3][3]; bool operator == (const Matrix3 &b) const { for (uint i = 0; i < 3; i++) for (uint j = 0; j < 3; j++) if (!Math::TestEqual(m[i][j], b.m[i][j])) return false; return true; } bool operator != (const Matrix3 &b) const { for (uint i = 0; i < 3; i++) for (uint j = 0; j < 3; j++) if (!Math::TestEqual(m[i][j], b.m[i][j])) return true; return false; } Matrix3 operator + (const Matrix3 &b) const { Matrix3 r; for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) r.m[i][j] = m[i][j] + b.m[i][j]; return r; } void operator += (const Matrix3 &b) { *this = *this + b; } void operator *= (const float k) { for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) m[i][j] *= k; } void operator /= (const float k) { for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) m[i][j] /= k; } Matrix3 operator - (const Matrix3 &b) const { Matrix3 r; for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) r.m[i][j] = m[i][j] - b.m[i][j]; return r; } void operator -= (const Matrix3 &b) { *this = *this - b; } Vector4 operator * (const Vector4 &v) const { Vector4 o; o.x = v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2]; o.y = v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2]; o.z = v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2]; o.w = 1; return o; } Matrix3 operator * (const Matrix3 &b) const { #define __M33M33(__I, __J) m[__I][0] * b.m[0][__J] + m[__I][1] * b.m[1][__J] + m[__I][2] * b.m[2][__J] return Matrix3 ( __M33M33(0, 0), __M33M33(1, 0), __M33M33(2, 0), __M33M33(0, 1), __M33M33(1, 1), __M33M33(2, 1), __M33M33(0, 2), __M33M33(1, 2), __M33M33(2, 2) ); } Matrix3 operator * (const float v) const { Matrix3 r; for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) r.m[i][j] = m[i][j] * v; return r; } void operator *= (const Matrix3 &b) { *this = (*this) * b; } Matrix3 operator / (const float v) const { Matrix3 r; for (uint j = 0; j < 3; j++) for (uint i = 0; i < 3; i++) r.m[i][j] = m[i][j] / v; return r; } /// Apply to a set of vector objects. void Apply(Vector4 *o, const Vector4 *v, uint n = 1) const; /// Compute the determinant of the matrix. float Det() const { return ((m[1][1] * m[2][2]) - (m[1][2] * m[2][1])) * m[0][0] + ((m[1][2] * m[2][0]) - (m[1][0] * m[2][2])) * m[0][1] + ((m[1][0] * m[2][1]) - (m[1][1] * m[2][0])) * m[0][2]; } /// Compute inverse matrix. bool Inverse(Matrix3 &i) const; /// Return the transposed matrix. inline Matrix3 Transposed() const { return Matrix3 ( m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2] ); } /// Return the nth row. inline Vector4 GetRow(uint n) const { return Vector4(m[0][n], m[1][n], m[2][n]); } /// Return the nth column. inline Vector4 GetColumn(uint n) const { return Vector4(m[n][0], m[n][1], m[n][2]); } /// Set the nth row. void SetRow(uint n, const Vector4 &row); /// Set the nth column. void SetColumn(uint n, const Vector4 &col); /// Set matrix values. void Set ( float m00, float m10, float m20, float m01, float m11, float m21, float m02, float m12, float m22 ); /// Set matrix values. void Set(const Vector4 &u, const Vector4 &v, const Vector4 &w); /// Return this matrix after normalization. Matrix3 Normalized() const; /// Normalize as orthonormal base. Matrix3 AsOrthonormalBase() const; /// Return an Euler orientation equivalent to this matrix. Vector4 AsEuler(Math::rOrder rorder = Math::rOrder_Default) const; /// Vector matrix. static Matrix3 VectorMatrix(const Vector4 &v); /// Identity matrix. static Matrix3 &IdentityMatrix() { return static_identity; } /// Translation matrix. static Matrix3 TranslationMatrix(const Vector2 &t); static Matrix3 TranslationMatrix(const Vector4 &t); /// Scale matrix. static Matrix3 ScaleMatrix(const Vector2 &s); static Matrix3 ScaleMatrix(const Vector4 &s); /// Cross product matrix. static Matrix3 CrossProductMatrix(const Vector4 &v); /// Rotation matrix around X axis. static Matrix3 RotationMatrixXAxis(float a); /// Rotation matrix around Y axis. static Matrix3 RotationMatrixYAxis(float a); /// Rotation matrix around Z axis. static Matrix3 RotationMatrixZAxis(float a); /*! @short From Orthonormal basis. Transform an orthogonal basis formed by one or two vectors to a rotation matrix. @note Left-handed base, eg: u = {1,0,0}, v = {0,1,0}, w = {0,0,1}. */ static Matrix3 FromOrthonormalBasis(const Vector4 &w, const Vector4 *v = 0); /// From Euler triplet. static Matrix3 FromEuler(float x = 0, float y = 0, float z = 0, Math::rOrder rorder = Math::rOrder_Default); /// From Euler vector. static Matrix3 FromEuler(const Vector4 &euler, Math::rOrder rorder = Math::rOrder_Default); /// From matrix4. static Matrix3 FromMatrix4(const Matrix4 &mtx); NML::Tag *AsMetaTag(const char *) const; bool FromMetaTag(NML::Tag &); Matrix3( float m00 = 1, float m10 = 0, float m20 = 0, float m01 = 0, float m11 = 1, float m21 = 0, float m02 = 0, float m12 = 0, float m22 = 1 ) { Set(m00, m10, m20, m01, m11, m21, m02, m12, m22); } Matrix3(const Vector4 &u, const Vector4 &v, const Vector4 &w) { Set(u, v, w); } }; } // GS #endif // __NMATRIX3__