llquaternion.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /**
  2. * @file llquaternion.h
  3. * @brief LLQuaternion class header file.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewergpl$
  6. *
  7. * Copyright (c) 2000-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LLQUATERNION_H
  33. #define LLQUATERNION_H
  34. #include <iostream>
  35. #include "llmath.h"
  36. #include "llsd.h"
  37. class LLMatrix3;
  38. class LLMatrix4;
  39. class LLVector3;
  40. class LLVector3d;
  41. class LLVector4;
  42. // IMPORTANT: LLQuaternion code is written assuming *unit* quaternions !
  43. // Moreover, it is written assuming that all vectors and matricies
  44. // passed as arguments are normalized and unitary respectively.
  45. // VERY VERY VERY BAD THINGS will happen if these assumptions fail.
  46. constexpr U32 LENGTHOFQUAT = 4;
  47. class LLQuaternion
  48. {
  49. public:
  50. LL_INLINE LLQuaternion() noexcept
  51. {
  52. mQ[VX] = mQ[VY] = mQ[VZ] = 0.f;
  53. mQ[VS] = 1.f;
  54. }
  55. // Initializes Quaternion to (x, y, z, w).
  56. // Note: we do not normalize this case as it is used mainly for temporaries
  57. // during calculations
  58. LL_INLINE LLQuaternion(F32 x, F32 y, F32 z, F32 w) noexcept
  59. {
  60. mQ[VX] = x;
  61. mQ[VY] = y;
  62. mQ[VZ] = z;
  63. mQ[VS] = w;
  64. }
  65. // Initializes Quaternion to normalize(x, y, z, w)
  66. LL_INLINE LLQuaternion(const F32* q) noexcept
  67. {
  68. mQ[VX] = q[VX];
  69. mQ[VY] = q[VY];
  70. mQ[VZ] = q[VZ];
  71. mQ[VS] = q[VW];
  72. normalize();
  73. }
  74. // Initializes Quaternion to axis_angle2quat(angle, vec)
  75. LLQuaternion(F32 angle, const LLVector4& vec) noexcept;
  76. // Initializes Quaternion to axis_angle2quat(angle, vec)
  77. LLQuaternion(F32 angle, const LLVector3& vec) noexcept;
  78. // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis]
  79. LLQuaternion(const LLVector3& x_axis, const LLVector3& y_axis,
  80. const LLVector3& z_axis) noexcept;
  81. explicit LLQuaternion(const LLMatrix4& mat) noexcept;
  82. explicit LLQuaternion(const LLMatrix3& mat) noexcept;
  83. explicit LLQuaternion(const LLSD& sd);
  84. // Allow the use of the default C++11 move constructor and assignation
  85. LLQuaternion(LLQuaternion&& other) noexcept = default;
  86. LLQuaternion& operator=(LLQuaternion&& other) noexcept = default;
  87. LLQuaternion(const LLQuaternion& other) = default;
  88. LLQuaternion& operator=(const LLQuaternion& other) = default;
  89. LL_INLINE void setValue(const LLSD& sd)
  90. {
  91. mQ[0] = sd[0].asReal();
  92. mQ[1] = sd[1].asReal();
  93. mQ[2] = sd[2].asReal();
  94. mQ[3] = sd[3].asReal();
  95. }
  96. LL_INLINE LLSD getValue() const
  97. {
  98. LLSD ret;
  99. ret[0] = mQ[0];
  100. ret[1] = mQ[1];
  101. ret[2] = mQ[2];
  102. ret[3] = mQ[3];
  103. return ret;
  104. }
  105. LL_INLINE bool isIdentity() const
  106. {
  107. return mQ[VX] == 0.f && mQ[VY] == 0.f && mQ[VZ] == 0.f &&
  108. mQ[VS] == 1.f;
  109. }
  110. LL_INLINE bool isNotIdentity() const
  111. {
  112. return mQ[VX] != 0.f || mQ[VY] != 0.f || mQ[VZ] != 0.f ||
  113. mQ[VS] != 1.f;
  114. }
  115. // Checks to see if all values of LLQuaternion are finite
  116. LL_INLINE bool isFinite() const
  117. {
  118. return llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) &&
  119. llfinite(mQ[VS]);
  120. }
  121. // Changes the vector to reflect quatization
  122. void quantize16(F32 lower, F32 upper);
  123. // Changes the vector to reflect quatization
  124. void quantize8(F32 lower, F32 upper);
  125. // Loads the quaternion that represents the identity rotation
  126. LL_INLINE void loadIdentity()
  127. {
  128. mQ[VX] = mQ[VY] = mQ[VZ] = 0.f;
  129. mQ[VW] = 1.f;
  130. }
  131. bool isEqualEps(const LLQuaternion& quat, F32 epsilon) const;
  132. bool isNotEqualEps(const LLQuaternion& quat, F32 epsilon) const;
  133. // Sets Quaternion without normalizing. HB
  134. const LLQuaternion& setRaw(const F32* q);
  135. // Sets Quaternion to normalize(x, y, z, w)
  136. const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w);
  137. // Copies Quaternion
  138. const LLQuaternion& set(const LLQuaternion& quat);
  139. // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW])
  140. const LLQuaternion& set(const F32* q);
  141. const LLQuaternion& set(const LLMatrix3& mat);
  142. const LLQuaternion& set(const LLMatrix4& mat);
  143. // Sets from azimuth and altitude in radians
  144. const LLQuaternion& setFromAzimuthAndAltitude(F32 azimuth, F32 altitude);
  145. // Sets Quaternion to axis_angle2quat(angle, x, y, z)
  146. const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z);
  147. // Sets Quaternion to axis_angle2quat(angle, vec)
  148. const LLQuaternion& setAngleAxis(F32 angle, const LLVector3& vec);
  149. // Sets Quaternion to axis_angle2quat(angle, vec)
  150. const LLQuaternion& setAngleAxis(F32 angle, const LLVector4& vec);
  151. // Sets Quaternion to euler2quat(pitch, yaw, roll)
  152. const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw);
  153. // Returns the Matrix4 equivalent of Quaternion
  154. LLMatrix4 getMatrix4() const;
  155. // Returns the Matrix3 equivalent of Quaternion
  156. LLMatrix3 getMatrix3() const;
  157. // Returns rotation in radians about axis x,y,z
  158. void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const;
  159. void getAngleAxis(F32* angle, LLVector3& vec) const;
  160. void getEulerAngles(F32* roll, F32* pitch, F32* yaw) const;
  161. void getAzimuthAndAltitude(F32& azimuth, F32& altitude);
  162. void getAzimuthAndElevation(F32& azimuth, F32& elevation);
  163. // Normalizes Quaternion and returns magnitude
  164. F32 normalize();
  165. // Transpose (AKA conjugate)
  166. const LLQuaternion& transpose();
  167. // Other useful methods
  168. // Shortest rotation from a to b
  169. void shortestArc(const LLVector3& a, const LLVector3& b);
  170. // Constrains rotation to a cone angle specified in radians
  171. const LLQuaternion& constrain(F32 radians);
  172. // Standard operators
  173. friend std::ostream& operator<<(std::ostream& s, const LLQuaternion& a);
  174. friend LLQuaternion operator+(const LLQuaternion& a,
  175. const LLQuaternion& b);
  176. friend LLQuaternion operator-(const LLQuaternion& a,
  177. const LLQuaternion& b);
  178. friend LLQuaternion operator-(const LLQuaternion& a); // Negation
  179. friend LLQuaternion operator*(F32 a, const LLQuaternion& q); // Scale
  180. friend LLQuaternion operator*(const LLQuaternion& q, F32 b); // Scale
  181. friend LLQuaternion operator*(const LLQuaternion& a,
  182. const LLQuaternion& b);
  183. // Returns a* (transposed/conjugate of a):
  184. friend LLQuaternion operator~(const LLQuaternion& a);
  185. bool operator==(const LLQuaternion& b) const;
  186. bool operator!=(const LLQuaternion& b) const;
  187. LL_INLINE F64 operator[](int idx) const { return mQ[idx]; }
  188. friend const LLQuaternion& operator*=(LLQuaternion& a,
  189. const LLQuaternion& b);
  190. // Rotations of a by rot
  191. friend LLVector4 operator*(const LLVector4& a, const LLQuaternion& rot);
  192. friend LLVector3 operator*(const LLVector3& a, const LLQuaternion& rot);
  193. friend LLVector3d operator*(const LLVector3d& a, const LLQuaternion& rot);
  194. // Non-standard operators
  195. friend F32 dot(const LLQuaternion& a, const LLQuaternion& b);
  196. // Linear interpolation (t = 0 to 1) from p to q
  197. friend LLQuaternion lerp(F32 t, const LLQuaternion& p,
  198. const LLQuaternion& q);
  199. // Linear interpolation (t = 0 to 1) from identity to q
  200. friend LLQuaternion lerp(F32 t, const LLQuaternion& q);
  201. // Spherical linear interpolation from p to q
  202. friend LLQuaternion slerp(F32 t, const LLQuaternion& p,
  203. const LLQuaternion& q);
  204. // Spherical linear interpolation from identity to q
  205. friend LLQuaternion slerp(F32 t, const LLQuaternion& q);
  206. // Normalized linear interpolation from p to q
  207. friend LLQuaternion nlerp(F32 t, const LLQuaternion& p,
  208. const LLQuaternion& q);
  209. // Normalized linear interpolation from p to q
  210. friend LLQuaternion nlerp(F32 t, const LLQuaternion& q);
  211. // These two methods save space by using the fact that our quaternions are
  212. // normalized:
  213. LLVector3 packToVector3() const;
  214. void unpackFromVector3(const LLVector3& vec);
  215. enum Order {
  216. XYZ = 0,
  217. YZX = 1,
  218. ZXY = 2,
  219. XZY = 3,
  220. YXZ = 4,
  221. ZYX = 5
  222. };
  223. // Creates a quaternions from Maya's rotation representation, which is 3
  224. // rotations (in DEGREES) in the specified order
  225. friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order);
  226. // Conversions between Order and strings like "xyz" or "ZYX"
  227. friend const char* OrderToString(const Order order);
  228. friend Order StringToOrder(const char* str);
  229. static bool parseQuat(const std::string& buf, LLQuaternion* value);
  230. // Note 1: 1.0e-3f radians corresponds to about 0.0573 degrees
  231. // Note 2: this only works for well-normalized quaternions.
  232. static bool almost_equal(const LLQuaternion& a, const LLQuaternion& b,
  233. F32 tolerance_angle = 1.0e-3f);
  234. public:
  235. F32 mQ[LENGTHOFQUAT];
  236. static const LLQuaternion DEFAULT;
  237. };
  238. LL_INLINE bool LLQuaternion::isEqualEps(const LLQuaternion& quat,
  239. F32 epsilon) const
  240. {
  241. return fabsf(mQ[VX] - quat.mQ[VX]) <= epsilon &&
  242. fabsf(mQ[VY] - quat.mQ[VY]) <= epsilon &&
  243. fabsf(mQ[VZ] - quat.mQ[VZ]) <= epsilon &&
  244. fabsf(mQ[VS] - quat.mQ[VS]) <= epsilon;
  245. }
  246. LL_INLINE bool LLQuaternion::isNotEqualEps(const LLQuaternion& quat,
  247. F32 epsilon) const
  248. {
  249. return fabsf(mQ[VX] - quat.mQ[VX]) > epsilon ||
  250. fabsf(mQ[VY] - quat.mQ[VY]) > epsilon ||
  251. fabsf(mQ[VZ] - quat.mQ[VZ]) > epsilon ||
  252. fabsf(mQ[VS] - quat.mQ[VS]) > epsilon;
  253. }
  254. LL_INLINE const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w)
  255. {
  256. mQ[VX] = x;
  257. mQ[VY] = y;
  258. mQ[VZ] = z;
  259. mQ[VS] = w;
  260. normalize();
  261. return *this;
  262. }
  263. LL_INLINE const LLQuaternion& LLQuaternion::set(const LLQuaternion& quat)
  264. {
  265. mQ[VX] = quat.mQ[VX];
  266. mQ[VY] = quat.mQ[VY];
  267. mQ[VZ] = quat.mQ[VZ];
  268. mQ[VW] = quat.mQ[VW];
  269. normalize();
  270. return *this;
  271. }
  272. LL_INLINE const LLQuaternion& LLQuaternion::set(const F32* q)
  273. {
  274. mQ[VX] = q[VX];
  275. mQ[VY] = q[VY];
  276. mQ[VZ] = q[VZ];
  277. mQ[VS] = q[VW];
  278. normalize();
  279. return *this;
  280. }
  281. LL_INLINE const LLQuaternion& LLQuaternion::setRaw(const F32* q)
  282. {
  283. mQ[VX] = q[VX];
  284. mQ[VY] = q[VY];
  285. mQ[VZ] = q[VZ];
  286. mQ[VS] = q[VW];
  287. return *this;
  288. }
  289. LL_INLINE void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
  290. {
  291. // length of the vector-component
  292. F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]);
  293. if (v > FP_MAG_THRESHOLD)
  294. {
  295. F32 oomag = 1.f / v;
  296. F32 w = mQ[VW];
  297. if (w < 0.f)
  298. {
  299. w = -w; // make VW positive
  300. oomag = -oomag; // invert the axis
  301. }
  302. *x = mQ[VX] * oomag; // normalize the axis
  303. *y = mQ[VY] * oomag;
  304. *z = mQ[VZ] * oomag;
  305. *angle = 2.f * atan2f(v, w); // get the angle
  306. }
  307. else
  308. {
  309. *angle = 0.f; // no rotation
  310. *x = 0.f; // around some dummy axis
  311. *y = 0.f;
  312. *z = 1.f;
  313. }
  314. }
  315. // Transpose
  316. LL_INLINE const LLQuaternion& LLQuaternion::transpose()
  317. {
  318. mQ[VX] *= -1.f;
  319. mQ[VY] *= -1.f;
  320. mQ[VZ] *= -1.f;
  321. return *this;
  322. }
  323. LL_INLINE LLQuaternion operator+(const LLQuaternion& a, const LLQuaternion& b)
  324. {
  325. return LLQuaternion(a.mQ[VX] + b.mQ[VX], a.mQ[VY] + b.mQ[VY],
  326. a.mQ[VZ] + b.mQ[VZ], a.mQ[VW] + b.mQ[VW]);
  327. }
  328. LL_INLINE LLQuaternion operator-(const LLQuaternion& a, const LLQuaternion& b)
  329. {
  330. return LLQuaternion(a.mQ[VX] - b.mQ[VX], a.mQ[VY] - b.mQ[VY],
  331. a.mQ[VZ] - b.mQ[VZ], a.mQ[VW] - b.mQ[VW]);
  332. }
  333. LL_INLINE LLQuaternion operator-(const LLQuaternion& a)
  334. {
  335. return LLQuaternion(-a.mQ[VX], -a.mQ[VY], -a.mQ[VZ], -a.mQ[VW]);
  336. }
  337. LL_INLINE LLQuaternion operator*(F32 a, const LLQuaternion& q)
  338. {
  339. return LLQuaternion(a * q.mQ[VX], a * q.mQ[VY], a * q.mQ[VZ],
  340. a * q.mQ[VW]);
  341. }
  342. LL_INLINE LLQuaternion operator*(const LLQuaternion& q, F32 a)
  343. {
  344. return LLQuaternion(a * q.mQ[VX], a * q.mQ[VY], a * q.mQ[VZ],
  345. a * q.mQ[VW]);
  346. }
  347. LL_INLINE LLQuaternion operator~(const LLQuaternion& a)
  348. {
  349. LLQuaternion q(a);
  350. q.transpose();
  351. return q;
  352. }
  353. LL_INLINE bool LLQuaternion::operator==(const LLQuaternion& b) const
  354. {
  355. return mQ[VX] == b.mQ[VX] && mQ[VY] == b.mQ[VY] && mQ[VZ] == b.mQ[VZ] &&
  356. mQ[VS] == b.mQ[VS];
  357. }
  358. LL_INLINE bool LLQuaternion::operator!=(const LLQuaternion& b) const
  359. {
  360. return mQ[VX] != b.mQ[VX] || mQ[VY] != b.mQ[VY] || mQ[VZ] != b.mQ[VZ] ||
  361. mQ[VS] != b.mQ[VS];
  362. }
  363. LL_INLINE const LLQuaternion& operator*=(LLQuaternion& a, const LLQuaternion& b)
  364. {
  365. #if 1
  366. LLQuaternion q(b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] +
  367. b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
  368. b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] +
  369. b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
  370. b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] +
  371. b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
  372. b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] -
  373. b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]);
  374. a = q;
  375. #else
  376. a = a * b;
  377. #endif
  378. return a;
  379. }
  380. constexpr F32 ONE_PART_IN_A_MILLION = 0.000001f;
  381. LL_INLINE F32 LLQuaternion::normalize()
  382. {
  383. F32 mag = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ] +
  384. mQ[VS] * mQ[VS]);
  385. if (mag > FP_MAG_THRESHOLD)
  386. {
  387. // Floating point error can prevent some quaternions from achieving
  388. // exact unity length. When trying to renormalize such quaternions we
  389. // can oscillate between multiple quantized states. To prevent such
  390. // drifts we only renomalize if the length is far enough from unity.
  391. if (fabsf(1.f - mag) > ONE_PART_IN_A_MILLION)
  392. {
  393. F32 oomag = 1.f / mag;
  394. mQ[VX] *= oomag;
  395. mQ[VY] *= oomag;
  396. mQ[VZ] *= oomag;
  397. mQ[VS] *= oomag;
  398. }
  399. }
  400. else
  401. {
  402. // We were given a very bad quaternion so we set it to identity
  403. mQ[VX] = mQ[VY] = mQ[VZ] = 0.f;
  404. mQ[VS] = 1.f;
  405. }
  406. return mag;
  407. }
  408. LLQuaternion::Order StringToOrder(const char* str);
  409. // Some notes about Quaternions
  410. // What is a Quaternion?
  411. // ---------------------
  412. // A quaternion is a point in 4-dimensional complex space.
  413. // Q = { Qx, Qy, Qz, Qw }
  414. //
  415. //
  416. // Why Quaternions ?
  417. // -----------------
  418. // The set of quaternions that make up the the 4-D unit sphere can be mapped to
  419. // the set of all rotations in 3-D space. Sometimes it is easier to describe or
  420. // manipulate rotations in quaternion space than rotation-matrix space.
  421. //
  422. //
  423. // How Quaternions ?
  424. // -----------------
  425. // In order to take advantage of quaternions we need to know how to go from
  426. // rotation-matricies to quaternions and back. We also have to agree what
  427. // variety of rotations we are generating.
  428. //
  429. // Consider the equation... v' = v * R
  430. //
  431. // There are two ways to think about rotations of vectors:
  432. // 1) v' is the same vector in a different reference frame
  433. // 2) v' is a new vector in the same reference frame
  434. //
  435. // bookmark -- which way are we using?
  436. //
  437. //
  438. // Quaternion from Angle-Axis:
  439. // ---------------------------
  440. // Suppose we wanted to represent a rotation of some angle (theta) about some
  441. // axis ({Ax, Ay, Az})...
  442. //
  443. // axis of rotation = {Ax, Ay, Az}
  444. // angle_of_rotation = theta
  445. //
  446. // s = sinf(0.5 * theta)
  447. // c = cosf(0.5 * theta)
  448. // Q = { s * Ax, s * Ay, s * Az, c }
  449. //
  450. //
  451. // 3x3 Matrix from Quaternion
  452. // --------------------------
  453. //
  454. // | |
  455. // | 1 - 2 * (y^2 + z^2) 2 * (x * y + z * w) 2 * (y * w - x * z) |
  456. // | |
  457. // M = | 2 * (x * y - z * w) 1 - 2 * (x^2 + z^2) 2 * (y * z + x * w) |
  458. // | |
  459. // | 2 * (x * z + y * w) 2 * (y * z - x * w) 1 - 2 * (x^2 + y^2) |
  460. // | |
  461. #endif