llquaternion.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:23k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llquaternion.cpp
  3.  * @brief LLQuaternion class implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, 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. #include "linden_common.h"
  33. #include "llquaternion.h"
  34. #include "llmath.h" // for F_PI
  35. //#include "vmath.h"
  36. #include "v3math.h"
  37. #include "v3dmath.h"
  38. #include "v4math.h"
  39. #include "m4math.h"
  40. #include "m3math.h"
  41. #include "llquantize.h"
  42. // WARNING: Don't use this for global const definitions!  using this
  43. // at the top of a *.cpp file might not give you what you think.
  44. const LLQuaternion LLQuaternion::DEFAULT;
  45.  
  46. // Constructors
  47. LLQuaternion::LLQuaternion(const LLMatrix4 &mat)
  48. {
  49. *this = mat.quaternion();
  50. normalize();
  51. }
  52. LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
  53. {
  54. *this = mat.quaternion();
  55. normalize();
  56. }
  57. LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
  58. {
  59. LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
  60. v.normalize();
  61. F32 c, s;
  62. c = cosf(angle*0.5f);
  63. s = sinf(angle*0.5f);
  64. mQ[VX] = v.mV[VX] * s;
  65. mQ[VY] = v.mV[VY] * s;
  66. mQ[VZ] = v.mV[VZ] * s;
  67. mQ[VW] = c;
  68. normalize();
  69. }
  70. LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
  71. {
  72. LLVector3 v(vec);
  73. v.normalize();
  74. F32 c, s;
  75. c = cosf(angle*0.5f);
  76. s = sinf(angle*0.5f);
  77. mQ[VX] = v.mV[VX] * s;
  78. mQ[VY] = v.mV[VY] * s;
  79. mQ[VZ] = v.mV[VZ] * s;
  80. mQ[VW] = c;
  81. normalize();
  82. }
  83. LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
  84.    const LLVector3 &y_axis,
  85.    const LLVector3 &z_axis)
  86. {
  87. LLMatrix3 mat;
  88. mat.setRows(x_axis, y_axis, z_axis);
  89. *this = mat.quaternion();
  90. normalize();
  91. }
  92. // Quatizations
  93. void LLQuaternion::quantize16(F32 lower, F32 upper)
  94. {
  95. F32 x = mQ[VX];
  96. F32 y = mQ[VY];
  97. F32 z = mQ[VZ];
  98. F32 s = mQ[VS];
  99. x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper);
  100. y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper);
  101. z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper);
  102. s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper);
  103. mQ[VX] = x;
  104. mQ[VY] = y;
  105. mQ[VZ] = z;
  106. mQ[VS] = s;
  107. normalize();
  108. }
  109. void LLQuaternion::quantize8(F32 lower, F32 upper)
  110. {
  111. mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper);
  112. mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper);
  113. mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
  114. mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
  115. normalize();
  116. }
  117. // LLVector3 Magnitude and Normalization Functions
  118. // Set LLQuaternion routines
  119. const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z)
  120. {
  121. LLVector3 vec(x, y, z);
  122. vec.normalize();
  123. angle *= 0.5f;
  124. F32 c, s;
  125. c = cosf(angle);
  126. s = sinf(angle);
  127. mQ[VX] = vec.mV[VX]*s;
  128. mQ[VY] = vec.mV[VY]*s;
  129. mQ[VZ] = vec.mV[VZ]*s;
  130. mQ[VW] = c;
  131. normalize();
  132. return (*this);
  133. }
  134. const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec)
  135. {
  136. LLVector3 v(vec);
  137. v.normalize();
  138. angle *= 0.5f;
  139. F32 c, s;
  140. c = cosf(angle);
  141. s = sinf(angle);
  142. mQ[VX] = v.mV[VX]*s;
  143. mQ[VY] = v.mV[VY]*s;
  144. mQ[VZ] = v.mV[VZ]*s;
  145. mQ[VW] = c;
  146. normalize();
  147. return (*this);
  148. }
  149. const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec)
  150. {
  151. LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
  152. v.normalize();
  153. F32 c, s;
  154. c = cosf(angle*0.5f);
  155. s = sinf(angle*0.5f);
  156. mQ[VX] = v.mV[VX]*s;
  157. mQ[VY] = v.mV[VY]*s;
  158. mQ[VZ] = v.mV[VZ]*s;
  159. mQ[VW] = c;
  160. normalize();
  161. return (*this);
  162. }
  163. const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw)
  164. {
  165. LLMatrix3 rot_mat(roll, pitch, yaw);
  166. rot_mat.orthogonalize();
  167. *this = rot_mat.quaternion();
  168. normalize();
  169. return (*this);
  170. }
  171. // deprecated
  172. const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat)
  173. {
  174. *this = mat.quaternion();
  175. normalize();
  176. return (*this);
  177. }
  178. // deprecated
  179. const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat)
  180. {
  181. *this = mat.quaternion();
  182. normalize();
  183. return (*this);
  184. }
  185. // deprecated
  186. const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z)
  187. {
  188. LLVector3 vec(x, y, z);
  189. vec.normalize();
  190. angle *= 0.5f;
  191. F32 c, s;
  192. c = cosf(angle);
  193. s = sinf(angle);
  194. mQ[VX] = vec.mV[VX]*s;
  195. mQ[VY] = vec.mV[VY]*s;
  196. mQ[VZ] = vec.mV[VZ]*s;
  197. mQ[VW] = c;
  198. normalize();
  199. return (*this);
  200. }
  201. // deprecated
  202. const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec)
  203. {
  204. LLVector3 v(vec);
  205. v.normalize();
  206. angle *= 0.5f;
  207. F32 c, s;
  208. c = cosf(angle);
  209. s = sinf(angle);
  210. mQ[VX] = v.mV[VX]*s;
  211. mQ[VY] = v.mV[VY]*s;
  212. mQ[VZ] = v.mV[VZ]*s;
  213. mQ[VW] = c;
  214. normalize();
  215. return (*this);
  216. }
  217. const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec)
  218. {
  219. LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
  220. v.normalize();
  221. F32 c, s;
  222. c = cosf(angle*0.5f);
  223. s = sinf(angle*0.5f);
  224. mQ[VX] = v.mV[VX]*s;
  225. mQ[VY] = v.mV[VY]*s;
  226. mQ[VZ] = v.mV[VZ]*s;
  227. mQ[VW] = c;
  228. normalize();
  229. return (*this);
  230. }
  231. const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw)
  232. {
  233. LLMatrix3 rot_mat(roll, pitch, yaw);
  234. rot_mat.orthogonalize();
  235. *this = rot_mat.quaternion();
  236. normalize();
  237. return (*this);
  238. }
  239. const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat)
  240. {
  241. *this = mat.quaternion();
  242. normalize();
  243. return (*this);
  244. }
  245. const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
  246. {
  247. *this = mat.quaternion();
  248. normalize();
  249. return (*this);
  250. //#if 1
  251. // // NOTE: LLQuaternion's are actually inverted with respect to
  252. // // the matrices, so this code also assumes inverted quaternions
  253. // // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied
  254. // // in reverse order (yaw,pitch,roll).
  255. // F64 cosX = cos(roll);
  256. //    F64 cosY = cos(pitch);
  257. //    F64 cosZ = cos(yaw);
  258. //
  259. //    F64 sinX = sin(roll);
  260. //    F64 sinY = sin(pitch);
  261. //    F64 sinZ = sin(yaw);
  262. //
  263. //    mQ[VW] = (F32)sqrt(cosY*cosZ - sinX*sinY*sinZ + cosX*cosZ + cosX*cosY + 1.0)*.5;
  264. // if (fabs(mQ[VW]) < F_APPROXIMATELY_ZERO)
  265. // {
  266. // // null rotation, any axis will do
  267. // mQ[VX] = 0.0f;
  268. // mQ[VY] = 1.0f;
  269. // mQ[VZ] = 0.0f;
  270. // }
  271. // else
  272. // {
  273. // F32 inv_s = 1.0f / (4.0f * mQ[VW]);
  274. // mQ[VX] = (F32)-(-sinX*cosY - cosX*sinY*sinZ - sinX*cosZ) * inv_s;
  275. // mQ[VY] = (F32)-(-cosX*sinY*cosZ + sinX*sinZ - sinY) * inv_s;
  276. // mQ[VZ] = (F32)-(-cosY*sinZ - sinX*sinY*cosZ - cosX*sinZ) * inv_s;
  277. // }
  278. //
  279. //#else // This only works on a certain subset of roll/pitch/yaw
  280. //
  281. // F64 cosX = cosf(roll/2.0);
  282. //    F64 cosY = cosf(pitch/2.0);
  283. //    F64 cosZ = cosf(yaw/2.0);
  284. //
  285. //    F64 sinX = sinf(roll/2.0);
  286. //    F64 sinY = sinf(pitch/2.0);
  287. //    F64 sinZ = sinf(yaw/2.0);
  288. //
  289. //    mQ[VW] = (F32)(cosX*cosY*cosZ + sinX*sinY*sinZ);
  290. //    mQ[VX] = (F32)(sinX*cosY*cosZ - cosX*sinY*sinZ);
  291. //    mQ[VY] = (F32)(cosX*sinY*cosZ + sinX*cosY*sinZ);
  292. //    mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
  293. //#endif
  294. //
  295. // normalize();
  296. // return (*this);
  297. }
  298. // SJB: This code is correct for a logicly stored (non-transposed) matrix;
  299. // Our matrices are stored transposed, OpenGL style, so this generates the
  300. // INVERSE matrix, or the CORRECT matrix form an INVERSE quaternion.
  301. // Because we use similar logic in LLMatrix3::quaternion(),
  302. // we are internally consistant so everything works OK :)
  303. LLMatrix3 LLQuaternion::getMatrix3(void) const
  304. {
  305. LLMatrix3 mat;
  306. F32 xx, xy, xz, xw, yy, yz, yw, zz, zw;
  307.     xx      = mQ[VX] * mQ[VX];
  308.     xy      = mQ[VX] * mQ[VY];
  309.     xz      = mQ[VX] * mQ[VZ];
  310.     xw      = mQ[VX] * mQ[VW];
  311.     yy      = mQ[VY] * mQ[VY];
  312.     yz      = mQ[VY] * mQ[VZ];
  313.     yw      = mQ[VY] * mQ[VW];
  314.     zz      = mQ[VZ] * mQ[VZ];
  315.     zw      = mQ[VZ] * mQ[VW];
  316.     mat.mMatrix[0][0]  = 1.f - 2.f * ( yy + zz );
  317.     mat.mMatrix[0][1]  =    2.f * ( xy + zw );
  318.     mat.mMatrix[0][2]  =    2.f * ( xz - yw );
  319.     mat.mMatrix[1][0]  =    2.f * ( xy - zw );
  320.     mat.mMatrix[1][1]  = 1.f - 2.f * ( xx + zz );
  321.     mat.mMatrix[1][2]  =    2.f * ( yz + xw );
  322.     mat.mMatrix[2][0]  =    2.f * ( xz + yw );
  323.     mat.mMatrix[2][1]  =    2.f * ( yz - xw );
  324.     mat.mMatrix[2][2]  = 1.f - 2.f * ( xx + yy );
  325. return mat;
  326. }
  327. LLMatrix4 LLQuaternion::getMatrix4(void) const
  328. {
  329. LLMatrix4 mat;
  330. F32 xx, xy, xz, xw, yy, yz, yw, zz, zw;
  331.     xx      = mQ[VX] * mQ[VX];
  332.     xy      = mQ[VX] * mQ[VY];
  333.     xz      = mQ[VX] * mQ[VZ];
  334.     xw      = mQ[VX] * mQ[VW];
  335.     yy      = mQ[VY] * mQ[VY];
  336.     yz      = mQ[VY] * mQ[VZ];
  337.     yw      = mQ[VY] * mQ[VW];
  338.     zz      = mQ[VZ] * mQ[VZ];
  339.     zw      = mQ[VZ] * mQ[VW];
  340.     mat.mMatrix[0][0]  = 1.f - 2.f * ( yy + zz );
  341.     mat.mMatrix[0][1]  =    2.f * ( xy + zw );
  342.     mat.mMatrix[0][2]  =    2.f * ( xz - yw );
  343.     mat.mMatrix[1][0]  =    2.f * ( xy - zw );
  344.     mat.mMatrix[1][1]  = 1.f - 2.f * ( xx + zz );
  345.     mat.mMatrix[1][2]  =    2.f * ( yz + xw );
  346.     mat.mMatrix[2][0]  =    2.f * ( xz + yw );
  347.     mat.mMatrix[2][1]  =    2.f * ( yz - xw );
  348.     mat.mMatrix[2][2]  = 1.f - 2.f * ( xx + yy );
  349. // TODO -- should we set the translation portion to zero?
  350. return mat;
  351. }
  352. // Other useful methods
  353. // calculate the shortest rotation from a to b
  354. void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b)
  355. {
  356. // Make a local copy of both vectors.
  357. LLVector3 vec_a = a;
  358. LLVector3 vec_b = b;
  359. // Make sure neither vector is zero length.  Also normalize
  360. // the vectors while we are at it.
  361. F32 vec_a_mag = vec_a.normalize();
  362. F32 vec_b_mag = vec_b.normalize();
  363. if (vec_a_mag < F_APPROXIMATELY_ZERO ||
  364. vec_b_mag < F_APPROXIMATELY_ZERO)
  365. {
  366. // Can't calculate a rotation from this.
  367. // Just return ZERO_ROTATION instead.
  368. loadIdentity();
  369. return;
  370. }
  371. // Create an axis to rotate around, and the cos of the angle to rotate.
  372. LLVector3 axis = vec_a % vec_b;
  373. F32 cos_theta  = vec_a * vec_b;
  374. // Check the angle between the vectors to see if they are parallel or anti-parallel.
  375. if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO)
  376. {
  377. // a and b are parallel.  No rotation is necessary.
  378. loadIdentity();
  379. }
  380. else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO)
  381. {
  382. // a and b are anti-parallel.
  383. // Rotate 180 degrees around some orthogonal axis.
  384. // Find the projection of the x-axis onto a, and try
  385. // using the vector between the projection and the x-axis
  386. // as the orthogonal axis.
  387. LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a;
  388. LLVector3 ortho_axis(1.f, 0.f, 0.f);
  389. ortho_axis -= proj;
  390. // Turn this into an orthonormal axis.
  391. F32 ortho_length = ortho_axis.normalize();
  392. // If the axis' length is 0, then our guess at an orthogonal axis
  393. // was wrong (a is parallel to the x-axis).
  394. if (ortho_length < F_APPROXIMATELY_ZERO)
  395. {
  396. // Use the z-axis instead.
  397. ortho_axis.setVec(0.f, 0.f, 1.f);
  398. }
  399. // Construct a quaternion from this orthonormal axis.
  400. mQ[VX] = ortho_axis.mV[VX];
  401. mQ[VY] = ortho_axis.mV[VY];
  402. mQ[VZ] = ortho_axis.mV[VZ];
  403. mQ[VW] = 0.f;
  404. }
  405. else
  406. {
  407. // a and b are NOT parallel or anti-parallel.
  408. // Return the rotation between these vectors.
  409. F32 theta = (F32)acos(cos_theta);
  410. setAngleAxis(theta, axis);
  411. }
  412. }
  413. // constrains rotation to a cone angle specified in radians
  414. const LLQuaternion &LLQuaternion::constrain(F32 radians)
  415. {
  416. const F32 cos_angle_lim = cosf( radians/2 ); // mQ[VW] limit
  417. const F32 sin_angle_lim = sinf( radians/2 ); // rotation axis length limit
  418. if (mQ[VW] < 0.f)
  419. {
  420. mQ[VX] *= -1.f;
  421. mQ[VY] *= -1.f;
  422. mQ[VZ] *= -1.f;
  423. mQ[VW] *= -1.f;
  424. }
  425. // if rotation angle is greater than limit (cos is less than limit)
  426. if( mQ[VW] < cos_angle_lim )
  427. {
  428. mQ[VW] = cos_angle_lim;
  429. F32 axis_len = sqrtf( mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] ); // sin(theta/2)
  430. F32 axis_mult_fact = sin_angle_lim / axis_len;
  431. mQ[VX] *= axis_mult_fact;
  432. mQ[VY] *= axis_mult_fact;
  433. mQ[VZ] *= axis_mult_fact;
  434. }
  435. return *this;
  436. }
  437. // Operators
  438. std::ostream& operator<<(std::ostream &s, const LLQuaternion &a)
  439. {
  440. s << "{ " 
  441. << a.mQ[VX] << ", " << a.mQ[VY] << ", " << a.mQ[VZ] << ", " << a.mQ[VW] 
  442. << " }";
  443. return s;
  444. }
  445. // Does NOT renormalize the result
  446. LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b)
  447. {
  448. // LLQuaternion::mMultCount++;
  449. LLQuaternion q(
  450. b.mQ[3] * a.mQ[0] + b.mQ[0] * a.mQ[3] + b.mQ[1] * a.mQ[2] - b.mQ[2] * a.mQ[1],
  451. b.mQ[3] * a.mQ[1] + b.mQ[1] * a.mQ[3] + b.mQ[2] * a.mQ[0] - b.mQ[0] * a.mQ[2],
  452. b.mQ[3] * a.mQ[2] + b.mQ[2] * a.mQ[3] + b.mQ[0] * a.mQ[1] - b.mQ[1] * a.mQ[0],
  453. b.mQ[3] * a.mQ[3] - b.mQ[0] * a.mQ[0] - b.mQ[1] * a.mQ[1] - b.mQ[2] * a.mQ[2]
  454. );
  455. return q;
  456. }
  457. /*
  458. LLMatrix4 operator*(const LLMatrix4 &m, const LLQuaternion &q)
  459. {
  460. LLMatrix4 qmat(q);
  461. return (m*qmat);
  462. }
  463. */
  464. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot)
  465. {
  466.     F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
  467.     F32 rx =   rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
  468.     F32 ry =   rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ];
  469.     F32 rz =   rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX];
  470.     F32 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
  471.     F32 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
  472.     F32 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
  473.     return LLVector4(nx, ny, nz, a.mV[VW]);
  474. }
  475. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot)
  476. {
  477.     F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
  478.     F32 rx =   rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
  479.     F32 ry =   rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ];
  480.     F32 rz =   rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX];
  481.     F32 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
  482.     F32 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
  483.     F32 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
  484.     return LLVector3(nx, ny, nz);
  485. }
  486. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot)
  487. {
  488.     F64 rw = - rot.mQ[VX] * a.mdV[VX] - rot.mQ[VY] * a.mdV[VY] - rot.mQ[VZ] * a.mdV[VZ];
  489.     F64 rx =   rot.mQ[VW] * a.mdV[VX] + rot.mQ[VY] * a.mdV[VZ] - rot.mQ[VZ] * a.mdV[VY];
  490.     F64 ry =   rot.mQ[VW] * a.mdV[VY] + rot.mQ[VZ] * a.mdV[VX] - rot.mQ[VX] * a.mdV[VZ];
  491.     F64 rz =   rot.mQ[VW] * a.mdV[VZ] + rot.mQ[VX] * a.mdV[VY] - rot.mQ[VY] * a.mdV[VX];
  492.     F64 nx = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
  493.     F64 ny = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
  494.     F64 nz = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
  495.     return LLVector3d(nx, ny, nz);
  496. }
  497. F32 dot(const LLQuaternion &a, const LLQuaternion &b)
  498. {
  499. return a.mQ[VX] * b.mQ[VX] + 
  500.    a.mQ[VY] * b.mQ[VY] + 
  501.    a.mQ[VZ] * b.mQ[VZ] + 
  502.    a.mQ[VW] * b.mQ[VW]; 
  503. }
  504. // DEMO HACK: This lerp is probably inocrrect now due intermediate normalization
  505. // it should look more like the lerp below
  506. #if 0
  507. // linear interpolation
  508. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
  509. {
  510. LLQuaternion r;
  511. r = t * (q - p) + p;
  512. r.normalize();
  513. return r;
  514. }
  515. #endif
  516. // lerp from identity to q
  517. LLQuaternion lerp(F32 t, const LLQuaternion &q)
  518. {
  519. LLQuaternion r;
  520. r.mQ[VX] = t * q.mQ[VX];
  521. r.mQ[VY] = t * q.mQ[VY];
  522. r.mQ[VZ] = t * q.mQ[VZ];
  523. r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f;
  524. r.normalize();
  525. return r;
  526. }
  527. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q)
  528. {
  529. LLQuaternion r;
  530. F32 inv_t;
  531. inv_t = 1.f - t;
  532. r.mQ[VX] = t * q.mQ[VX] + (inv_t * p.mQ[VX]);
  533. r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]);
  534. r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]);
  535. r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]);
  536. r.normalize();
  537. return r;
  538. }
  539. // spherical linear interpolation
  540. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b )
  541. {
  542. // cosine theta = dot product of a and b
  543. F32 cos_t = a.mQ[0]*b.mQ[0] + a.mQ[1]*b.mQ[1] + a.mQ[2]*b.mQ[2] + a.mQ[3]*b.mQ[3];
  544. // if b is on opposite hemisphere from a, use -a instead
  545. int bflip;
  546.   if (cos_t < 0.0f)
  547. {
  548. cos_t = -cos_t;
  549. bflip = TRUE;
  550. }
  551. else
  552. bflip = FALSE;
  553. // if B is (within precision limits) the same as A,
  554. // just linear interpolate between A and B.
  555. F32 alpha; // interpolant
  556. F32 beta; // 1 - interpolant
  557. if (1.0f - cos_t < 0.00001f)
  558. {
  559. beta = 1.0f - u;
  560. alpha = u;
  561.   }
  562. else
  563. {
  564.   F32 theta = acosf(cos_t);
  565.   F32 sin_t = sinf(theta);
  566.   beta = sinf(theta - u*theta) / sin_t;
  567.   alpha = sinf(u*theta) / sin_t;
  568.   }
  569. if (bflip)
  570. beta = -beta;
  571. // interpolate
  572. LLQuaternion ret;
  573. ret.mQ[0] = beta*a.mQ[0] + alpha*b.mQ[0];
  574.   ret.mQ[1] = beta*a.mQ[1] + alpha*b.mQ[1];
  575.   ret.mQ[2] = beta*a.mQ[2] + alpha*b.mQ[2];
  576.   ret.mQ[3] = beta*a.mQ[3] + alpha*b.mQ[3];
  577. return ret;
  578. }
  579. // lerp whenever possible
  580. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b)
  581. {
  582. if (dot(a, b) < 0.f)
  583. {
  584. return slerp(t, a, b);
  585. }
  586. else
  587. {
  588. return lerp(t, a, b);
  589. }
  590. }
  591. LLQuaternion nlerp(F32 t, const LLQuaternion &q)
  592. {
  593. if (q.mQ[VW] < 0.f)
  594. {
  595. return slerp(t, q);
  596. }
  597. else
  598. {
  599. return lerp(t, q);
  600. }
  601. }
  602. // slerp from identity quaternion to another quaternion
  603. LLQuaternion slerp(F32 t, const LLQuaternion &q)
  604. {
  605. F32 c = q.mQ[VW];
  606. if (1.0f == t  ||  1.0f == c)
  607. {
  608. // the trivial cases
  609. return q;
  610. }
  611. LLQuaternion r;
  612. F32 s, angle, stq, stp;
  613. s = (F32) sqrt(1.f - c*c);
  614.     if (c < 0.0f)
  615.     {
  616.         // when c < 0.0 then theta > PI/2 
  617.         // since quat and -quat are the same rotation we invert one of  
  618.         // p or q to reduce unecessary spins
  619.         // A equivalent way to do it is to convert acos(c) as if it had 
  620. // been negative, and to negate stp 
  621.         angle   = (F32) acos(-c); 
  622.         stp     = -(F32) sin(angle * (1.f - t));
  623.         stq     = (F32) sin(angle * t);
  624.     }   
  625.     else
  626.     {
  627. angle  = (F32) acos(c);
  628.         stp     = (F32) sin(angle * (1.f - t));
  629.         stq     = (F32) sin(angle * t);
  630.     }
  631. r.mQ[VX] = (q.mQ[VX] * stq) / s;
  632. r.mQ[VY] = (q.mQ[VY] * stq) / s;
  633. r.mQ[VZ] = (q.mQ[VZ] * stq) / s;
  634. r.mQ[VW] = (stp + q.mQ[VW] * stq) / s;
  635. return r;
  636. }
  637. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order)
  638. {
  639. LLQuaternion xQ( xRot*DEG_TO_RAD, LLVector3(1.0f, 0.0f, 0.0f) );
  640. LLQuaternion yQ( yRot*DEG_TO_RAD, LLVector3(0.0f, 1.0f, 0.0f) );
  641. LLQuaternion zQ( zRot*DEG_TO_RAD, LLVector3(0.0f, 0.0f, 1.0f) );
  642. LLQuaternion ret;
  643. switch( order )
  644. {
  645. case LLQuaternion::XYZ:
  646. ret = xQ * yQ * zQ;
  647. break;
  648. case LLQuaternion::YZX:
  649. ret = yQ * zQ * xQ;
  650. break;
  651. case LLQuaternion::ZXY:
  652. ret = zQ * xQ * yQ;
  653. break;
  654. case LLQuaternion::XZY:
  655. ret = xQ * zQ * yQ;
  656. break;
  657. case LLQuaternion::YXZ:
  658. ret = yQ * xQ * zQ;
  659. break;
  660. case LLQuaternion::ZYX:
  661. ret = zQ * yQ * xQ;
  662. break;
  663. }
  664. return ret;
  665. }
  666. const char *OrderToString( const LLQuaternion::Order order )
  667. {
  668. const char *p = NULL;
  669. switch( order )
  670. {
  671. default:
  672. case LLQuaternion::XYZ:
  673. p = "XYZ";
  674. break;
  675. case LLQuaternion::YZX:
  676. p = "YZX";
  677. break;
  678. case LLQuaternion::ZXY:
  679. p = "ZXY";
  680. break;
  681. case LLQuaternion::XZY:
  682. p = "XZY";
  683. break;
  684. case LLQuaternion::YXZ:
  685. p = "YXZ";
  686. break;
  687. case LLQuaternion::ZYX:
  688. p = "ZYX";
  689. break;
  690. }
  691. return p;
  692. }
  693. LLQuaternion::Order StringToOrder( const char *str )
  694. {
  695. if (strncmp(str, "XYZ", 3)==0 || strncmp(str, "xyz", 3)==0)
  696. return LLQuaternion::XYZ;
  697. if (strncmp(str, "YZX", 3)==0 || strncmp(str, "yzx", 3)==0)
  698. return LLQuaternion::YZX;
  699. if (strncmp(str, "ZXY", 3)==0 || strncmp(str, "zxy", 3)==0)
  700. return LLQuaternion::ZXY;
  701. if (strncmp(str, "XZY", 3)==0 || strncmp(str, "xzy", 3)==0)
  702. return LLQuaternion::XZY;
  703. if (strncmp(str, "YXZ", 3)==0 || strncmp(str, "yxz", 3)==0)
  704. return LLQuaternion::YXZ;
  705. if (strncmp(str, "ZYX", 3)==0 || strncmp(str, "zyx", 3)==0)
  706. return LLQuaternion::ZYX;
  707. return LLQuaternion::XYZ;
  708. }
  709. void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
  710. {
  711. F32 cos_a = mQ[VW];
  712. if (cos_a > 1.0f) cos_a = 1.0f;
  713. if (cos_a < -1.0f) cos_a = -1.0f;
  714.     F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
  715.     if ( fabs( sin_a ) < 0.0005f )
  716. sin_a = 1.0f;
  717. else
  718. sin_a = 1.f/sin_a;
  719.     F32 temp_angle = 2.0f * (F32) acos( cos_a );
  720. if (temp_angle > F_PI)
  721. {
  722. // The (angle,axis) pair should never have angles outside [PI, -PI]
  723. // since we want the _shortest_ (angle,axis) solution.
  724. // Since acos is defined for [0, PI], and we multiply by 2.0, we
  725. // can push the angle outside the acceptible range.
  726. // When this happens we set the angle to the other portion of a 
  727. // full 2PI rotation, and negate the axis, which reverses the 
  728. // direction of the rotation (by the right-hand rule).
  729. *angle = 2.f * F_PI - temp_angle;
  730.      vec.mV[VX] = - mQ[VX] * sin_a;
  731.      vec.mV[VY] = - mQ[VY] * sin_a;
  732.      vec.mV[VZ] = - mQ[VZ] * sin_a;
  733. }
  734. else
  735. {
  736. *angle = temp_angle;
  737.      vec.mV[VX] = mQ[VX] * sin_a;
  738.      vec.mV[VY] = mQ[VY] * sin_a;
  739.      vec.mV[VZ] = mQ[VZ] * sin_a;
  740. }
  741. }
  742. // quaternion does not need to be normalized
  743. void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
  744. {
  745. LLMatrix3 rot_mat(*this);
  746. rot_mat.orthogonalize();
  747. rot_mat.getEulerAngles(roll, pitch, yaw);
  748. // // NOTE: LLQuaternion's are actually inverted with respect to
  749. // // the matrices, so this code also assumes inverted quaternions
  750. // // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied
  751. // // in reverse order (yaw,pitch,roll).
  752. // F32 x = -mQ[VX], y = -mQ[VY], z = -mQ[VZ], w = mQ[VW];
  753. // F64 m20 = 2.0*(x*z-y*w);
  754. // if (1.0f - fabsf(m20) < F_APPROXIMATELY_ZERO)
  755. // {
  756. // *roll = 0.0f;
  757. // *pitch = (F32)asin(m20);
  758. // *yaw = (F32)atan2(2.0*(x*y-z*w), 1.0 - 2.0*(x*x+z*z));
  759. // }
  760. // else
  761. // {
  762. // *roll  = (F32)atan2(-2.0*(y*z+x*w), 1.0-2.0*(x*x+y*y));
  763. // *pitch = (F32)asin(m20);
  764. // *yaw   = (F32)atan2(-2.0*(x*y+z*w), 1.0-2.0*(y*y+z*z));
  765. // }
  766. }
  767. // Saves space by using the fact that our quaternions are normalized
  768. LLVector3 LLQuaternion::packToVector3() const
  769. {
  770. if( mQ[VW] >= 0 )
  771. {
  772. return LLVector3( mQ[VX], mQ[VY], mQ[VZ] );
  773. }
  774. else
  775. {
  776. return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] );
  777. }
  778. }
  779. // Saves space by using the fact that our quaternions are normalized
  780. void LLQuaternion::unpackFromVector3( const LLVector3& vec )
  781. {
  782. mQ[VX] = vec.mV[VX];
  783. mQ[VY] = vec.mV[VY];
  784. mQ[VZ] = vec.mV[VZ];
  785. F32 t = 1.f - vec.magVecSquared();
  786. if( t > 0 )
  787. {
  788. mQ[VW] = sqrt( t );
  789. }
  790. else
  791. {
  792. // Need this to avoid trying to find the square root of a negative number due
  793. // to floating point error.
  794. mQ[VW] = 0;
  795. }
  796. }
  797. BOOL LLQuaternion::parseQuat(const std::string& buf, LLQuaternion* value)
  798. {
  799. if( buf.empty() || value == NULL)
  800. {
  801. return FALSE;
  802. }
  803. LLQuaternion quat;
  804. S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 );
  805. if( 4 == count )
  806. {
  807. value->set( quat );
  808. return TRUE;
  809. }
  810. return FALSE;
  811. }
  812. // End