#ifndef BLUECORE_MATRIX_H #define BLUECORE_MATRIX_H // system includes #include #include // local includes #include "Scalar.h" #include "Vector.h" #include "Quaternion.h" namespace BlueCore { template class Matrix3x3Template { public: T m[9]; /** * default constructor */ inline Matrix3x3Template() { identity(); } /** * constructor from array */ template inline Matrix3x3Template( const S a[9] ) { m[0] = static_cast(a[0]); m[1] = static_cast(a[1]); m[2] = static_cast(a[2]); m[3] = static_cast(a[3]); m[4] = static_cast(a[4]); m[5] = static_cast(a[5]); m[6] = static_cast(a[6]); m[7] = static_cast(a[7]); m[8] = static_cast(a[8]); } /** * copy constructor */ template inline Matrix3x3Template( const Matrix3x3Template &a ) { m[0] = static_cast(a.m[0]); m[1] = static_cast(a.m[1]); m[2] = static_cast(a.m[2]); m[3] = static_cast(a.m[3]); m[4] = static_cast(a.m[4]); m[5] = static_cast(a.m[5]); m[6] = static_cast(a.m[6]); m[7] = static_cast(a.m[7]); m[8] = static_cast(a.m[8]); } /** * constructor from heading and up vectors */ inline Matrix3x3Template( const Vector3Template &h, const Vector3Template &u ) { Vector3Template a, b, c; c = h.unit(); a = h.crossProduct( u ).unit(); b = c.crossProduct( a ).unit(); m[0] = a.x; m[1] = b.x; m[2] = c.x; m[3] = a.y; m[4] = b.y; m[5] = c.y; m[6] = a.z; m[7] = b.z; m[8] = c.z; } /** * contructor from euler angles */ inline Matrix3x3Template( T a, T e, T t ) { T ch = cos( a ); T sh = sin( a ); T ca = cos( e ); T sa = sin( e ); T cb = cos( t ); T sb = sin( t ); m[0] = ch * ca; m[1] = sh*sb - ch*sa*cb; m[2] = ch*sa*sb + sh*cb; m[3] = sa; m[4] = ca*cb; m[5] = -ca*sb; m[6] = -sh*ca; m[7] = sh*sa*cb + ch*sb; m[8] = -sh*sa*sb + ch*cb; } /** * contructor from quaternion */ template inline Matrix3x3Template( const QuaternionTemplate &q ) { T xx = static_cast(q.x*q.x), xy = static_cast(q.x*q.y), xz = static_cast(q.x*q.z), xw = static_cast(q.x*q.w), yy = static_cast(q.y*q.y), yz = static_cast(q.y*q.z), yw = static_cast(q.y*q.w), zz = static_cast(q.z*q.z), zw = static_cast(q.z*q.w); m[0] = 1 - yy - yy - zz - zz; m[1] = xy + xy + zw + zw; m[2] = xz + xz - yw - yw; m[3] = xy + xy - zw - zw; m[4] = 1 - xx - xx - zz - zz; m[5] = yz + yz + xw + xw; m[6] = xz + xz + yw + yw; m[7] = yz + yz - xw - xw; m[8] = 1 - xx - xx - yy - yy; } /** * set matrix to identity matrix */ inline void identity() { m[0] = static_cast(1); m[1] = static_cast(0); m[2] = static_cast(0); m[3] = static_cast(0); m[4] = static_cast(1); m[5] = static_cast(0); m[6] = static_cast(0); m[7] = static_cast(0); m[8] = static_cast(1); } /** * get transposed matrix */ inline Matrix3x3Template transposed() const { Matrix3x3Template a; a.m[0] = m[0]; a.m[3] = m[1]; a.m[6] = m[2]; a.m[1] = m[3]; a.m[4] = m[4]; a.m[7] = m[5]; a.m[2] = m[6]; a.m[5] = m[7]; a.m[8] = m[8]; return a; } /** * transpose */ inline void transpose() { swap( m[3], m[1] ); swap( m[6], m[2] ); swap( m[7], m[5] ); } /** * determinate */ inline T determinant() const { return ( m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7] ) - ( m[6]*m[4]*m[2] + m[7]*m[5]*m[0] + m[8]*m[3]*m[1] ); } inline Matrix3x3Template inverted() { T det = determinant(); T one_over_det = 1.0f / det; Matrix3x3Template result; result.m[0] = +(m[4] * m[8] - m[5] * m[7]) * one_over_det; result.m[1] = -(m[1] * m[8] - m[2] * m[7]) * one_over_det; result.m[2] = +(m[1] * m[5] - m[2] * m[4]) * one_over_det; result.m[3] = -(m[3] * m[8] - m[5] * m[6]) * one_over_det; result.m[4] = +(m[0] * m[8] - m[2] * m[6]) * one_over_det; result.m[5] = -(m[0] * m[5] - m[2] * m[3]) * one_over_det; result.m[6] = +(m[3] * m[7] - m[4] * m[6]) * one_over_det; result.m[7] = -(m[0] * m[7] - m[1] * m[6]) * one_over_det; result.m[8] = +(m[0] * m[4] - m[1] * m[3]) * one_over_det; return result; } /** * add/assign operator */ template inline Matrix3x3Template &operator += ( const Matrix3x3Template &a ) { m[0] += static_cast(a.m[0]); m[1] += static_cast(a.m[1]); m[2] += static_cast(a.m[2]); m[3] += static_cast(a.m[3]); m[4] += static_cast(a.m[4]); m[5] += static_cast(a.m[5]); m[6] += static_cast(a.m[6]); m[7] += static_cast(a.m[7]); m[8] += static_cast(a.m[8]); return *this; } /** * matrix multiplication */ template inline Matrix3x3Template operator * ( const Matrix3x3Template &a ) { Matrix3x3Template result; result.m[0] = m[0] * static_cast(a.m[0]) + m[3] * static_cast(a.m[1]) + m[6] * static_cast(a.m[2]); result.m[1] = m[1] * static_cast(a.m[0]) + m[4] * static_cast(a.m[1]) + m[7] * static_cast(a.m[2]); result.m[2] = m[2] * static_cast(a.m[0]) + m[5] * static_cast(a.m[1]) + m[8] * static_cast(a.m[2]); result.m[3] = m[0] * static_cast(a.m[3]) + m[3] * static_cast(a.m[4]) + m[6] * static_cast(a.m[5]); result.m[4] = m[1] * static_cast(a.m[3]) + m[4] * static_cast(a.m[4]) + m[7] * static_cast(a.m[5]); result.m[5] = m[2] * static_cast(a.m[3]) + m[5] * static_cast(a.m[4]) + m[8] * static_cast(a.m[5]); result.m[6] = m[0] * static_cast(a.m[6]) + m[3] * static_cast(a.m[7]) + m[6] * static_cast(a.m[8]); result.m[7] = m[1] * static_cast(a.m[6]) + m[4] * static_cast(a.m[7]) + m[7] * static_cast(a.m[8]); result.m[8] = m[2] * static_cast(a.m[6]) + m[5] * static_cast(a.m[7]) + m[8] * static_cast(a.m[8]); return result; } /** * matrix vector multiplication */ template Vector3Template operator * ( const Vector3Template& a ) { return Vector3Template( m[0] * static_cast(a.x) + m[3] * static_cast(a.y) + m[6] * static_cast(a.z), m[1] * static_cast(a.x) + m[4] * static_cast(a.y) + m[7] * static_cast(a.z), m[2] * static_cast(a.x) + m[5] * static_cast(a.y) + m[8] * static_cast(a.z) ); } /** * matrix scalar multiplication */ template Matrix3x3Template operator * ( const S a ) { Matrix3x3Template result; result.m[0] = m[0] * static_cast(a); result.m[1] = m[1] * static_cast(a); result.m[2] = m[2] * static_cast(a); result.m[3] = m[3] * static_cast(a); result.m[4] = m[4] * static_cast(a); result.m[5] = m[5] * static_cast(a); result.m[6] = m[6] * static_cast(a); result.m[7] = m[7] * static_cast(a); result.m[8] = m[8] * static_cast(a); return result; } friend std::ostream &operator << ( std::ostream& os, Matrix3x3Template m ) { os << "( " << m.m[0] << ", " << m.m[1] << ", " << m.m[2] << " )" << std::endl; os << "( " << m.m[3] << ", " << m.m[4] << ", " << m.m[5] << " )" << std::endl; os << "( " << m.m[6] << ", " << m.m[7] << ", " << m.m[8] << " )" << std::endl; return os; } }; typedef Matrix3x3Template Matrix3x3Float; typedef Matrix3x3Template Matrix3x3Double; typedef Matrix3x3Template Matrix3x3; template class Matrix4x4Template { public: T m[16]; /** * default constructor */ inline Matrix4x4Template() { identity(); } inline void identity() { m[0] = static_cast(1); m[1] = static_cast(0); m[2] = static_cast(0); m[3] = static_cast(0); m[4] = static_cast(0); m[5] = static_cast(1); m[6] = static_cast(0); m[7] = static_cast(0); m[8] = static_cast(0); m[9] = static_cast(0); m[10] = static_cast(1); m[11] = static_cast(0); m[12] = static_cast(0); m[13] = static_cast(0); m[14] = static_cast(0); m[15] = static_cast(1); } /** * constructor from array */ inline Matrix4x4Template( const T a[16] ) { m[0] = a[0]; m[1] = a[1]; m[2] = a[2]; m[3] = a[3]; m[4] = a[4]; m[5] = a[5]; m[6] = a[6]; m[7] = a[7]; m[8] = a[8]; m[9] = a[9]; m[10] = a[10]; m[11] = a[11]; m[12] = a[12]; m[13] = a[13]; m[14] = a[14]; m[15] = a[15]; } /** * constructor from 3x3 matrix, add. element are set to zero */ inline Matrix4x4Template( const Matrix3x3Template &a ) { m[0] = a[0]; m[1] = a[1]; m[2] = a[2]; m[3] = static_cast(0); m[4] = a[3]; m[5] = a[4]; m[6] = a[5]; m[7] = static_cast(0); m[8] = a[6]; m[9] = a[7]; m[10] = a[8]; m[11] = static_cast(0); m[12] = static_cast(0); m[13] = static_cast(0); m[14] = static_cast(0); m[15] = static_cast(1); } /** * constructor from 3x3 rotation matrix and translation vector */ inline Matrix4x4Template( const Matrix3x3Template &a, const Vector3Template &b ) { m[0] = a[0]; m[1] = a[1]; m[2] = a[2]; m[3] = static_cast(0); m[4] = a[3]; m[5] = a[4]; m[6] = a[5]; m[7] = static_cast(0); m[8] = a[6]; m[9] = a[7]; m[10] = a[8]; m[11] = static_cast(0); m[12] = b.x; m[13] = b.y; m[14] = b.z; m[15] = static_cast(1); } /** * copy constructor */ inline Matrix4x4Template( const Matrix4x4Template &a ) { m[0] = a.m[0]; m[1] = a.m[1]; m[2] = a.m[2]; m[3] = a.m[3]; m[4] = a.m[4]; m[5] = a.m[5]; m[6] = a.m[6]; m[7] = a.m[7]; m[8] = a.m[8]; m[9] = a.m[9]; m[10] = a.m[10]; m[11] = a.m[11]; m[12] = a.m[12]; m[13] = a.m[13]; m[14] = a.m[14]; m[15] = a.m[15]; } /** * constructor from quaternion */ inline Matrix4x4Template( const QuaternionTemplate &q ) { m[0] = 1 - 2*q.y*q.y - 2*q.z*q.z; m[1] = 2*q.x*q.y - 2*q.z*q.w; m[2] = 2*q.x*q.z + 2*q.y*q.w; m[3] = static_cast(0); m[4] = 2*q.x*q.y + 2*q.z*q.w; m[5] = 1 - 2*q.x*q.x - 2*q.z*q.z; m[6] = 2*q.y*q.z - 2*q.x*q.w; m[7] = static_cast(0); m[8] = 2*q.x*q.z - 2*q.y*q.w; m[9] = 2*q.y*q.z + 2*q.x*q.w; m[10] = 1 - 2*q.x*q.x - 2*q.y*q.y; m[11] = static_cast(0); m[12] = static_cast(0); m[13] = static_cast(0); m[14] = static_cast(0); m[15] = static_cast(1); } /** * constructor from quaternion and translation vector */ inline Matrix4x4Template( const QuaternionTemplate &q, const Vector3Template &a ) { m[0] = 1 - 2*q.y*q.y - 2*q.z*q.z; m[1] = 2*q.x*q.y - 2*q.z*q.w; m[2] = 2*q.x*q.z + 2*q.y*q.w; m[3] = static_cast(0); m[4] = 2*q.x*q.y + 2*q.z*q.w; m[5] = 1 - 2*q.x*q.x - 2*q.z*q.z; m[6] = 2*q.y*q.z - 2*q.x*q.w; m[7] = static_cast(0); m[8] = 2*q.x*q.z - 2*q.y*q.w; m[9] = 2*q.y*q.z + 2*q.x*q.w; m[10] = 1 - 2*q.x*q.x - 2*q.y*q.y; m[11] = static_cast(0); m[12] = a.x; m[13] = a.y; m[14] = a.z; m[15] = static_cast(1); } /** * constructor from heading, up and translation vectors */ inline Matrix4x4Template( const Vector3Template &h, const Vector3Template &u, const Vector3Template &t ) { Vector3Template a, b, c; c = h.unit(); a = h.crossProduct( u ).unit(); b = c.crossProduct( a ).unit(); m[0] = a.x; m[1] = b.x; m[2] = c.x; m[3] = static_cast(0); m[4] = a.y; m[5] = b.y; m[6] = c.y; m[7] = static_cast(0); m[8] = a.z; m[9] = b.z; m[10] = c.z; m[11] = static_cast(0); m[12] = t.x; m[13] = t.y; m[14] = t.z; m[15] = static_cast(1); } /** * contructor from euler angles */ inline Matrix4x4Template( T a, T e, T t, const Vector3Template &tr ) { T ch = cos( a ); T sh = sin( a ); T ca = cos( e ); T sa = sin( e ); T cb = cos( t ); T sb = sin( t ); m[0] = ch * ca; m[1] = sh*sb - ch*sa*cb; m[2] = ch*sa*sb + sh*cb; m[3] = static_cast(0); m[4] = sa; m[5] = ca*cb; m[6] = -ca*sb; m[7] = static_cast(0); m[8] = -sh*ca; m[9] = sh*sa*cb + ch*sb; m[10] = -sh*sa*sb + ch*cb; m[11] = static_cast(0); m[12] = tr.x; m[13] = tr.y; m[14] = tr.z; m[15] = static_cast(1); } /** * transpose this matrix */ inline void transpose() { std::swap( m[4], m[1] ); std::swap( m[8], m[2] ); std::swap( m[12], m[3] ); std::swap( m[9], m[6] ); std::swap( m[13], m[7] ); std::swap( m[14], m[11] ); } /** * get transposed matrix */ inline Matrix4x4Template transposed() { Matrix4x4Template a; a.m[0] = m[0]; a.m[4] = m[1]; a.m[8] = m[2]; a.m[12] = m[3]; a.m[1] = m[4]; a.m[5] = m[5]; a.m[9] = m[6]; a.m[13] = m[7]; a.m[2] = m[8]; a.m[6] = m[9]; a.m[10] = m[10]; a.m[14] = m[11]; a.m[3] = m[12]; a.m[7] = m[13]; a.m[11] = m[14]; a.m[15] = m[15]; return a; } /** * matrix multiplication */ template inline Matrix4x4Template operator * ( const Matrix4x4Template &a ) { Matrix4x4Template result; result.m[0] = m[0] * static_cast(a.m[0]) + m[4] * static_cast(a.m[1]) + m[8] * static_cast(a.m[2]) + m[12] * static_cast(a.m[3]); result.m[1] = m[1] * static_cast(a.m[0]) + m[5] * static_cast(a.m[1]) + m[9] * static_cast(a.m[2]) + m[13] * static_cast(a.m[3]); result.m[2] = m[2] * static_cast(a.m[0]) + m[6] * static_cast(a.m[1]) + m[10] * static_cast(a.m[2]) + m[14] * static_cast(a.m[3]); result.m[3] = m[3] * static_cast(a.m[0]) + m[7] * static_cast(a.m[1]) + m[11] * static_cast(a.m[2]) + m[15] * static_cast(a.m[3]); result.m[4] = m[0] * static_cast(a.m[4]) + m[4] * static_cast(a.m[5]) + m[8] * static_cast(a.m[6]) + m[12] * static_cast(a.m[7]); result.m[5] = m[1] * static_cast(a.m[4]) + m[5] * static_cast(a.m[5]) + m[9] * static_cast(a.m[6]) + m[13] * static_cast(a.m[7]); result.m[6] = m[2] * static_cast(a.m[4]) + m[6] * static_cast(a.m[5]) + m[10] * static_cast(a.m[6]) + m[14] * static_cast(a.m[7]); result.m[7] = m[3] * static_cast(a.m[4]) + m[7] * static_cast(a.m[5]) + m[11] * static_cast(a.m[6]) + m[15] * static_cast(a.m[7]); result.m[8] = m[0] * static_cast(a.m[8]) + m[4] * static_cast(a.m[9]) + m[8] * static_cast(a.m[10]) + m[12] * static_cast(a.m[11]); result.m[9] = m[1] * static_cast(a.m[8]) + m[5] * static_cast(a.m[9]) + m[9] * static_cast(a.m[10]) + m[13] * static_cast(a.m[11]); result.m[10] = m[2] * static_cast(a.m[8]) + m[6] * static_cast(a.m[9]) + m[10] * static_cast(a.m[10]) + m[14] * static_cast(a.m[11]); result.m[11] = m[3] * static_cast(a.m[8]) + m[7] * static_cast(a.m[9]) + m[11] * static_cast(a.m[10]) + m[15] * static_cast(a.m[11]); result.m[12] = m[0] * static_cast(a.m[12]) + m[4] * static_cast(a.m[13]) + m[8] * static_cast(a.m[14]) + m[12] * static_cast(a.m[15]); result.m[13] = m[1] * static_cast(a.m[12]) + m[5] * static_cast(a.m[13]) + m[9] * static_cast(a.m[14]) + m[13] * static_cast(a.m[15]); result.m[14] = m[2] * static_cast(a.m[12]) + m[6] * static_cast(a.m[13]) + m[10] * static_cast(a.m[14]) + m[14] * static_cast(a.m[15]); result.m[15] = m[3] * static_cast(a.m[12]) + m[7] * static_cast(a.m[13]) + m[11] * static_cast(a.m[14]) + m[15] * static_cast(a.m[15]); return result; } /** * matrix multiplication */ /* template inline Matrix4x4Template operator *= ( const Matrix4x4Template &a ) { Matrix4x4Template result; result.m[0] = m[0] * static_cast(a.m[0]) + m[4] * static_cast(a.m[1]) + m[8] * static_cast(a.m[2]); + m[12] * static_cast(a.m[3]); result.m[1] = m[1] * static_cast(a.m[0]) + m[5] * static_cast(a.m[1]) + m[9] * static_cast(a.m[2]); + m[13] * static_cast(a.m[3]); result.m[2] = m[2] * static_cast(a.m[0]) + m[6] * static_cast(a.m[1]) + m[10] * static_cast(a.m[2]); + m[14] * static_cast(a.m[3]); result.m[3] = m[3] * static_cast(a.m[0]) + m[7] * static_cast(a.m[1]) + m[11] * static_cast(a.m[2]); + m[15] * static_cast(a.m[3]); result.m[4] = m[0] * static_cast(a.m[4]) + m[4] * static_cast(a.m[5]) + m[8] * static_cast(a.m[6]); + m[12] * static_cast(a.m[7]); result.m[5] = m[1] * static_cast(a.m[4]) + m[5] * static_cast(a.m[5]) + m[9] * static_cast(a.m[6]); + m[13] * static_cast(a.m[7]); result.m[6] = m[2] * static_cast(a.m[4]) + m[6] * static_cast(a.m[5]) + m[10] * static_cast(a.m[6]); + m[14] * static_cast(a.m[7]); result.m[7] = m[3] * static_cast(a.m[4]) + m[7] * static_cast(a.m[5]) + m[11] * static_cast(a.m[6]); + m[15] * static_cast(a.m[7]); result.m[8] = m[0] * static_cast(a.m[8]) + m[4] * static_cast(a.m[9]) + m[8] * static_cast(a.m[10]); + m[12] * static_cast(a.m[11]); result.m[9] = m[1] * static_cast(a.m[8]) + m[5] * static_cast(a.m[9]) + m[9] * static_cast(a.m[10]); + m[13] * static_cast(a.m[11]); result.m[10] = m[2] * static_cast(a.m[8]) + m[6] * static_cast(a.m[9]) + m[10] * static_cast(a.m[10]); + m[14] * static_cast(a.m[11]); result.m[11] = m[3] * static_cast(a.m[8]) + m[7] * static_cast(a.m[9]) + m[11] * static_cast(a.m[10]); + m[15] * static_cast(a.m[11]); result.m[12] = m[0] * static_cast(a.m[12]) + m[4] * static_cast(a.m[13]) + m[8] * static_cast(a.m[14]); + m[12] * static_cast(a.m[15]); result.m[13] = m[1] * static_cast(a.m[12]) + m[5] * static_cast(a.m[13]) + m[9] * static_cast(a.m[14]); + m[13] * static_cast(a.m[15]); result.m[14] = m[2] * static_cast(a.m[12]) + m[6] * static_cast(a.m[13]) + m[10] * static_cast(a.m[14]); + m[14] * static_cast(a.m[15]); result.m[15] = m[3] * static_cast(a.m[12]) + m[7] * static_cast(a.m[13]) + m[11] * static_cast(a.m[14]); + m[15] * static_cast(a.m[15]); m = result.m; return *this; } */ /** * matrix vector multiplication */ Vector3Template operator * ( const Vector3Template &a ) { Vector3Template result; result.x = m[0] * a.x + m[4] * a.y + m[8] * a.z + m[12]; result.y = m[1] * a.x + m[5] * a.y + m[9] * a.z + m[13]; result.z = m[2] * a.x + m[6] * a.y + m[11] * a.z + m[14]; return result; } T *data() { return &m[0]; } }; typedef Matrix4x4Template Matrix4x4Float; typedef Matrix4x4Template Matrix4x4Double; typedef Matrix4x4Template Matrix4x4; } // namespace bc #endif // BLUECORE_MATRIX_H