CmQuaternion.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. // This file is based on material originally from:
  25. // Geometric Tools, LLC
  26. // Copyright (c) 1998-2010
  27. // Distributed under the Boost Software License, Version 1.0.
  28. // http://www.boost.org/LICENSE_1_0.txt
  29. // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  30. #pragma once
  31. #include "CmPrerequisitesUtil.h"
  32. #include "CmMath.h"
  33. #include "CmVector3.h"
  34. namespace CamelotFramework
  35. {
  36. class CM_UTILITY_EXPORT Quaternion
  37. {
  38. private:
  39. struct EulerAngleOrderData
  40. {
  41. int a, b, c;
  42. };
  43. public:
  44. Quaternion(float w = 1.0f, float x = 0.0f, float y = 0.0f, float z = 0.0f)
  45. :w(w), z(z), y(y), x(x)
  46. { }
  47. /**
  48. * @brief Construct a quaternion from a rotation matrix.
  49. */
  50. explicit Quaternion(const Matrix3& rot)
  51. {
  52. fromRotationMatrix(rot);
  53. }
  54. /**
  55. * @brief Construct a quaternion from an angle/axis.
  56. */
  57. explicit Quaternion(const Vector3& axis, const Radian& angle)
  58. {
  59. fromAxisAngle(axis, angle);
  60. }
  61. /**
  62. * @brief Construct a quaternion from 3 orthonormal local axes.
  63. */
  64. explicit Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
  65. {
  66. fromAxes(xaxis, yaxis, zaxis);
  67. }
  68. /**
  69. * @brief Construct a quaternion from euler angles, XYZ ordering.
  70. *
  71. * @see Quaternion::fromEulerAngles
  72. */
  73. explicit Quaternion(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
  74. {
  75. fromEulerAngles(xAngle, yAngle, zAngle);
  76. }
  77. /**
  78. * @brief Construct a quaternion from euler angles, custom ordering.
  79. *
  80. * @see Quaternion::fromEulerAngles
  81. */
  82. explicit Quaternion(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
  83. {
  84. fromEulerAngles(xAngle, yAngle, zAngle, order);
  85. }
  86. /**
  87. * @brief Exchange the contents of this quaternion with another.
  88. */
  89. void swap(Quaternion& other)
  90. {
  91. std::swap(w, other.w);
  92. std::swap(x, other.x);
  93. std::swap(y, other.y);
  94. std::swap(z, other.z);
  95. }
  96. float operator[] (const size_t i) const
  97. {
  98. assert(i < 4);
  99. return *(&w+i);
  100. }
  101. float& operator[] (const size_t i)
  102. {
  103. assert(i < 4);
  104. return *(&w+i);
  105. }
  106. void fromRotationMatrix(const Matrix3& mat);
  107. void fromAxisAngle(const Vector3& axis, const Radian& angle);
  108. void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
  109. /**
  110. * @brief Creates a quaternion from the provided Pitch/Yaw/Roll angles.
  111. *
  112. * @param xAngle Rotation about x axis. (AKA Pitch)
  113. * @param yAngle Rotation about y axis. (AKA Yaw)
  114. * @param zAngle Rotation about z axis. (AKA Roll)
  115. *
  116. * @note Since different values will be produced depending in which order are the rotations applied, this method assumes
  117. * they are applied in XYZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
  118. */
  119. void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
  120. /**
  121. * @brief Creates a quaternion from the provided Pitch/Yaw/Roll angles.
  122. *
  123. * @param xAngle Rotation about x axis. (AKA Pitch)
  124. * @param yAngle Rotation about y axis. (AKA Yaw)
  125. * @param zAngle Rotation about z axis. (AKA Roll)
  126. * @param order The order in which rotations will be extracted.
  127. * Different values can be retrieved depending on the order.
  128. */
  129. void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
  130. void toRotationMatrix(Matrix3& mat) const;
  131. void toAxisAngle(Vector3& axis, Radian& angle) const;
  132. void toAxes(Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) const;
  133. /**
  134. * @brief Extracts Pitch/Yaw/Roll rotations from this quaternion.
  135. *
  136. * @param [in,out] xAngle Rotation about x axis. (AKA Pitch)
  137. * @param [in,out] yAngle Rotation about y axis. (AKA Yaw)
  138. * @param [in,out] zAngle Rotation about z axis. (AKA Roll)
  139. *
  140. * @return True if unique solution was found, false otherwise.
  141. *
  142. * @note Since different values will be returned depending in which order are the rotations applied, this method assumes
  143. * they are applied in XYZ order. If you need a specific order, use the overloaded "toEulerAngles" method instead.
  144. */
  145. bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
  146. /**
  147. * @brief Extracts Pitch/Yaw/Roll rotations from this quaternion.
  148. *
  149. * @param xAngle Rotation about x axis. (AKA Pitch)
  150. * @param yAngle Rotation about y axis. (AKA Yaw)
  151. * @param zAngle Rotation about z axis. (AKA Roll)
  152. * @param order The order in which rotations will be extracted.
  153. * Different values can be retrieved depending on the order.
  154. *
  155. * @return True if unique solution was found, false otherwise.
  156. */
  157. bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle, EulerAngleOrder order) const;
  158. /**
  159. * @brief Get the local x-axis.
  160. */
  161. Vector3 xAxis() const;
  162. /**
  163. * @brief Get the local y-axis.
  164. */
  165. Vector3 yAxis() const;
  166. /**
  167. * @brief Get the local z-axis.
  168. */
  169. Vector3 zAxis() const;
  170. Quaternion& operator= (const Quaternion& rhs)
  171. {
  172. w = rhs.w;
  173. x = rhs.x;
  174. y = rhs.y;
  175. z = rhs.z;
  176. return *this;
  177. }
  178. Quaternion operator+ (const Quaternion& rhs) const;
  179. Quaternion operator- (const Quaternion& rhs) const;
  180. Quaternion operator* (const Quaternion& rhs) const;
  181. Quaternion operator* (float rhs) const;
  182. Quaternion operator- () const;
  183. bool operator== (const Quaternion& rhs) const
  184. {
  185. return (rhs.x == x) && (rhs.y == y) && (rhs.z == z) && (rhs.w == w);
  186. }
  187. bool operator!= (const Quaternion& rhs) const
  188. {
  189. return !operator==(rhs);
  190. }
  191. friend Quaternion operator* (float lhs, const Quaternion& rhs);
  192. float dot(const Quaternion& other) const;
  193. /**
  194. * @brief Normalizes this quaternion, and returns the previous length.
  195. */
  196. float normalize();
  197. /**
  198. * @brief Gets the inverse.
  199. *
  200. * @note Quaternion must be non-zero.
  201. */
  202. Quaternion inverse() const;
  203. /**
  204. * @brief Rotates the provided vector.
  205. */
  206. Vector3 rotate(const Vector3& vec) const;
  207. bool isNaN() const
  208. {
  209. return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
  210. }
  211. /**
  212. * @brief Spherical linear interpolation
  213. */
  214. static Quaternion slerp(float t, const Quaternion& p,
  215. const Quaternion& q, bool shortestPath = false);
  216. /**
  217. * @brief Gets the shortest arc quaternion to rotate this vector to the destination
  218. * vector.
  219. */
  220. static Quaternion getRotationFromTo(const Vector3& from, const Vector3& dest, const Vector3& fallbackAxis = Vector3::ZERO);
  221. static const float EPSILON;
  222. static const Quaternion ZERO;
  223. static const Quaternion IDENTITY;
  224. float x, y, z, w;
  225. private:
  226. static const EulerAngleOrderData EA_LOOKUP[6];
  227. };
  228. }