Quaternion.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #ifndef QUATERNION_H_
  2. #define QUATERNION_H_
  3. #include "Vector3.h"
  4. #include "Matrix.h"
  5. namespace gameplay
  6. {
  7. class Matrix;
  8. /**
  9. * Defines a 4-element quaternion that represents the orientation of an object in space.
  10. *
  11. * Quaternions are typically used as a replacement for euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
  12. *
  13. * Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when necessary, by calling the normalize method.
  14. * The package provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
  15. *
  16. * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
  17. * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
  18. * squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
  19. * - the curve is not smooth at the control points;
  20. * - the angular velocity is not constant;
  21. * - the angular velocity is not continuous at the control points.
  22. *
  23. * Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
  24. * The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
  25. *
  26. * The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
  27. *
  28. * As an example, consider the following quaternions:
  29. *
  30. * q1 = (0.6, 0.8, 0.0, 0.0),
  31. * q2 = (0.0, 0.6, 0.8, 0.0),
  32. * q3 = (0.6, 0.0, 0.8, 0.0), and
  33. * q4 = (-0.8, 0.0, -0.6, 0.0).
  34. * For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
  35. */
  36. class Quaternion
  37. {
  38. friend class Curve;
  39. public:
  40. /**
  41. * The x-value of the quaternion's vector component.
  42. */
  43. float x;
  44. /**
  45. * The y-value of the quaternion's vector component.
  46. */
  47. float y;
  48. /**
  49. * The z-value of the quaternion's vector component.
  50. */
  51. float z;
  52. /**
  53. * The scalar component of the quaternion.
  54. */
  55. float w;
  56. /**
  57. * Constructs a quaternion initialized to (0, 0, 0, 1).
  58. */
  59. Quaternion();
  60. /**
  61. * Constructs a quaternion initialized to (0, 0, 0, 1).
  62. *
  63. * @param x The x component of the quaternion.
  64. * @param y The y component of the quaternion.
  65. * @param z The z component of the quaternion.
  66. * @param w The w component of the quaternion.
  67. */
  68. Quaternion(float x, float y, float z, float w);
  69. /**
  70. * Constructs a new quaternion from the values in the specified array.
  71. *
  72. * @param array The values for the new quaternion.
  73. */
  74. Quaternion(float* array);
  75. /**
  76. * Constructs a quaternion equal to the rotation from the specified axis and angle.
  77. *
  78. * @param axis A vector describing the axis of rotation.
  79. * @param angle The angle of rotation (in radians).
  80. */
  81. Quaternion(const Vector3& axis, float angle);
  82. /**
  83. * Constructs a new quaternion that is a copy of the specified one.
  84. *
  85. * @param copy The quaternion to copy.
  86. */
  87. Quaternion(const Quaternion& copy);
  88. /**
  89. * Destructor.
  90. */
  91. ~Quaternion();
  92. /**
  93. * Returns the identity quaternion.
  94. *
  95. * @return The identity quaternion.
  96. */
  97. static const Quaternion& identity();
  98. /**
  99. * Returns the quaternion with all zeros.
  100. *
  101. * @return The quaternion.
  102. */
  103. static const Quaternion& zero();
  104. /**
  105. * Determines if this quaternion is equal to the identity quaternion.
  106. *
  107. * @return true if it is the identity quaternion, false otherwise.
  108. */
  109. bool isIdentity() const;
  110. /**
  111. * Determines if this quaternion is all zeros.
  112. *
  113. * @return true if this quaternion is all zeros, false otherwise.
  114. */
  115. bool isZero() const;
  116. /**
  117. * Creates this quaternion equal to the rotation from the specified axis and angle
  118. * and stores the result in dst.
  119. *
  120. * @param axis A vector describing the axis of rotation.
  121. * @param angle The angle of rotation (in radians).
  122. * @param dst A quaternion to store the conjugate in.
  123. */
  124. static void createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst);
  125. /**
  126. * Sets this quaternion to the conjugate of itself.
  127. */
  128. void conjugate();
  129. /**
  130. * Gets the conjugate of this quaternion in dst.
  131. *
  132. * @param dst A quaternion to store the conjugate in.
  133. */
  134. void conjugate(Quaternion* dst) const;
  135. /**
  136. * Sets this quaternion to the inverse of itself.
  137. *
  138. * Note that the inverse of a quaternion is equal to its conjugate
  139. * when the quaternion is unit-length. For this reason, it is more
  140. * efficient to use the conjugate method directly when you know your
  141. * quaternion is already unit-length.
  142. *
  143. * @return true if the inverse can be computed, false otherwise.
  144. */
  145. bool inverse();
  146. /**
  147. * Gets the inverse of this quaternion in dst.
  148. *
  149. * Note that the inverse of a quaternion is equal to its conjugate
  150. * when the quaternion is unit-length. For this reason, it is more
  151. * efficient to use the conjugate method directly when you know your
  152. * quaternion is already unit-length.
  153. *
  154. * @param dst A quaternion to store the inverse in.
  155. *
  156. * @return true if the inverse can be computed, false otherwise.
  157. */
  158. bool inverse(Quaternion* dst) const;
  159. /**
  160. * Multiplies this quaternion by the specified one and stores the result in this quaternion.
  161. *
  162. * @param q The quaternion to multiply.
  163. */
  164. void multiply(const Quaternion& q);
  165. /**
  166. * Multiplies the specified quaternions and stores the result in dst.
  167. *
  168. * @param q1 The first quaternion.
  169. * @param q2 The second quaternion.
  170. * @param dst A quaternion to store the result in.
  171. */
  172. static void multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
  173. /**
  174. * Normalizes this quaternion to have unit length.
  175. *
  176. * If the quaternion already has unit length or if the length
  177. * of the quaternion is zero, this method does nothing.
  178. */
  179. void normalize();
  180. /**
  181. * Normalizes this quaternion and stores the result in dst.
  182. *
  183. * If the quaternion already has unit length or if the length
  184. * of the quaternion is zero, this method simply copies
  185. * this vector into dst.
  186. *
  187. * @param dst A quaternion to store the result in.
  188. */
  189. void normalize(Quaternion* dst) const;
  190. /**
  191. * Sets the elements of the quaternion to the specified values.
  192. *
  193. * @param x The new x-value.
  194. * @param y The new y-value.
  195. * @param z The new z-value.
  196. * @param w The new w-value.
  197. */
  198. void set(float x, float y, float z, float w);
  199. /**
  200. * Sets the elements of the quaternion from the values in the specified array.
  201. *
  202. * @param array An array containing the elements of the quaternion in the order x, y, z, w.
  203. */
  204. void set(float* array);
  205. /**
  206. * Sets the quaternion equal to the rotation from the specified axis and angle.
  207. *
  208. * @param axis The axis of rotation.
  209. * @param angle The angle of rotation (in radians).
  210. */
  211. void set(const Vector3& axis, float angle);
  212. /**
  213. * Sets the elements of this quaternion to a copy of the specified quaternion.
  214. *
  215. * @param q The quaternion to copy.
  216. */
  217. void set(const Quaternion& q);
  218. /**
  219. * Sets this quaternion to be equal to the identity quaternion.
  220. */
  221. void setIdentity();
  222. /**
  223. * Converts this Quaternion4f to axis-angle notation. The axis is normalized.
  224. *
  225. * @param e The Vector3f which stores the axis.
  226. *
  227. * @return The angle (in radians).
  228. */
  229. float toAxisAngle(Vector3* e) const;
  230. /**
  231. * Interpolates between two quaternions using linear interpolation.
  232. *
  233. * The interpolation curve for linear interpolation between
  234. * quaternions gives a straight line in quaternion space.
  235. *
  236. * @param q1 The first quaternion.
  237. * @param q2 The second quaternion.
  238. * @param t The interpolation coefficient.
  239. * @param dst A quaternion to store the result in.
  240. */
  241. static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
  242. /**
  243. * Interpolates between two quaternions using spherical linear interpolation.
  244. *
  245. * Spherical linear interpolation provides smooth transitions between different
  246. * orientations and is often useful for animating models or cameras in 3D.
  247. *
  248. * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
  249. * This method does not automatically normalize the input quaternions, so it is up to the
  250. * caller to ensure they call normalize beforehand, if necessary.
  251. *
  252. * @param q1 The first quaternion.
  253. * @param q2 The second quaternion.
  254. * @param t The interpolation coefficient.
  255. * @param dst A quaternion to store the result in.
  256. */
  257. static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
  258. /**
  259. * Interpolates over a series of quaternions using spherical spline interpolation.
  260. *
  261. * Spherical spline interpolation provides smooth transitions between different
  262. * orientations and is often useful for animating models or cameras in 3D.
  263. *
  264. * Note: For accurate interpolation, the input quaternions must be unit.
  265. * This method does not automatically normalize the input quaternions,
  266. * so it is up to the caller to ensure they call normalize beforehand, if necessary.
  267. *
  268. * @param q1 The first quaternion.
  269. * @param q2 The second quaternion.
  270. * @param s1 The first control point.
  271. * @param s2 The second control point.
  272. * @param t The interpolation coefficient.
  273. * @param dst A quaternion to store the result in.
  274. */
  275. static void squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst);
  276. /**
  277. * Calculates the quaternion product of this quaternion with the given quaternion.
  278. *
  279. * Note: this does not modify this quaternion.
  280. *
  281. * @param q The quaternion to multiply.
  282. * @return The quaternion product.
  283. */
  284. inline Quaternion operator*(const Quaternion& q) const;
  285. /**
  286. * Multiplies this quaternion with the given quaternion.
  287. *
  288. * @param q The quaternion to multiply.
  289. * @return This quaternion, after the multiplication occurs.
  290. */
  291. inline Quaternion& operator*=(const Quaternion& q);
  292. private:
  293. /**
  294. * Interpolates between two quaternions using spherical linear interpolation.
  295. *
  296. * Spherical linear interpolation provides smooth transitions between different
  297. * orientations and is often useful for animating models or cameras in 3D.
  298. *
  299. * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
  300. * This method does not automatically normalize the input quaternions, so it is up to the
  301. * caller to ensure they call normalize beforehand, if necessary.
  302. *
  303. * @param q1x The x component of the first quaternion.
  304. * @param q1y The y component of the first quaternion.
  305. * @param q1z The z component of the first quaternion.
  306. * @param q1w The w component of the first quaternion.
  307. * @param q2x The x component of the second quaternion.
  308. * @param q2y The y component of the second quaternion.
  309. * @param q2z The z component of the second quaternion.
  310. * @param q2w The w component of the second quaternion.
  311. * @param t The interpolation coefficient.
  312. * @param dstx A pointer to store the x component of the slerp in.
  313. * @param dsty A pointer to store the y component of the slerp in.
  314. * @param dstz A pointer to store the z component of the slerp in.
  315. * @param dstw A pointer to store the w component of the slerp in.
  316. */
  317. static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw);
  318. static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
  319. };
  320. }
  321. #include "Quaternion.inl"
  322. #endif