ImathQuat.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright Contributors to the OpenEXR Project.
  4. //
  5. //
  6. // A quaternion
  7. //
  8. // "Quaternions came from Hamilton ... and have been an unmixed
  9. // evil to those who have touched them in any way. Vector is a
  10. // useless survival ... and has never been of the slightest use
  11. // to any creature."
  12. //
  13. // - Lord Kelvin
  14. //
  15. #ifndef INCLUDED_IMATHQUAT_H
  16. #define INCLUDED_IMATHQUAT_H
  17. #include "ImathExport.h"
  18. #include "ImathNamespace.h"
  19. #include "ImathMatrix.h"
  20. #include <iostream>
  21. IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
  22. #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
  23. // Disable MS VC++ warnings about conversion from double to float
  24. # pragma warning(push)
  25. # pragma warning(disable : 4244)
  26. #endif
  27. ///
  28. /// The Quat class implements the quaternion numerical type -- you
  29. /// will probably want to use this class to represent orientations
  30. /// in R3 and to convert between various euler angle reps. You
  31. /// should probably use Imath::Euler<> for that.
  32. ///
  33. template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Quat
  34. {
  35. public:
  36. /// @{
  37. /// @name Direct access to elements
  38. /// The real part
  39. T r;
  40. /// The imaginary vector
  41. Vec3<T> v;
  42. /// @}
  43. /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the
  44. /// imaginary part.
  45. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int index) IMATH_NOEXCEPT; // as 4D vector
  46. /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the
  47. /// imaginary part.
  48. IMATH_HOSTDEVICE constexpr T operator[] (int index) const IMATH_NOEXCEPT;
  49. /// @{
  50. /// @name Constructors
  51. /// Default constructor is the identity quat
  52. IMATH_HOSTDEVICE constexpr Quat() IMATH_NOEXCEPT;
  53. /// Copy constructor
  54. IMATH_HOSTDEVICE constexpr Quat (const Quat& q) IMATH_NOEXCEPT;
  55. /// Construct from a quaternion of a another base type
  56. template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat (const Quat<S>& q) IMATH_NOEXCEPT;
  57. /// Initialize with real part `s` and imaginary vector 1(i,j,k)`
  58. IMATH_HOSTDEVICE constexpr Quat (T s, T i, T j, T k) IMATH_NOEXCEPT;
  59. /// Initialize with real part `s` and imaginary vector `d`
  60. IMATH_HOSTDEVICE constexpr Quat (T s, Vec3<T> d) IMATH_NOEXCEPT;
  61. /// The identity quaternion
  62. IMATH_HOSTDEVICE constexpr static Quat<T> identity() IMATH_NOEXCEPT;
  63. /// Assignment
  64. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator= (const Quat<T>& q) IMATH_NOEXCEPT;
  65. /// Destructor
  66. ~Quat () IMATH_NOEXCEPT = default;
  67. /// @}
  68. /// @{
  69. /// @name Basic Algebra
  70. ///
  71. /// Note that the operator return values are *NOT* normalized
  72. //
  73. /// Quaternion multiplication
  74. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator*= (const Quat<T>& q) IMATH_NOEXCEPT;
  75. /// Scalar multiplication: multiply both real and imaginary parts
  76. /// by the given scalar.
  77. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator*= (T t) IMATH_NOEXCEPT;
  78. /// Quaterion division, using the inverse()
  79. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator/= (const Quat<T>& q) IMATH_NOEXCEPT;
  80. /// Scalar division: multiply both real and imaginary parts
  81. /// by the given scalar.
  82. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator/= (T t) IMATH_NOEXCEPT;
  83. /// Quaternion addition
  84. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator+= (const Quat<T>& q) IMATH_NOEXCEPT;
  85. /// Quaternion subtraction
  86. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator-= (const Quat<T>& q) IMATH_NOEXCEPT;
  87. /// Equality
  88. template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Quat<S>& q) const IMATH_NOEXCEPT;
  89. /// Inequality
  90. template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Quat<S>& q) const IMATH_NOEXCEPT;
  91. /// @}
  92. /// @{
  93. /// @name Query
  94. /// Return the R4 length
  95. IMATH_HOSTDEVICE constexpr T length() const IMATH_NOEXCEPT; // in R4
  96. /// Return the angle of the axis/angle representation
  97. IMATH_HOSTDEVICE constexpr T angle() const IMATH_NOEXCEPT;
  98. /// Return the axis of the axis/angle representation
  99. IMATH_HOSTDEVICE constexpr Vec3<T> axis() const IMATH_NOEXCEPT;
  100. /// Return a 3x3 rotation matrix
  101. IMATH_HOSTDEVICE constexpr Matrix33<T> toMatrix33() const IMATH_NOEXCEPT;
  102. /// Return a 4x4 rotation matrix
  103. IMATH_HOSTDEVICE constexpr Matrix44<T> toMatrix44() const IMATH_NOEXCEPT;
  104. /// Return the logarithm of the quaterion
  105. IMATH_HOSTDEVICE Quat<T> log() const IMATH_NOEXCEPT;
  106. /// Return the exponent of the quaterion
  107. IMATH_HOSTDEVICE Quat<T> exp() const IMATH_NOEXCEPT;
  108. /// @}
  109. /// @{
  110. /// @name Utility Methods
  111. /// Invert in place: this = 1 / this.
  112. /// @return const reference to this.
  113. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& invert() IMATH_NOEXCEPT;
  114. /// Return 1/this, leaving this unchanged.
  115. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> inverse() const IMATH_NOEXCEPT;
  116. /// Normalize in place
  117. /// @return const reference to this.
  118. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& normalize() IMATH_NOEXCEPT;
  119. /// Return a normalized quaternion, leaving this unmodified.
  120. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> normalized() const IMATH_NOEXCEPT;
  121. /// Rotate the given point by the quaterion.
  122. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> rotateVector (const Vec3<T>& original) const IMATH_NOEXCEPT;
  123. /// Return the Euclidean inner product.
  124. IMATH_HOSTDEVICE constexpr T euclideanInnerProduct (const Quat<T>& q) const IMATH_NOEXCEPT;
  125. /// Set the quaterion to be a rotation around the given axis by the
  126. /// given angle.
  127. /// @return const reference to this.
  128. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& setAxisAngle (const Vec3<T>& axis, T radians) IMATH_NOEXCEPT;
  129. /// Set the quaternion to be a rotation that transforms the
  130. /// direction vector `fromDirection` to `toDirection`
  131. /// @return const reference to this.
  132. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>&
  133. setRotation (const Vec3<T>& fromDirection, const Vec3<T>& toDirection) IMATH_NOEXCEPT;
  134. /// @}
  135. /// The base type: In templates that accept a parameter `V`, you
  136. /// can refer to `T` as `V::BaseType`
  137. typedef T BaseType;
  138. private:
  139. IMATH_HOSTDEVICE void setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) IMATH_NOEXCEPT;
  140. };
  141. template <class T>
  142. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT;
  143. template <class T>
  144. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT;
  145. template <class T>
  146. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>
  147. squad (const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& qa, const Quat<T>& qb, T t) IMATH_NOEXCEPT;
  148. ///
  149. /// From advanced Animation and Rendering Techniques by Watt and Watt,
  150. /// Page 366:
  151. ///
  152. /// computing the inner quadrangle points (qa and qb) to guarantee
  153. /// tangent continuity.
  154. template <class T>
  155. IMATH_HOSTDEVICE void intermediate (const Quat<T>& q0,
  156. const Quat<T>& q1,
  157. const Quat<T>& q2,
  158. const Quat<T>& q3,
  159. Quat<T>& qa,
  160. Quat<T>& qb) IMATH_NOEXCEPT;
  161. template <class T>
  162. IMATH_HOSTDEVICE constexpr Matrix33<T> operator* (const Matrix33<T>& M, const Quat<T>& q) IMATH_NOEXCEPT;
  163. template <class T>
  164. IMATH_HOSTDEVICE constexpr Matrix33<T> operator* (const Quat<T>& q, const Matrix33<T>& M) IMATH_NOEXCEPT;
  165. template <class T> std::ostream& operator<< (std::ostream& o, const Quat<T>& q);
  166. template <class T>
  167. IMATH_HOSTDEVICE constexpr Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
  168. template <class T>
  169. IMATH_HOSTDEVICE constexpr Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
  170. template <class T>
  171. IMATH_HOSTDEVICE constexpr Quat<T> operator/ (const Quat<T>& q, T t) IMATH_NOEXCEPT;
  172. template <class T>
  173. IMATH_HOSTDEVICE constexpr Quat<T> operator* (const Quat<T>& q, T t) IMATH_NOEXCEPT;
  174. template <class T>
  175. IMATH_HOSTDEVICE constexpr Quat<T> operator* (T t, const Quat<T>& q) IMATH_NOEXCEPT;
  176. template <class T>
  177. IMATH_HOSTDEVICE constexpr Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
  178. template <class T>
  179. IMATH_HOSTDEVICE constexpr Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
  180. template <class T>
  181. IMATH_HOSTDEVICE constexpr Quat<T> operator~ (const Quat<T>& q) IMATH_NOEXCEPT;
  182. template <class T>
  183. IMATH_HOSTDEVICE constexpr Quat<T> operator- (const Quat<T>& q) IMATH_NOEXCEPT;
  184. template <class T>
  185. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> operator* (const Vec3<T>& v, const Quat<T>& q) IMATH_NOEXCEPT;
  186. /// Quaternion of type float
  187. typedef Quat<float> Quatf;
  188. /// Quaternion of type double
  189. typedef Quat<double> Quatd;
  190. //---------------
  191. // Implementation
  192. //---------------
  193. template <class T>
  194. IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat() IMATH_NOEXCEPT : r (1), v (0, 0, 0)
  195. {
  196. // empty
  197. }
  198. template <class T>
  199. template <class S>
  200. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>::Quat (const Quat<S>& q) IMATH_NOEXCEPT : r (q.r), v (q.v)
  201. {
  202. // empty
  203. }
  204. template <class T>
  205. IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat (T s, T i, T j, T k) IMATH_NOEXCEPT : r (s), v (i, j, k)
  206. {
  207. // empty
  208. }
  209. template <class T>
  210. IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat (T s, Vec3<T> d) IMATH_NOEXCEPT : r (s), v (d)
  211. {
  212. // empty
  213. }
  214. template <class T>
  215. IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat (const Quat<T>& q) IMATH_NOEXCEPT : r (q.r), v (q.v)
  216. {
  217. // empty
  218. }
  219. template <class T>
  220. IMATH_HOSTDEVICE constexpr inline Quat<T>
  221. Quat<T>::identity() IMATH_NOEXCEPT
  222. {
  223. return Quat<T>();
  224. }
  225. template <class T>
  226. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  227. Quat<T>::operator= (const Quat<T>& q) IMATH_NOEXCEPT
  228. {
  229. r = q.r;
  230. v = q.v;
  231. return *this;
  232. }
  233. template <class T>
  234. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  235. Quat<T>::operator*= (const Quat<T>& q) IMATH_NOEXCEPT
  236. {
  237. T rtmp = r * q.r - (v ^ q.v);
  238. v = r * q.v + v * q.r + v % q.v;
  239. r = rtmp;
  240. return *this;
  241. }
  242. template <class T>
  243. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  244. Quat<T>::operator*= (T t) IMATH_NOEXCEPT
  245. {
  246. r *= t;
  247. v *= t;
  248. return *this;
  249. }
  250. template <class T>
  251. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  252. Quat<T>::operator/= (const Quat<T>& q) IMATH_NOEXCEPT
  253. {
  254. *this = *this * q.inverse();
  255. return *this;
  256. }
  257. template <class T>
  258. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  259. Quat<T>::operator/= (T t) IMATH_NOEXCEPT
  260. {
  261. r /= t;
  262. v /= t;
  263. return *this;
  264. }
  265. template <class T>
  266. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  267. Quat<T>::operator+= (const Quat<T>& q) IMATH_NOEXCEPT
  268. {
  269. r += q.r;
  270. v += q.v;
  271. return *this;
  272. }
  273. template <class T>
  274. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
  275. Quat<T>::operator-= (const Quat<T>& q) IMATH_NOEXCEPT
  276. {
  277. r -= q.r;
  278. v -= q.v;
  279. return *this;
  280. }
  281. template <class T>
  282. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T&
  283. Quat<T>::operator[] (int index) IMATH_NOEXCEPT
  284. {
  285. return index ? v[index - 1] : r;
  286. }
  287. template <class T>
  288. IMATH_HOSTDEVICE constexpr inline T
  289. Quat<T>::operator[] (int index) const IMATH_NOEXCEPT
  290. {
  291. return index ? v[index - 1] : r;
  292. }
  293. template <class T>
  294. template <class S>
  295. IMATH_HOSTDEVICE constexpr inline bool
  296. Quat<T>::operator== (const Quat<S>& q) const IMATH_NOEXCEPT
  297. {
  298. return r == q.r && v == q.v;
  299. }
  300. template <class T>
  301. template <class S>
  302. IMATH_HOSTDEVICE constexpr inline bool
  303. Quat<T>::operator!= (const Quat<S>& q) const IMATH_NOEXCEPT
  304. {
  305. return r != q.r || v != q.v;
  306. }
  307. /// 4D dot product
  308. template <class T>
  309. IMATH_HOSTDEVICE constexpr inline T
  310. operator^ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  311. {
  312. return q1.r * q2.r + (q1.v ^ q2.v);
  313. }
  314. template <class T>
  315. IMATH_HOSTDEVICE constexpr inline T
  316. Quat<T>::length() const IMATH_NOEXCEPT
  317. {
  318. return std::sqrt (r * r + (v ^ v));
  319. }
  320. template <class T>
  321. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
  322. Quat<T>::normalize() IMATH_NOEXCEPT
  323. {
  324. if (T l = length())
  325. {
  326. r /= l;
  327. v /= l;
  328. }
  329. else
  330. {
  331. r = 1;
  332. v = Vec3<T> (0);
  333. }
  334. return *this;
  335. }
  336. template <class T>
  337. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  338. Quat<T>::normalized() const IMATH_NOEXCEPT
  339. {
  340. if (T l = length())
  341. return Quat (r / l, v / l);
  342. return Quat();
  343. }
  344. template <class T>
  345. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  346. Quat<T>::inverse() const IMATH_NOEXCEPT
  347. {
  348. //
  349. // 1 Q*
  350. // - = ---- where Q* is conjugate (operator~)
  351. // Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
  352. //
  353. T qdot = *this ^ *this;
  354. return Quat (r / qdot, -v / qdot);
  355. }
  356. template <class T>
  357. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
  358. Quat<T>::invert() IMATH_NOEXCEPT
  359. {
  360. T qdot = (*this) ^ (*this);
  361. r /= qdot;
  362. v = -v / qdot;
  363. return *this;
  364. }
  365. template <class T>
  366. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>
  367. Quat<T>::rotateVector (const Vec3<T>& original) const IMATH_NOEXCEPT
  368. {
  369. //
  370. // Given a vector p and a quaternion q (aka this),
  371. // calculate p' = qpq*
  372. //
  373. // Assumes unit quaternions (because non-unit
  374. // quaternions cannot be used to rotate vectors
  375. // anyway).
  376. //
  377. Quat<T> vec (0, original); // temporarily promote grade of original
  378. Quat<T> inv (*this);
  379. inv.v *= -1; // unit multiplicative inverse
  380. Quat<T> result = *this * vec * inv;
  381. return result.v;
  382. }
  383. template <class T>
  384. IMATH_HOSTDEVICE constexpr inline T
  385. Quat<T>::euclideanInnerProduct (const Quat<T>& q) const IMATH_NOEXCEPT
  386. {
  387. return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z;
  388. }
  389. ///
  390. /// Compute the angle between two quaternions,
  391. /// interpreting the quaternions as 4D vectors.
  392. template <class T>
  393. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
  394. angle4D (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  395. {
  396. Quat<T> d = q1 - q2;
  397. T lengthD = std::sqrt (d ^ d);
  398. Quat<T> s = q1 + q2;
  399. T lengthS = std::sqrt (s ^ s);
  400. return 2 * std::atan2 (lengthD, lengthS);
  401. }
  402. ///
  403. /// Spherical linear interpolation.
  404. /// Assumes q1 and q2 are normalized and that q1 != -q2.
  405. ///
  406. /// This method does *not* interpolate along the shortest
  407. /// arc between q1 and q2. If you desire interpolation
  408. /// along the shortest arc, and q1^q2 is negative, then
  409. /// consider calling slerpShortestArc(), below, or flipping
  410. /// the second quaternion explicitly.
  411. ///
  412. /// The implementation of squad() depends on a slerp()
  413. /// that interpolates as is, without the automatic
  414. /// flipping.
  415. ///
  416. /// Don Hatch explains the method we use here on his
  417. /// web page, The Right Way to Calculate Stuff, at
  418. /// http://www.plunk.org/~hatch/rightway.php
  419. template <class T>
  420. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  421. slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT
  422. {
  423. T a = angle4D (q1, q2);
  424. T s = 1 - t;
  425. Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
  426. sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
  427. return q.normalized();
  428. }
  429. ///
  430. /// Spherical linear interpolation along the shortest
  431. /// arc from q1 to either q2 or -q2, whichever is closer.
  432. /// Assumes q1 and q2 are unit quaternions.
  433. template <class T>
  434. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  435. slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT
  436. {
  437. if ((q1 ^ q2) >= 0)
  438. return slerp (q1, q2, t);
  439. else
  440. return slerp (q1, -q2, t);
  441. }
  442. ///
  443. /// Spherical Cubic Spline Interpolation - from Advanced Animation and
  444. /// Rendering Techniques by Watt and Watt, Page 366:
  445. ///
  446. /// A spherical curve is constructed using three spherical linear
  447. /// interpolations of a quadrangle of unit quaternions: q1, qa, qb,
  448. /// q2. Given a set of quaternion keys: q0, q1, q2, q3, this routine
  449. /// does the interpolation between q1 and q2 by constructing two
  450. /// intermediate quaternions: qa and qb. The qa and qb are computed by
  451. /// the intermediate function to guarantee the continuity of tangents
  452. /// across adjacent cubic segments. The qa represents in-tangent for
  453. /// q1 and the qb represents the out-tangent for q2.
  454. ///
  455. /// The q1 q2 is the cubic segment being interpolated.
  456. ///
  457. /// The q0 is from the previous adjacent segment and q3 is from the
  458. /// next adjacent segment. The q0 and q3 are used in computing qa and
  459. /// qb.
  460. template <class T>
  461. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  462. spline (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& q3, T t) IMATH_NOEXCEPT
  463. {
  464. Quat<T> qa = intermediate (q0, q1, q2);
  465. Quat<T> qb = intermediate (q1, q2, q3);
  466. Quat<T> result = squad (q1, qa, qb, q2, t);
  467. return result;
  468. }
  469. ///
  470. /// Spherical Quadrangle Interpolation - from Advanced Animation and
  471. /// Rendering Techniques by Watt and Watt, Page 366:
  472. ///
  473. /// It constructs a spherical cubic interpolation as a series of three
  474. /// spherical linear interpolations of a quadrangle of unit
  475. /// quaternions.
  476. template <class T>
  477. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  478. squad (const Quat<T>& q1, const Quat<T>& qa, const Quat<T>& qb, const Quat<T>& q2, T t) IMATH_NOEXCEPT
  479. {
  480. Quat<T> r1 = slerp (q1, q2, t);
  481. Quat<T> r2 = slerp (qa, qb, t);
  482. Quat<T> result = slerp (r1, r2, 2 * t * (1 - t));
  483. return result;
  484. }
  485. /// Compute the intermediate point between three quaternions `q0`, `q1`,
  486. /// and `q2`.
  487. template <class T>
  488. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
  489. intermediate (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  490. {
  491. Quat<T> q1inv = q1.inverse();
  492. Quat<T> c1 = q1inv * q2;
  493. Quat<T> c2 = q1inv * q0;
  494. Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
  495. Quat<T> qa = q1 * c3.exp();
  496. qa.normalize();
  497. return qa;
  498. }
  499. template <class T>
  500. IMATH_HOSTDEVICE inline Quat<T>
  501. Quat<T>::log() const IMATH_NOEXCEPT
  502. {
  503. //
  504. // For unit quaternion, from Advanced Animation and
  505. // Rendering Techniques by Watt and Watt, Page 366:
  506. //
  507. T theta = std::acos (std::min (r, (T) 1.0));
  508. if (theta == 0)
  509. return Quat<T> (0, v);
  510. T sintheta = std::sin (theta);
  511. T k;
  512. if (std::abs(sintheta) < 1 && std::abs(theta) >= std::numeric_limits<T>::max() * std::abs(sintheta))
  513. k = 1;
  514. else
  515. k = theta / sintheta;
  516. return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
  517. }
  518. template <class T>
  519. IMATH_HOSTDEVICE inline Quat<T>
  520. Quat<T>::exp() const IMATH_NOEXCEPT
  521. {
  522. //
  523. // For pure quaternion (zero scalar part):
  524. // from Advanced Animation and Rendering
  525. // Techniques by Watt and Watt, Page 366:
  526. //
  527. T theta = v.length();
  528. T sintheta = std::sin (theta);
  529. T k;
  530. if (abs (theta) < 1 && abs (sintheta) >= std::numeric_limits<T>::max() * abs (theta))
  531. k = 1;
  532. else
  533. k = sintheta / theta;
  534. T costheta = std::cos (theta);
  535. return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
  536. }
  537. template <class T>
  538. IMATH_HOSTDEVICE constexpr inline T
  539. Quat<T>::angle() const IMATH_NOEXCEPT
  540. {
  541. return 2 * std::atan2 (v.length(), r);
  542. }
  543. template <class T>
  544. IMATH_HOSTDEVICE constexpr inline Vec3<T>
  545. Quat<T>::axis() const IMATH_NOEXCEPT
  546. {
  547. return v.normalized();
  548. }
  549. template <class T>
  550. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
  551. Quat<T>::setAxisAngle (const Vec3<T>& axis, T radians) IMATH_NOEXCEPT
  552. {
  553. r = std::cos (radians / 2);
  554. v = axis.normalized() * std::sin (radians / 2);
  555. return *this;
  556. }
  557. template <class T>
  558. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
  559. Quat<T>::setRotation (const Vec3<T>& from, const Vec3<T>& to) IMATH_NOEXCEPT
  560. {
  561. //
  562. // Create a quaternion that rotates vector from into vector to,
  563. // such that the rotation is around an axis that is the cross
  564. // product of from and to.
  565. //
  566. // This function calls function setRotationInternal(), which is
  567. // numerically accurate only for rotation angles that are not much
  568. // greater than pi/2. In order to achieve good accuracy for angles
  569. // greater than pi/2, we split large angles in half, and rotate in
  570. // two steps.
  571. //
  572. //
  573. // Normalize from and to, yielding f0 and t0.
  574. //
  575. Vec3<T> f0 = from.normalized();
  576. Vec3<T> t0 = to.normalized();
  577. if ((f0 ^ t0) >= 0)
  578. {
  579. //
  580. // The rotation angle is less than or equal to pi/2.
  581. //
  582. setRotationInternal (f0, t0, *this);
  583. }
  584. else
  585. {
  586. //
  587. // The angle is greater than pi/2. After computing h0,
  588. // which is halfway between f0 and t0, we rotate first
  589. // from f0 to h0, then from h0 to t0.
  590. //
  591. Vec3<T> h0 = (f0 + t0).normalized();
  592. if ((h0 ^ h0) != 0)
  593. {
  594. setRotationInternal (f0, h0, *this);
  595. Quat<T> q;
  596. setRotationInternal (h0, t0, q);
  597. *this *= q;
  598. }
  599. else
  600. {
  601. //
  602. // f0 and t0 point in exactly opposite directions.
  603. // Pick an arbitrary axis that is orthogonal to f0,
  604. // and rotate by pi.
  605. //
  606. r = T (0);
  607. Vec3<T> f02 = f0 * f0;
  608. if (f02.x <= f02.y && f02.x <= f02.z)
  609. v = (f0 % Vec3<T> (1, 0, 0)).normalized();
  610. else if (f02.y <= f02.z)
  611. v = (f0 % Vec3<T> (0, 1, 0)).normalized();
  612. else
  613. v = (f0 % Vec3<T> (0, 0, 1)).normalized();
  614. }
  615. }
  616. return *this;
  617. }
  618. template <class T>
  619. IMATH_HOSTDEVICE inline void
  620. Quat<T>::setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) IMATH_NOEXCEPT
  621. {
  622. //
  623. // The following is equivalent to setAxisAngle(n,2*phi),
  624. // where the rotation axis, n, is orthogonal to the f0 and
  625. // t0 vectors, and 2*phi is the angle between f0 and t0.
  626. //
  627. // This function is called by setRotation(), above; it assumes
  628. // that f0 and t0 are normalized and that the angle between
  629. // them is not much greater than pi/2. This function becomes
  630. // numerically inaccurate if f0 and t0 point into nearly
  631. // opposite directions.
  632. //
  633. //
  634. // Find a normalized vector, h0, that is halfway between f0 and t0.
  635. // The angle between f0 and h0 is phi.
  636. //
  637. Vec3<T> h0 = (f0 + t0).normalized();
  638. //
  639. // Store the rotation axis and rotation angle.
  640. //
  641. q.r = f0 ^ h0; // f0 ^ h0 == cos (phi)
  642. q.v = f0 % h0; // (f0 % h0).length() == sin (phi)
  643. }
  644. template <class T>
  645. IMATH_HOSTDEVICE constexpr inline Matrix33<T>
  646. Quat<T>::toMatrix33() const IMATH_NOEXCEPT
  647. {
  648. return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z),
  649. 2 * (v.x * v.y + v.z * r),
  650. 2 * (v.z * v.x - v.y * r),
  651. 2 * (v.x * v.y - v.z * r),
  652. 1 - 2 * (v.z * v.z + v.x * v.x),
  653. 2 * (v.y * v.z + v.x * r),
  654. 2 * (v.z * v.x + v.y * r),
  655. 2 * (v.y * v.z - v.x * r),
  656. 1 - 2 * (v.y * v.y + v.x * v.x));
  657. }
  658. template <class T>
  659. IMATH_HOSTDEVICE constexpr inline Matrix44<T>
  660. Quat<T>::toMatrix44() const IMATH_NOEXCEPT
  661. {
  662. return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z),
  663. 2 * (v.x * v.y + v.z * r),
  664. 2 * (v.z * v.x - v.y * r),
  665. 0,
  666. 2 * (v.x * v.y - v.z * r),
  667. 1 - 2 * (v.z * v.z + v.x * v.x),
  668. 2 * (v.y * v.z + v.x * r),
  669. 0,
  670. 2 * (v.z * v.x + v.y * r),
  671. 2 * (v.y * v.z - v.x * r),
  672. 1 - 2 * (v.y * v.y + v.x * v.x),
  673. 0,
  674. 0,
  675. 0,
  676. 0,
  677. 1);
  678. }
  679. /// Transform the quaternion by the matrix
  680. /// @return M * q
  681. template <class T>
  682. IMATH_HOSTDEVICE constexpr inline Matrix33<T>
  683. operator* (const Matrix33<T>& M, const Quat<T>& q) IMATH_NOEXCEPT
  684. {
  685. return M * q.toMatrix33();
  686. }
  687. /// Transform the matrix by the quaterion:
  688. /// @return q * M
  689. template <class T>
  690. IMATH_HOSTDEVICE constexpr inline Matrix33<T>
  691. operator* (const Quat<T>& q, const Matrix33<T>& M) IMATH_NOEXCEPT
  692. {
  693. return q.toMatrix33() * M;
  694. }
  695. /// Stream output as "(r x y z)"
  696. template <class T>
  697. std::ostream&
  698. operator<< (std::ostream& o, const Quat<T>& q)
  699. {
  700. return o << "(" << q.r << " " << q.v.x << " " << q.v.y << " " << q.v.z << ")";
  701. }
  702. /// Quaterion multiplication
  703. template <class T>
  704. IMATH_HOSTDEVICE constexpr inline Quat<T>
  705. operator* (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  706. {
  707. return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v), q1.r * q2.v + q1.v * q2.r + q1.v % q2.v);
  708. }
  709. /// Quaterion division
  710. template <class T>
  711. IMATH_HOSTDEVICE constexpr inline Quat<T>
  712. operator/ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  713. {
  714. return q1 * q2.inverse();
  715. }
  716. /// Quaterion division
  717. template <class T>
  718. IMATH_HOSTDEVICE constexpr inline Quat<T>
  719. operator/ (const Quat<T>& q, T t) IMATH_NOEXCEPT
  720. {
  721. return Quat<T> (q.r / t, q.v / t);
  722. }
  723. /// Quaterion*scalar multiplication
  724. /// @return q * t
  725. template <class T>
  726. IMATH_HOSTDEVICE constexpr inline Quat<T>
  727. operator* (const Quat<T>& q, T t) IMATH_NOEXCEPT
  728. {
  729. return Quat<T> (q.r * t, q.v * t);
  730. }
  731. /// Quaterion*scalar multiplication
  732. /// @return q * t
  733. template <class T>
  734. IMATH_HOSTDEVICE constexpr inline Quat<T>
  735. operator* (T t, const Quat<T>& q) IMATH_NOEXCEPT
  736. {
  737. return Quat<T> (q.r * t, q.v * t);
  738. }
  739. /// Quaterion addition
  740. template <class T>
  741. IMATH_HOSTDEVICE constexpr inline Quat<T>
  742. operator+ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  743. {
  744. return Quat<T> (q1.r + q2.r, q1.v + q2.v);
  745. }
  746. /// Quaterion subtraction
  747. template <class T>
  748. IMATH_HOSTDEVICE constexpr inline Quat<T>
  749. operator- (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
  750. {
  751. return Quat<T> (q1.r - q2.r, q1.v - q2.v);
  752. }
  753. /// Compute the conjugate
  754. template <class T>
  755. IMATH_HOSTDEVICE constexpr inline Quat<T>
  756. operator~ (const Quat<T>& q) IMATH_NOEXCEPT
  757. {
  758. return Quat<T> (q.r, -q.v);
  759. }
  760. /// Negate the quaterion
  761. template <class T>
  762. IMATH_HOSTDEVICE constexpr inline Quat<T>
  763. operator- (const Quat<T>& q) IMATH_NOEXCEPT
  764. {
  765. return Quat<T> (-q.r, -q.v);
  766. }
  767. /// Quaterion*vector multiplcation
  768. /// @return v * q
  769. template <class T>
  770. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>
  771. operator* (const Vec3<T>& v, const Quat<T>& q) IMATH_NOEXCEPT
  772. {
  773. Vec3<T> a = q.v % v;
  774. Vec3<T> b = q.v % a;
  775. return v + T (2) * (q.r * a + b);
  776. }
  777. #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
  778. # pragma warning(pop)
  779. #endif
  780. IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
  781. #endif // INCLUDED_IMATHQUAT_H