PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llmath/llquaternion.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 588 lines | 381 code | 80 blank | 127 comment | 27 complexity | 2901803c13d86b8f3acf0c3a76f5b305 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llquaternion.h
  3. * @brief LLQuaternion class header file.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LLQUATERNION_H
  27. #define LLQUATERNION_H
  28. #include <iostream>
  29. #ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies
  30. #error "Please include llmath.h first."
  31. #endif
  32. class LLVector4;
  33. class LLVector3;
  34. class LLVector3d;
  35. class LLMatrix4;
  36. class LLMatrix3;
  37. // NOTA BENE: Quaternion code is written assuming Unit Quaternions!!!!
  38. // Moreover, it is written assuming that all vectors and matricies
  39. // passed as arguments are normalized and unitary respectively.
  40. // VERY VERY VERY VERY BAD THINGS will happen if these assumptions fail.
  41. static const U32 LENGTHOFQUAT = 4;
  42. class LLQuaternion
  43. {
  44. public:
  45. F32 mQ[LENGTHOFQUAT];
  46. static const LLQuaternion DEFAULT;
  47. LLQuaternion(); // Initializes Quaternion to (0,0,0,1)
  48. explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4
  49. explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3
  50. LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w)
  51. LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec)
  52. LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec)
  53. LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w)
  54. LLQuaternion(const LLVector3 &x_axis,
  55. const LLVector3 &y_axis,
  56. const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis]
  57. BOOL isIdentity() const;
  58. BOOL isNotIdentity() const;
  59. BOOL isFinite() const; // checks to see if all values of LLQuaternion are finite
  60. void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization
  61. void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization
  62. void loadIdentity(); // Loads the quaternion that represents the identity rotation
  63. const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w)
  64. const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion
  65. const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW])
  66. const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat)
  67. const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat)
  68. const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z)
  69. const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
  70. const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
  71. const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll)
  72. const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated
  73. const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated
  74. const LLQuaternion& setQuat(const F32 *q); // deprecated
  75. const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated
  76. const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated
  77. const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated
  78. const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated
  79. const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated
  80. const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated
  81. LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion
  82. LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion
  83. void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z
  84. void getAngleAxis(F32* angle, LLVector3 &vec) const;
  85. void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const;
  86. F32 normalize(); // Normalizes Quaternion and returns magnitude
  87. F32 normQuat(); // deprecated
  88. const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result
  89. const LLQuaternion& conjQuat(void); // deprecated
  90. // Other useful methods
  91. const LLQuaternion& transpose(); // transpose (same as conjugate)
  92. const LLQuaternion& transQuat(); // deprecated
  93. void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b
  94. const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians
  95. // Standard operators
  96. friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a); // Prints a
  97. friend LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b); // Addition
  98. friend LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b); // Subtraction
  99. friend LLQuaternion operator-(const LLQuaternion &a); // Negation
  100. friend LLQuaternion operator*(F32 a, const LLQuaternion &q); // Scale
  101. friend LLQuaternion operator*(const LLQuaternion &q, F32 b); // Scale
  102. friend LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b); // Returns a * b
  103. friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a)
  104. bool operator==(const LLQuaternion &b) const; // Returns a == b
  105. bool operator!=(const LLQuaternion &b) const; // Returns a != b
  106. friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b
  107. friend LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot); // Rotates a by rot
  108. friend LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot); // Rotates a by rot
  109. friend LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot); // Rotates a by rot
  110. // Non-standard operators
  111. friend F32 dot(const LLQuaternion &a, const LLQuaternion &b);
  112. friend LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from p to q
  113. friend LLQuaternion lerp(F32 t, const LLQuaternion &q); // linear interpolation (t = 0 to 1) from identity to q
  114. friend LLQuaternion slerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // spherical linear interpolation from p to q
  115. friend LLQuaternion slerp(F32 t, const LLQuaternion &q); // spherical linear interpolation from identity to q
  116. friend LLQuaternion nlerp(F32 t, const LLQuaternion &p, const LLQuaternion &q); // normalized linear interpolation from p to q
  117. friend LLQuaternion nlerp(F32 t, const LLQuaternion &q); // normalized linear interpolation from p to q
  118. LLVector3 packToVector3() const; // Saves space by using the fact that our quaternions are normalized
  119. void unpackFromVector3(const LLVector3& vec); // Saves space by using the fact that our quaternions are normalized
  120. enum Order {
  121. XYZ = 0,
  122. YZX = 1,
  123. ZXY = 2,
  124. XZY = 3,
  125. YXZ = 4,
  126. ZYX = 5
  127. };
  128. // Creates a quaternions from maya's rotation representation,
  129. // which is 3 rotations (in DEGREES) in the specified order
  130. friend LLQuaternion mayaQ(F32 x, F32 y, F32 z, Order order);
  131. // Conversions between Order and strings like "xyz" or "ZYX"
  132. friend const char *OrderToString( const Order order );
  133. friend Order StringToOrder( const char *str );
  134. static BOOL parseQuat(const std::string& buf, LLQuaternion* value);
  135. // For debugging, only
  136. //static U32 mMultCount;
  137. };
  138. // checker
  139. inline BOOL LLQuaternion::isFinite() const
  140. {
  141. return (llfinite(mQ[VX]) && llfinite(mQ[VY]) && llfinite(mQ[VZ]) && llfinite(mQ[VS]));
  142. }
  143. inline BOOL LLQuaternion::isIdentity() const
  144. {
  145. return
  146. ( mQ[VX] == 0.f ) &&
  147. ( mQ[VY] == 0.f ) &&
  148. ( mQ[VZ] == 0.f ) &&
  149. ( mQ[VS] == 1.f );
  150. }
  151. inline BOOL LLQuaternion::isNotIdentity() const
  152. {
  153. return
  154. ( mQ[VX] != 0.f ) ||
  155. ( mQ[VY] != 0.f ) ||
  156. ( mQ[VZ] != 0.f ) ||
  157. ( mQ[VS] != 1.f );
  158. }
  159. inline LLQuaternion::LLQuaternion(void)
  160. {
  161. mQ[VX] = 0.f;
  162. mQ[VY] = 0.f;
  163. mQ[VZ] = 0.f;
  164. mQ[VS] = 1.f;
  165. }
  166. inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w)
  167. {
  168. mQ[VX] = x;
  169. mQ[VY] = y;
  170. mQ[VZ] = z;
  171. mQ[VS] = w;
  172. //RN: don't normalize this case as its used mainly for temporaries during calculations
  173. //normalize();
  174. /*
  175. F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
  176. mag -= 1.f;
  177. mag = fabs(mag);
  178. llassert(mag < 10.f*FP_MAG_THRESHOLD);
  179. */
  180. }
  181. inline LLQuaternion::LLQuaternion(const F32 *q)
  182. {
  183. mQ[VX] = q[VX];
  184. mQ[VY] = q[VY];
  185. mQ[VZ] = q[VZ];
  186. mQ[VS] = q[VW];
  187. normalize();
  188. /*
  189. F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
  190. mag -= 1.f;
  191. mag = fabs(mag);
  192. llassert(mag < FP_MAG_THRESHOLD);
  193. */
  194. }
  195. inline void LLQuaternion::loadIdentity()
  196. {
  197. mQ[VX] = 0.0f;
  198. mQ[VY] = 0.0f;
  199. mQ[VZ] = 0.0f;
  200. mQ[VW] = 1.0f;
  201. }
  202. inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w)
  203. {
  204. mQ[VX] = x;
  205. mQ[VY] = y;
  206. mQ[VZ] = z;
  207. mQ[VS] = w;
  208. normalize();
  209. return (*this);
  210. }
  211. inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat)
  212. {
  213. mQ[VX] = quat.mQ[VX];
  214. mQ[VY] = quat.mQ[VY];
  215. mQ[VZ] = quat.mQ[VZ];
  216. mQ[VW] = quat.mQ[VW];
  217. normalize();
  218. return (*this);
  219. }
  220. inline const LLQuaternion& LLQuaternion::set(const F32 *q)
  221. {
  222. mQ[VX] = q[VX];
  223. mQ[VY] = q[VY];
  224. mQ[VZ] = q[VZ];
  225. mQ[VS] = q[VW];
  226. normalize();
  227. return (*this);
  228. }
  229. // deprecated
  230. inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w)
  231. {
  232. mQ[VX] = x;
  233. mQ[VY] = y;
  234. mQ[VZ] = z;
  235. mQ[VS] = w;
  236. normalize();
  237. return (*this);
  238. }
  239. // deprecated
  240. inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat)
  241. {
  242. mQ[VX] = quat.mQ[VX];
  243. mQ[VY] = quat.mQ[VY];
  244. mQ[VZ] = quat.mQ[VZ];
  245. mQ[VW] = quat.mQ[VW];
  246. normalize();
  247. return (*this);
  248. }
  249. // deprecated
  250. inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q)
  251. {
  252. mQ[VX] = q[VX];
  253. mQ[VY] = q[VY];
  254. mQ[VZ] = q[VZ];
  255. mQ[VS] = q[VW];
  256. normalize();
  257. return (*this);
  258. }
  259. // There may be a cheaper way that avoids the sqrt.
  260. // Does sin_a = VX*VX + VY*VY + VZ*VZ?
  261. // Copied from Matrix and Quaternion FAQ 1.12
  262. inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
  263. {
  264. F32 cos_a = mQ[VW];
  265. if (cos_a > 1.0f) cos_a = 1.0f;
  266. if (cos_a < -1.0f) cos_a = -1.0f;
  267. F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
  268. if ( fabs( sin_a ) < 0.0005f )
  269. sin_a = 1.0f;
  270. else
  271. sin_a = 1.f/sin_a;
  272. F32 temp_angle = 2.0f * (F32) acos( cos_a );
  273. if (temp_angle > F_PI)
  274. {
  275. // The (angle,axis) pair should never have angles outside [PI, -PI]
  276. // since we want the _shortest_ (angle,axis) solution.
  277. // Since acos is defined for [0, PI], and we multiply by 2.0, we
  278. // can push the angle outside the acceptible range.
  279. // When this happens we set the angle to the other portion of a
  280. // full 2PI rotation, and negate the axis, which reverses the
  281. // direction of the rotation (by the right-hand rule).
  282. *angle = 2.f * F_PI - temp_angle;
  283. *x = - mQ[VX] * sin_a;
  284. *y = - mQ[VY] * sin_a;
  285. *z = - mQ[VZ] * sin_a;
  286. }
  287. else
  288. {
  289. *angle = temp_angle;
  290. *x = mQ[VX] * sin_a;
  291. *y = mQ[VY] * sin_a;
  292. *z = mQ[VZ] * sin_a;
  293. }
  294. }
  295. inline const LLQuaternion& LLQuaternion::conjugate()
  296. {
  297. mQ[VX] *= -1.f;
  298. mQ[VY] *= -1.f;
  299. mQ[VZ] *= -1.f;
  300. return (*this);
  301. }
  302. inline const LLQuaternion& LLQuaternion::conjQuat()
  303. {
  304. mQ[VX] *= -1.f;
  305. mQ[VY] *= -1.f;
  306. mQ[VZ] *= -1.f;
  307. return (*this);
  308. }
  309. // Transpose
  310. inline const LLQuaternion& LLQuaternion::transpose()
  311. {
  312. mQ[VX] *= -1.f;
  313. mQ[VY] *= -1.f;
  314. mQ[VZ] *= -1.f;
  315. return (*this);
  316. }
  317. // deprecated
  318. inline const LLQuaternion& LLQuaternion::transQuat()
  319. {
  320. mQ[VX] *= -1.f;
  321. mQ[VY] *= -1.f;
  322. mQ[VZ] *= -1.f;
  323. return (*this);
  324. }
  325. inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)
  326. {
  327. return LLQuaternion(
  328. a.mQ[VX] + b.mQ[VX],
  329. a.mQ[VY] + b.mQ[VY],
  330. a.mQ[VZ] + b.mQ[VZ],
  331. a.mQ[VW] + b.mQ[VW] );
  332. }
  333. inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b)
  334. {
  335. return LLQuaternion(
  336. a.mQ[VX] - b.mQ[VX],
  337. a.mQ[VY] - b.mQ[VY],
  338. a.mQ[VZ] - b.mQ[VZ],
  339. a.mQ[VW] - b.mQ[VW] );
  340. }
  341. inline LLQuaternion operator-(const LLQuaternion &a)
  342. {
  343. return LLQuaternion(
  344. -a.mQ[VX],
  345. -a.mQ[VY],
  346. -a.mQ[VZ],
  347. -a.mQ[VW] );
  348. }
  349. inline LLQuaternion operator*(F32 a, const LLQuaternion &q)
  350. {
  351. return LLQuaternion(
  352. a * q.mQ[VX],
  353. a * q.mQ[VY],
  354. a * q.mQ[VZ],
  355. a * q.mQ[VW] );
  356. }
  357. inline LLQuaternion operator*(const LLQuaternion &q, F32 a)
  358. {
  359. return LLQuaternion(
  360. a * q.mQ[VX],
  361. a * q.mQ[VY],
  362. a * q.mQ[VZ],
  363. a * q.mQ[VW] );
  364. }
  365. inline LLQuaternion operator~(const LLQuaternion &a)
  366. {
  367. LLQuaternion q(a);
  368. q.conjQuat();
  369. return q;
  370. }
  371. inline bool LLQuaternion::operator==(const LLQuaternion &b) const
  372. {
  373. return ( (mQ[VX] == b.mQ[VX])
  374. &&(mQ[VY] == b.mQ[VY])
  375. &&(mQ[VZ] == b.mQ[VZ])
  376. &&(mQ[VS] == b.mQ[VS]));
  377. }
  378. inline bool LLQuaternion::operator!=(const LLQuaternion &b) const
  379. {
  380. return ( (mQ[VX] != b.mQ[VX])
  381. ||(mQ[VY] != b.mQ[VY])
  382. ||(mQ[VZ] != b.mQ[VZ])
  383. ||(mQ[VS] != b.mQ[VS]));
  384. }
  385. inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
  386. {
  387. #if 1
  388. LLQuaternion q(
  389. b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
  390. b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
  391. b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
  392. b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]
  393. );
  394. a = q;
  395. #else
  396. a = a * b;
  397. #endif
  398. return a;
  399. }
  400. const F32 ONE_PART_IN_A_MILLION = 0.000001f;
  401. inline F32 LLQuaternion::normalize()
  402. {
  403. F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
  404. if (mag > FP_MAG_THRESHOLD)
  405. {
  406. // Floating point error can prevent some quaternions from achieving
  407. // exact unity length. When trying to renormalize such quaternions we
  408. // can oscillate between multiple quantized states. To prevent such
  409. // drifts we only renomalize if the length is far enough from unity.
  410. if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
  411. {
  412. F32 oomag = 1.f/mag;
  413. mQ[VX] *= oomag;
  414. mQ[VY] *= oomag;
  415. mQ[VZ] *= oomag;
  416. mQ[VS] *= oomag;
  417. }
  418. }
  419. else
  420. {
  421. // we were given a very bad quaternion so we set it to identity
  422. mQ[VX] = 0.f;
  423. mQ[VY] = 0.f;
  424. mQ[VZ] = 0.f;
  425. mQ[VS] = 1.f;
  426. }
  427. return mag;
  428. }
  429. // deprecated
  430. inline F32 LLQuaternion::normQuat()
  431. {
  432. F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
  433. if (mag > FP_MAG_THRESHOLD)
  434. {
  435. if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
  436. {
  437. // only renormalize if length not close enough to 1.0 already
  438. F32 oomag = 1.f/mag;
  439. mQ[VX] *= oomag;
  440. mQ[VY] *= oomag;
  441. mQ[VZ] *= oomag;
  442. mQ[VS] *= oomag;
  443. }
  444. }
  445. else
  446. {
  447. mQ[VX] = 0.f;
  448. mQ[VY] = 0.f;
  449. mQ[VZ] = 0.f;
  450. mQ[VS] = 1.f;
  451. }
  452. return mag;
  453. }
  454. LLQuaternion::Order StringToOrder( const char *str );
  455. // Some notes about Quaternions
  456. // What is a Quaternion?
  457. // ---------------------
  458. // A quaternion is a point in 4-dimensional complex space.
  459. // Q = { Qx, Qy, Qz, Qw }
  460. //
  461. //
  462. // Why Quaternions?
  463. // ----------------
  464. // The set of quaternions that make up the the 4-D unit sphere
  465. // can be mapped to the set of all rotations in 3-D space. Sometimes
  466. // it is easier to describe/manipulate rotations in quaternion space
  467. // than rotation-matrix space.
  468. //
  469. //
  470. // How Quaternions?
  471. // ----------------
  472. // In order to take advantage of quaternions we need to know how to
  473. // go from rotation-matricies to quaternions and back. We also have
  474. // to agree what variety of rotations we're generating.
  475. //
  476. // Consider the equation... v' = v * R
  477. //
  478. // There are two ways to think about rotations of vectors.
  479. // 1) v' is the same vector in a different reference frame
  480. // 2) v' is a new vector in the same reference frame
  481. //
  482. // bookmark -- which way are we using?
  483. //
  484. //
  485. // Quaternion from Angle-Axis:
  486. // ---------------------------
  487. // Suppose we wanted to represent a rotation of some angle (theta)
  488. // about some axis ({Ax, Ay, Az})...
  489. //
  490. // axis of rotation = {Ax, Ay, Az}
  491. // angle_of_rotation = theta
  492. //
  493. // s = sin(0.5 * theta)
  494. // c = cos(0.5 * theta)
  495. // Q = { s * Ax, s * Ay, s * Az, c }
  496. //
  497. //
  498. // 3x3 Matrix from Quaternion
  499. // --------------------------
  500. //
  501. // | |
  502. // | 1 - 2 * (y^2 + z^2) 2 * (x * y + z * w) 2 * (y * w - x * z) |
  503. // | |
  504. // M = | 2 * (x * y - z * w) 1 - 2 * (x^2 + z^2) 2 * (y * z + x * w) |
  505. // | |
  506. // | 2 * (x * z + y * w) 2 * (y * z - x * w) 1 - 2 * (x^2 + y^2) |
  507. // | |
  508. #endif