CmMatrix3.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #pragma once
  25. #include "CmPrerequisitesUtil.h"
  26. #include "CmVector3.h"
  27. namespace CamelotFramework
  28. {
  29. class CM_UTILITY_EXPORT Matrix3
  30. {
  31. private:
  32. struct EulerAngleOrderData
  33. {
  34. int a, b, c;
  35. float sign;
  36. };
  37. public:
  38. Matrix3() {}
  39. Matrix3(const Matrix3& mat)
  40. {
  41. memcpy(m, mat.m, 9*sizeof(float));
  42. }
  43. Matrix3(float m00, float m01, float m02,
  44. float m10, float m11, float m12,
  45. float m20, float m21, float m22)
  46. {
  47. m[0][0] = m00;
  48. m[0][1] = m01;
  49. m[0][2] = m02;
  50. m[1][0] = m10;
  51. m[1][1] = m11;
  52. m[1][2] = m12;
  53. m[2][0] = m20;
  54. m[2][1] = m21;
  55. m[2][2] = m22;
  56. }
  57. /**
  58. * @brief Construct a matrix from a quaternion.
  59. */
  60. explicit Matrix3(const Quaternion& quad)
  61. {
  62. fromQuaternion(quad);
  63. }
  64. /**
  65. * @brief Construct a matrix that performs rotation and scale.
  66. */
  67. explicit Matrix3(const Quaternion& quad, const Vector3 scale)
  68. {
  69. fromQuaternion(quad);
  70. for (int row = 0; row < 3; row++)
  71. {
  72. for (int col = 0; col < 3; col++)
  73. m[row][col] = scale[row]*m[row][col];
  74. }
  75. }
  76. /**
  77. * @brief Construct a matrix from an angle/axis.
  78. */
  79. explicit Matrix3(const Vector3& axis, const Radian& angle)
  80. {
  81. fromAxisAngle(axis, angle);
  82. }
  83. /**
  84. * @brief Construct a matrix from 3 orthonormal local axes.
  85. */
  86. explicit Matrix3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
  87. {
  88. fromAxes(xaxis, yaxis, zaxis);
  89. }
  90. /**
  91. * @brief Construct a matrix from euler angles, XYZ ordering.
  92. *
  93. * @see Matrix3::fromEulerAngles
  94. */
  95. explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
  96. {
  97. fromEulerAngles(xAngle, yAngle, zAngle);
  98. }
  99. /**
  100. * @brief Construct a matrix from euler angles, custom ordering.
  101. *
  102. * @see Matrix3::fromEulerAngles
  103. */
  104. explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
  105. {
  106. fromEulerAngles(xAngle, yAngle, zAngle, order);
  107. }
  108. void swap(Matrix3& other)
  109. {
  110. std::swap(m[0][0], other.m[0][0]);
  111. std::swap(m[0][1], other.m[0][1]);
  112. std::swap(m[0][2], other.m[0][2]);
  113. std::swap(m[1][0], other.m[1][0]);
  114. std::swap(m[1][1], other.m[1][1]);
  115. std::swap(m[1][2], other.m[1][2]);
  116. std::swap(m[2][0], other.m[2][0]);
  117. std::swap(m[2][1], other.m[2][1]);
  118. std::swap(m[2][2], other.m[2][2]);
  119. }
  120. inline float* operator[] (size_t row) const
  121. {
  122. return (float*)m[row];
  123. }
  124. Vector3 getColumn(size_t col) const;
  125. void setColumn(size_t col, const Vector3& vec);
  126. Matrix3& operator= (const Matrix3& rhs)
  127. {
  128. memcpy(m, rhs.m, 9*sizeof(float));
  129. return *this;
  130. }
  131. bool operator== (const Matrix3& rhs) const;
  132. bool operator!= (const Matrix3& rhs) const;
  133. Matrix3 operator+ (const Matrix3& rhs) const;
  134. Matrix3 operator- (const Matrix3& rhs) const;
  135. Matrix3 operator* (const Matrix3& rhs) const;
  136. Matrix3 operator- () const;
  137. Matrix3 operator* (float rhs) const;
  138. friend Matrix3 operator* (float lhs, const Matrix3& rhs);
  139. Vector3 transform(const Vector3& vec) const;
  140. Matrix3 transpose () const;
  141. bool inverse(Matrix3& mat, float fTolerance = 1e-06f) const;
  142. Matrix3 inverse(float fTolerance = 1e-06f) const;
  143. float determinant() const;
  144. void singularValueDecomposition (Matrix3& matL, Vector3& matS, Matrix3& matR) const;
  145. void QDUDecomposition (Matrix3& matQ, Vector3& vecD, Vector3& vecU) const;
  146. /**
  147. * @brief Gram-Schmidt orthonormalization (applied to columns of rotation matrix)
  148. */
  149. void orthonormalize();
  150. /**
  151. * @brief Converts an orthonormal matrix to axis angle representation.
  152. *
  153. * @note Matrix must be orthonormal.
  154. */
  155. void toAxisAngle(Vector3& axis, Radian& angle) const;
  156. /**
  157. * @brief Creates a rotation matrix from an axis angle representation.
  158. */
  159. void fromAxisAngle(const Vector3& axis, const Radian& angle);
  160. /**
  161. * @brief Converts an orthonormal matrix to quaternion representation.
  162. *
  163. * @note Matrix must be orthonormal.
  164. */
  165. void toQuaternion(Quaternion& quat) const;
  166. /**
  167. * @brief Creates a rotation matrix from a quaternion representation.
  168. */
  169. void fromQuaternion(const Quaternion& quat);
  170. /**
  171. * @brief Creates a matrix from a three axes.
  172. */
  173. void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
  174. /**
  175. * @brief Extracts Pitch/Yaw/Roll rotations from this matrix.
  176. *
  177. * @param [in,out] xAngle Rotation about x axis. (AKA Pitch)
  178. * @param [in,out] yAngle Rotation about y axis. (AKA Yaw)
  179. * @param [in,out] zAngle Rotation about z axis. (AKA Roll)
  180. *
  181. * @return True if unique solution was found, false otherwise.
  182. *
  183. * @note Matrix must be orthonormal.
  184. *
  185. * Since different values will be returned depending in which order are the rotations applied, this method assumes
  186. * they are applied in XYZ order. If you need a specific order, use the overloaded "toEulerAngles" method instead.
  187. */
  188. bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
  189. /**
  190. * @brief Extracts Pitch/Yaw/Roll rotations from this matrix.
  191. *
  192. * @param xAngle Rotation about x axis. (AKA Pitch)
  193. * @param yAngle Rotation about y axis. (AKA Yaw)
  194. * @param zAngle Rotation about z axis. (AKA Roll)
  195. * @param order The order in which rotations will be extracted.
  196. * Different values can be retrieved depending on the order.
  197. *
  198. * @return True if unique solution was found, false otherwise.
  199. *
  200. * @note Matrix must be orthonormal.
  201. */
  202. bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle, EulerAngleOrder order) const;
  203. /**
  204. * @brief Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
  205. *
  206. * @param xAngle Rotation about x axis. (AKA Pitch)
  207. * @param yAngle Rotation about y axis. (AKA Yaw)
  208. * @param zAngle Rotation about z axis. (AKA Roll)
  209. *
  210. * @note Matrix must be orthonormal.
  211. * Since different values will be produced depending in which order are the rotations applied, this method assumes
  212. * they are applied in XYZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
  213. */
  214. void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
  215. /**
  216. * @brief Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
  217. *
  218. * @param xAngle Rotation about x axis. (AKA Pitch)
  219. * @param yAngle Rotation about y axis. (AKA Yaw)
  220. * @param zAngle Rotation about z axis. (AKA Roll)
  221. * @param order The order in which rotations will be extracted.
  222. * Different values can be retrieved depending on the order.
  223. *
  224. * @note Matrix must be orthonormal.
  225. */
  226. void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
  227. /**
  228. * @brief Eigensolver, matrix must be symmetric.
  229. */
  230. void eigenSolveSymmetric(float eigenValues[3], Vector3 eigenVectors[3]) const;
  231. static const float EPSILON;
  232. static const Matrix3 ZERO;
  233. static const Matrix3 IDENTITY;
  234. protected:
  235. friend class Matrix4;
  236. // Support for eigensolver
  237. void tridiagonal (float diag[3], float subDiag[3]);
  238. bool QLAlgorithm (float diag[3], float subDiag[3]);
  239. // Support for singular value decomposition
  240. static const float SVD_EPSILON;
  241. static const unsigned int SVD_MAX_ITERS;
  242. static void bidiagonalize (Matrix3& matA, Matrix3& matL, Matrix3& matR);
  243. static void golubKahanStep (Matrix3& matA, Matrix3& matL, Matrix3& matR);
  244. // Euler angle conversions
  245. static const EulerAngleOrderData EA_LOOKUP[6];
  246. float m[3][3];
  247. };
  248. CM_ALLOW_MEMCPY_SERIALIZATION(Matrix3);
  249. }