00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright (c) 2000-2011 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __Matrix3_H__ 00029 #define __Matrix3_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 00033 #include "OgreVector3.h" 00034 00035 // NB All code adapted from Wild Magic 0.2 Matrix math (free source code) 00036 // http://www.geometrictools.com/ 00037 00038 // NOTE. The (x,y,z) coordinate system is assumed to be right-handed. 00039 // Coordinate axis rotation matrices are of the form 00040 // RX = 1 0 0 00041 // 0 cos(t) -sin(t) 00042 // 0 sin(t) cos(t) 00043 // where t > 0 indicates a counterclockwise rotation in the yz-plane 00044 // RY = cos(t) 0 sin(t) 00045 // 0 1 0 00046 // -sin(t) 0 cos(t) 00047 // where t > 0 indicates a counterclockwise rotation in the zx-plane 00048 // RZ = cos(t) -sin(t) 0 00049 // sin(t) cos(t) 0 00050 // 0 0 1 00051 // where t > 0 indicates a counterclockwise rotation in the xy-plane. 00052 00053 namespace Ogre 00054 { 00068 class _OgreExport Matrix3 00069 { 00070 public: 00075 inline Matrix3 () {} 00076 inline explicit Matrix3 (const Real arr[3][3]) 00077 { 00078 memcpy(m,arr,9*sizeof(Real)); 00079 } 00080 inline Matrix3 (const Matrix3& rkMatrix) 00081 { 00082 memcpy(m,rkMatrix.m,9*sizeof(Real)); 00083 } 00084 Matrix3 (Real fEntry00, Real fEntry01, Real fEntry02, 00085 Real fEntry10, Real fEntry11, Real fEntry12, 00086 Real fEntry20, Real fEntry21, Real fEntry22) 00087 { 00088 m[0][0] = fEntry00; 00089 m[0][1] = fEntry01; 00090 m[0][2] = fEntry02; 00091 m[1][0] = fEntry10; 00092 m[1][1] = fEntry11; 00093 m[1][2] = fEntry12; 00094 m[2][0] = fEntry20; 00095 m[2][1] = fEntry21; 00096 m[2][2] = fEntry22; 00097 } 00098 00101 inline void swap(Matrix3& other) 00102 { 00103 std::swap(m[0][0], other.m[0][0]); 00104 std::swap(m[0][1], other.m[0][1]); 00105 std::swap(m[0][2], other.m[0][2]); 00106 std::swap(m[1][0], other.m[1][0]); 00107 std::swap(m[1][1], other.m[1][1]); 00108 std::swap(m[1][2], other.m[1][2]); 00109 std::swap(m[2][0], other.m[2][0]); 00110 std::swap(m[2][1], other.m[2][1]); 00111 std::swap(m[2][2], other.m[2][2]); 00112 } 00113 00114 // member access, allows use of construct mat[r][c] 00115 inline Real* operator[] (size_t iRow) const 00116 { 00117 return (Real*)m[iRow]; 00118 } 00119 /*inline operator Real* () 00120 { 00121 return (Real*)m[0]; 00122 }*/ 00123 Vector3 GetColumn (size_t iCol) const; 00124 void SetColumn(size_t iCol, const Vector3& vec); 00125 void FromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis); 00126 00127 // assignment and comparison 00128 inline Matrix3& operator= (const Matrix3& rkMatrix) 00129 { 00130 memcpy(m,rkMatrix.m,9*sizeof(Real)); 00131 return *this; 00132 } 00133 bool operator== (const Matrix3& rkMatrix) const; 00134 inline bool operator!= (const Matrix3& rkMatrix) const 00135 { 00136 return !operator==(rkMatrix); 00137 } 00138 00139 // arithmetic operations 00140 Matrix3 operator+ (const Matrix3& rkMatrix) const; 00141 Matrix3 operator- (const Matrix3& rkMatrix) const; 00142 Matrix3 operator* (const Matrix3& rkMatrix) const; 00143 Matrix3 operator- () const; 00144 00145 // matrix * vector [3x3 * 3x1 = 3x1] 00146 Vector3 operator* (const Vector3& rkVector) const; 00147 00148 // vector * matrix [1x3 * 3x3 = 1x3] 00149 _OgreExport friend Vector3 operator* (const Vector3& rkVector, 00150 const Matrix3& rkMatrix); 00151 00152 // matrix * scalar 00153 Matrix3 operator* (Real fScalar) const; 00154 00155 // scalar * matrix 00156 _OgreExport friend Matrix3 operator* (Real fScalar, const Matrix3& rkMatrix); 00157 00158 // utilities 00159 Matrix3 Transpose () const; 00160 bool Inverse (Matrix3& rkInverse, Real fTolerance = 1e-06) const; 00161 Matrix3 Inverse (Real fTolerance = 1e-06) const; 00162 Real Determinant () const; 00163 00164 // singular value decomposition 00165 void SingularValueDecomposition (Matrix3& rkL, Vector3& rkS, 00166 Matrix3& rkR) const; 00167 void SingularValueComposition (const Matrix3& rkL, 00168 const Vector3& rkS, const Matrix3& rkR); 00169 00170 // Gram-Schmidt orthonormalization (applied to columns of rotation matrix) 00171 void Orthonormalize (); 00172 00173 // orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) 00174 void QDUDecomposition (Matrix3& rkQ, Vector3& rkD, 00175 Vector3& rkU) const; 00176 00177 Real SpectralNorm () const; 00178 00179 // matrix must be orthonormal 00180 void ToAxisAngle (Vector3& rkAxis, Radian& rfAngle) const; 00181 inline void ToAxisAngle (Vector3& rkAxis, Degree& rfAngle) const { 00182 Radian r; 00183 ToAxisAngle ( rkAxis, r ); 00184 rfAngle = r; 00185 } 00186 void FromAxisAngle (const Vector3& rkAxis, const Radian& fRadians); 00187 00188 // The matrix must be orthonormal. The decomposition is yaw*pitch*roll 00189 // where yaw is rotation about the Up vector, pitch is rotation about the 00190 // Right axis, and roll is rotation about the Direction axis. 00191 bool ToEulerAnglesXYZ (Radian& rfYAngle, Radian& rfPAngle, 00192 Radian& rfRAngle) const; 00193 bool ToEulerAnglesXZY (Radian& rfYAngle, Radian& rfPAngle, 00194 Radian& rfRAngle) const; 00195 bool ToEulerAnglesYXZ (Radian& rfYAngle, Radian& rfPAngle, 00196 Radian& rfRAngle) const; 00197 bool ToEulerAnglesYZX (Radian& rfYAngle, Radian& rfPAngle, 00198 Radian& rfRAngle) const; 00199 bool ToEulerAnglesZXY (Radian& rfYAngle, Radian& rfPAngle, 00200 Radian& rfRAngle) const; 00201 bool ToEulerAnglesZYX (Radian& rfYAngle, Radian& rfPAngle, 00202 Radian& rfRAngle) const; 00203 void FromEulerAnglesXYZ (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00204 void FromEulerAnglesXZY (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00205 void FromEulerAnglesYXZ (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00206 void FromEulerAnglesYZX (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00207 void FromEulerAnglesZXY (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00208 void FromEulerAnglesZYX (const Radian& fYAngle, const Radian& fPAngle, const Radian& fRAngle); 00209 // eigensolver, matrix must be symmetric 00210 void EigenSolveSymmetric (Real afEigenvalue[3], 00211 Vector3 akEigenvector[3]) const; 00212 00213 static void TensorProduct (const Vector3& rkU, const Vector3& rkV, 00214 Matrix3& rkProduct); 00215 00217 inline bool hasScale() const 00218 { 00219 // check magnitude of column vectors (==local axes) 00220 Real t = m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0]; 00221 if (!Math::RealEqual(t, 1.0, (Real)1e-04)) 00222 return true; 00223 t = m[0][1] * m[0][1] + m[1][1] * m[1][1] + m[2][1] * m[2][1]; 00224 if (!Math::RealEqual(t, 1.0, (Real)1e-04)) 00225 return true; 00226 t = m[0][2] * m[0][2] + m[1][2] * m[1][2] + m[2][2] * m[2][2]; 00227 if (!Math::RealEqual(t, 1.0, (Real)1e-04)) 00228 return true; 00229 00230 return false; 00231 } 00232 00235 inline _OgreExport friend std::ostream& operator << 00236 ( std::ostream& o, const Matrix3& mat ) 00237 { 00238 o << "Matrix3(" << mat[0][0] << ", " << mat[0][1] << ", " << mat[0][2] << ", " 00239 << mat[1][0] << ", " << mat[1][1] << ", " << mat[1][2] << ", " 00240 << mat[2][0] << ", " << mat[2][1] << ", " << mat[2][2] << ")"; 00241 return o; 00242 } 00243 00244 static const Real EPSILON; 00245 static const Matrix3 ZERO; 00246 static const Matrix3 IDENTITY; 00247 00248 protected: 00249 // support for eigensolver 00250 void Tridiagonal (Real afDiag[3], Real afSubDiag[3]); 00251 bool QLAlgorithm (Real afDiag[3], Real afSubDiag[3]); 00252 00253 // support for singular value decomposition 00254 static const Real ms_fSvdEpsilon; 00255 static const unsigned int ms_iSvdMaxIterations; 00256 static void Bidiagonalize (Matrix3& kA, Matrix3& kL, 00257 Matrix3& kR); 00258 static void GolubKahanStep (Matrix3& kA, Matrix3& kL, 00259 Matrix3& kR); 00260 00261 // support for spectral norm 00262 static Real MaxCubicRoot (Real afCoeff[3]); 00263 00264 Real m[3][3]; 00265 00266 // for faster access 00267 friend class Matrix4; 00268 }; 00271 } 00272 #endif
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sat Jan 14 2012 18:40:43