Quaternion.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  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. #pragma once
  24. #include "Matrix3.h"
  25. /// Rotation represented as a four-dimensional normalized vector.
  26. class Quaternion
  27. {
  28. public:
  29. /// Construct identity quaternion.
  30. Quaternion() :
  31. w_(1.0f),
  32. x_(0.0f),
  33. y_(0.0f),
  34. z_(0.0f)
  35. {
  36. }
  37. /// Copy-construct from another quaternion.
  38. Quaternion(const Quaternion& quat) :
  39. w_(quat.w_),
  40. x_(quat.x_),
  41. y_(quat.y_),
  42. z_(quat.z_)
  43. {
  44. }
  45. /// Construct from values.
  46. Quaternion(float w, float x, float y, float z) :
  47. w_(w),
  48. x_(x),
  49. y_(y),
  50. z_(z)
  51. {
  52. }
  53. /// Construct from a float array.
  54. Quaternion(const float* data) :
  55. w_(data[0]),
  56. x_(data[1]),
  57. y_(data[2]),
  58. z_(data[3])
  59. {
  60. }
  61. /// Construct from an angle (in degrees) and axis.
  62. Quaternion(float angle, const Vector3& axis)
  63. {
  64. FromAngleAxis(angle, axis);
  65. }
  66. /// Construct from Euler angles (in degrees.)
  67. Quaternion(float x, float y, float z)
  68. {
  69. FromEulerAngles(x, y, z);
  70. }
  71. /// Construct from the rotation difference between two vectors.
  72. Quaternion(const Vector3& start, const Vector3& end)
  73. {
  74. FromRotationTo(start, end);
  75. }
  76. /// Construct from orthonormal axes.
  77. Quaternion(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis)
  78. {
  79. FromAxes(xAxis, yAxis, zAxis);
  80. }
  81. /// Construct from a rotation matrix.
  82. Quaternion(const Matrix3& matrix)
  83. {
  84. FromRotationMatrix(matrix);
  85. }
  86. /// Assign from another quaternion.
  87. Quaternion& operator = (const Quaternion& rhs)
  88. {
  89. w_ = rhs.w_;
  90. x_ = rhs.x_;
  91. y_ = rhs.y_;
  92. z_ = rhs.z_;
  93. return *this;
  94. }
  95. /// Add-assign a quaternion.
  96. Quaternion& operator += (const Quaternion& rhs)
  97. {
  98. w_ += rhs.w_;
  99. x_ += rhs.x_;
  100. y_ += rhs.y_;
  101. z_ += rhs.z_;
  102. return *this;
  103. }
  104. /// Test for equality with another quaternion.
  105. bool operator == (const Quaternion& rhs) const { return Equals(w_, rhs.w_) && Equals(x_, rhs.x_) && Equals(y_, rhs.y_) && Equals(z_, rhs.z_); }
  106. /// Test for inequality with another quaternion.
  107. bool operator != (const Quaternion& rhs) const { return !Equals(w_, rhs.w_) || !Equals(x_, rhs.x_) || !Equals(y_, rhs.y_) || !Equals(z_, rhs.z_); }
  108. /// Multiply with a scalar.
  109. Quaternion operator * (float rhs) const { return Quaternion(w_ * rhs, x_ * rhs, y_ * rhs, z_ * rhs); }
  110. /// Return negation.
  111. Quaternion operator - () const { return Quaternion(-w_, -x_, -y_, -z_); }
  112. /// Add a quaternion.
  113. Quaternion operator + (const Quaternion& rhs) const { return Quaternion(w_ + rhs.w_, x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
  114. /// Subtract a quaternion.
  115. Quaternion operator - (const Quaternion& rhs) const { return Quaternion(w_ - rhs.w_, x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
  116. /// Multiply a quaternion.
  117. Quaternion operator * (const Quaternion& rhs) const
  118. {
  119. return Quaternion(
  120. w_ * rhs.w_ - x_ * rhs.x_ - y_ * rhs.y_ - z_ * rhs.z_,
  121. w_ * rhs.x_ + x_ * rhs.w_ + y_ * rhs.z_ - z_ * rhs.y_,
  122. w_ * rhs.y_ + y_ * rhs.w_ + z_ * rhs.x_ - x_ * rhs.z_,
  123. w_ * rhs.z_ + z_ * rhs.w_ + x_ * rhs.y_ - y_ * rhs.x_
  124. );
  125. }
  126. /// Multiply a Vector3.
  127. Vector3 operator * (const Vector3& rhs) const
  128. {
  129. Vector3 qVec(x_,y_,z_);
  130. Vector3 cross1(qVec.CrossProduct(rhs));
  131. Vector3 cross2(qVec.CrossProduct(cross1));
  132. return rhs + 2.0f * (cross1 * w_ + cross2);
  133. }
  134. /// Define from an angle (in degrees) and axis.
  135. void FromAngleAxis(float angle, const Vector3& axis);
  136. /// Define from Euler angles (in degrees.)
  137. void FromEulerAngles(float x, float y, float z);
  138. /// Define from the rotation difference between two vectors.
  139. void FromRotationTo(const Vector3& start, const Vector3& end);
  140. /// Define from orthonormal axes.
  141. void FromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
  142. /// Define from a rotation matrix.
  143. void FromRotationMatrix(const Matrix3& matrix);
  144. /// Normalize to unit length and return the previous length.
  145. float Normalize()
  146. {
  147. float len = sqrtf(w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_);
  148. if (len >= M_EPSILON)
  149. {
  150. float invLen = 1.0f / len;
  151. w_ *= invLen;
  152. x_ *= invLen;
  153. y_ *= invLen;
  154. z_ *= invLen;
  155. }
  156. return len;
  157. }
  158. /// Return normalized to unit length.
  159. Quaternion Normalized() const
  160. {
  161. float len = sqrtf(w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_);
  162. if (len >= M_EPSILON)
  163. return *this * (1.0f / len);
  164. else
  165. return IDENTITY;
  166. }
  167. /// Return inverse.
  168. Quaternion Inverse() const
  169. {
  170. float lenSquared = w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_;
  171. if (lenSquared >= M_EPSILON)
  172. {
  173. float invLenSquared = 1.0f / lenSquared;
  174. return Quaternion(
  175. w_ * invLenSquared,
  176. -x_ * invLenSquared,
  177. -y_ * invLenSquared,
  178. -z_ * invLenSquared
  179. );
  180. }
  181. else
  182. return IDENTITY;
  183. }
  184. /// Return squared length.
  185. float LengthSquared() const { return w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_; }
  186. /// Calculate dot product.
  187. float DotProduct(const Quaternion& rhs) const { return w_ * rhs.w_ + x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
  188. /// Return Euler angles in degrees.
  189. Vector3 EulerAngles() const;
  190. /// Return yaw angle in degrees.
  191. float YawAngle() const;
  192. /// Return pitch angle in degrees.
  193. float PitchAngle() const;
  194. /// Return roll angle in degrees.
  195. float RollAngle() const;
  196. /// Return the rotation matrix that corresponds to this quaternion.
  197. Matrix3 RotationMatrix() const;
  198. /// Spherical interpolation with another quaternion.
  199. Quaternion Slerp(Quaternion rhs, float t) const;
  200. /// Return float data.
  201. const float* GetData() const { return &w_; }
  202. /// Return as string.
  203. String ToString() const;
  204. /// W coordinate.
  205. float w_;
  206. /// X coordinate.
  207. float x_;
  208. /// Y coordinate.
  209. float y_;
  210. /// Z coordinate.
  211. float z_;
  212. /// Identity quaternion.
  213. static const Quaternion IDENTITY;
  214. };