PageRenderTime 69ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/_engine/src/engine/utils/quaternion.c

https://gitlab.com/NunezG/GLTest
C | 1006 lines | 389 code | 191 blank | 426 comment | 28 complexity | 2d50b774162b2fc3f9528591ad145e26 MD5 | raw file
  1. /*SDOC*********************************************************************
  2. $Header$
  3. Module: GLquat.c
  4. Author: Nick Bobic
  5. Copyright (c) 1997 Nick Bobic
  6. Description: Common (and not so common) Quaternion Functions
  7. *********************************************************************EDOC*/
  8. /*SDOC*********************************************************************
  9. Revision Record
  10. Date Auth Changes
  11. ==== ==== =======
  12. 16AUG97 NB Created file
  13. 17AUG97 NB Added some exotic functions
  14. **********************************************************************EDOC*/
  15. // includes
  16. #include "quaternion.h"
  17. #include <math.h>
  18. // some math.h do not have M_PI definition
  19. #ifndef M_PI
  20. #define M_PI 3.14159265358979323846264338327950288419716939937510f
  21. #endif
  22. #define DELTA 1e-6 // error tolerance
  23. #if defined (WIN32)
  24. #pragma warning (disable:4244) // disable conversion warnings (dbl -> fl)
  25. #endif
  26. /*SDOC***********************************************************************
  27. Name: gluQuatToMat_EXT
  28. Action: Converts quaternion representation of a rotation to a matrix
  29. representation
  30. Params: GL_QUAT* (our quaternion), GLfloat (4x4 matrix)
  31. Returns: nothing
  32. Comments: remember matrix (in OGL) is represented in COLUMN major form
  33. ***********************************************************************EDOC*/
  34. void APIENTRY gluQuatToMat_EXT(GL_QUAT * quat, GLfloat m[4][4])
  35. {
  36. GLfloat wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  37. x2 = quat->x + quat->x; y2 = quat->y + quat->y; z2 = quat->z + quat->z;
  38. xx = quat->x * x2; xy = quat->x * y2; xz = quat->x * z2;
  39. yy = quat->y * y2; yz = quat->y * z2; zz = quat->z * z2;
  40. wx = quat->w * x2; wy = quat->w * y2; wz = quat->w * z2;
  41. m[0][0] = 1.0 - (yy + zz);
  42. m[0][1] = xy - wz;
  43. m[0][2] = xz + wy;
  44. m[0][3] = 0.0;
  45. m[1][0] = xy + wz;
  46. m[1][1] = 1.0 - (xx + zz);
  47. m[1][2] = yz - wx;
  48. m[1][3] = 0.0;
  49. m[2][0] = xz - wy;
  50. m[2][1] = yz + wx;
  51. m[2][2] = 1.0 - (xx + yy);
  52. m[2][3] = 0.0;
  53. m[3][0] = 0;
  54. m[3][1] = 0;
  55. m[3][2] = 0;
  56. m[3][3] = 1;
  57. }
  58. /*SDOC***********************************************************************
  59. Name: gluEulerToQuat_EXT
  60. Action: Converts representation of a rotation from Euler angles to
  61. quaternion representation
  62. Params: GLfloat (roll), GLfloat (pitch), GLfloat (yaw), GL_QUAT* (quat)
  63. Returns: nothing
  64. Comments: remember: roll - rotation around X axis
  65. pitch - rotation around Y axis
  66. yaw - rotation around Z axis
  67. rotations are performed in the following order:
  68. yaw -> pitch -> roll
  69. Qfinal = Qyaw Qpitch Qroll
  70. ***********************************************************************EDOC*/
  71. void APIENTRY gluEulerToQuat_EXT(GLfloat roll, GLfloat pitch, GLfloat yaw,
  72. GL_QUAT * quat)
  73. {
  74. GLfloat cr, cp, cy, sr, sp, sy, cpcy, spsy;
  75. cr = cos(roll/2);
  76. cp = cos(pitch/2);
  77. cy = cos(yaw/2);
  78. sr = sin(roll/2);
  79. sp = sin(pitch/2);
  80. sy = sin(yaw/2);
  81. cpcy = cp * cy;
  82. spsy = sp * sy;
  83. quat->w = cr * cpcy + sr * spsy;
  84. quat->x = sr * cpcy - cr * spsy;
  85. quat->y = cr * sp * cy + sr * cp * sy;
  86. quat->z = cr * cp * sy - sr * sp * cy;
  87. }
  88. /*SDOC***********************************************************************
  89. Name: gluMatToQuat_EXT
  90. Action: Converts matrix representation of a rotation to a quaternion
  91. representation
  92. Params: GLfloat (matrix), GL_QUAT* (quat)
  93. Returns: nothing
  94. Comments: remember matrix (in OGL) is represented in COLUMN major form
  95. ***********************************************************************EDOC*/
  96. void APIENTRY gluMatToQuat_EXT(GLfloat m[4][4], GL_QUAT * quat)
  97. {
  98. GLfloat tr, s;
  99. GLfloat q[4];
  100. GLint i, j, k;
  101. int nxt[3] = {1, 2, 0};
  102. tr = m[0][0] + m[1][1] + m[2][2];
  103. // check the diagonal
  104. if (tr > 0.0)
  105. {
  106. s = sqrt (tr + 1.0);
  107. quat->w = s / 2.0;
  108. s = 0.5 / s;
  109. quat->x = (m[1][2] - m[2][1]) * s;
  110. quat->y = (m[2][0] - m[0][2]) * s;
  111. quat->z = (m[0][1] - m[1][0]) * s;
  112. } else {
  113. // diagonal is negative
  114. i = 0;
  115. if (m[1][1] > m[0][0]) i = 1;
  116. if (m[2][2] > m[i][i]) i = 2;
  117. j = nxt[i];
  118. k = nxt[j];
  119. s = sqrt ((m[i][i] - (m[j][j] + m[k][k])) + 1.0);
  120. q[i] = s * 0.5;
  121. if (s != 0.0) s = 0.5 / s;
  122. q[3] = (m[j][k] - m[k][j]) * s;
  123. q[j] = (m[i][j] + m[j][i]) * s;
  124. q[k] = (m[i][k] + m[k][i]) * s;
  125. quat->x = q[0];
  126. quat->y = q[1];
  127. quat->z = q[2];
  128. quat->w = q[3];
  129. }
  130. }
  131. /*SDOC***********************************************************************
  132. Name: gluQuatSlerp_EXT
  133. Action: Smoothly (spherically, shortest path on a quaternion sphere)
  134. interpolates between two UNIT quaternion positions
  135. Params: GLQUAT (first and second quaternion), GLfloat (interpolation
  136. parameter [0..1]), GL_QUAT (resulting quaternion; inbetween)
  137. Returns: nothing
  138. Comments: Most of this code is optimized for speed and not for readability
  139. As t goes from 0 to 1, qt goes from p to q.
  140. slerp(p,q,t) = (p*sin((1-t)*omega) + q*sin(t*omega)) / sin(omega)
  141. ***********************************************************************EDOC*/
  142. void APIENTRY gluQuatSlerp_EXT(GL_QUAT * from, GL_QUAT * to, GLfloat t,
  143. GL_QUAT * res)
  144. {
  145. GLfloat to1[4];
  146. GLdouble omega, cosom, sinom;
  147. GLdouble scale0, scale1;
  148. // calc cosine
  149. cosom = from->x * to->x + from->y * to->y + from->z * to->z
  150. + from->w * to->w;
  151. // adjust signs (if necessary)
  152. if ( cosom < 0.0 )
  153. {
  154. cosom = -cosom;
  155. to1[0] = - to->x;
  156. to1[1] = - to->y;
  157. to1[2] = - to->z;
  158. to1[3] = - to->w;
  159. } else {
  160. to1[0] = to->x;
  161. to1[1] = to->y;
  162. to1[2] = to->z;
  163. to1[3] = to->w;
  164. }
  165. // calculate coefficients
  166. if ( (1.0 - cosom) > DELTA )
  167. {
  168. // standard case (slerp)
  169. omega = acos(cosom);
  170. sinom = sin(omega);
  171. scale0 = sin((1.0 - t) * omega) / sinom;
  172. scale1 = sin(t * omega) / sinom;
  173. } else {
  174. // "from" and "to" quaternions are very close
  175. // ... so we can do a linear interpolation
  176. scale0 = 1.0 - t;
  177. scale1 = t;
  178. }
  179. // calculate final values
  180. res->x = scale0 * from->x + scale1 * to1[0];
  181. res->y = scale0 * from->y + scale1 * to1[1];
  182. res->z = scale0 * from->z + scale1 * to1[2];
  183. res->w = scale0 * from->w + scale1 * to1[3];
  184. }
  185. /*SDOC***********************************************************************
  186. Name: gluQuatLerp_EXT
  187. Action: Linearly interpolates between two quaternion positions
  188. Params: GLQUAT (first and second quaternion), GLfloat (interpolation
  189. parameter [0..1]), GL_QUAT (resulting quaternion; inbetween)
  190. Returns: nothing
  191. Comments: fast but not as nearly as smooth as Slerp
  192. ***********************************************************************EDOC*/
  193. void APIENTRY gluQuatLerp_EXT(GL_QUAT * from, GL_QUAT * to, GLfloat t,
  194. GL_QUAT * res)
  195. {
  196. GLfloat to1[4];
  197. GLdouble cosom;
  198. GLdouble scale0, scale1;
  199. // calc cosine
  200. cosom = from->x * to->x + from->y * to->y + from->z * to->z
  201. + from->w * to->w;
  202. // adjust signs (if necessary)
  203. if ( cosom < 0.0 )
  204. {
  205. to1[0] = - to->x;
  206. to1[1] = - to->y;
  207. to1[2] = - to->z;
  208. to1[3] = - to->w;
  209. } else {
  210. to1[0] = to->x;
  211. to1[1] = to->y;
  212. to1[2] = to->z;
  213. to1[3] = to->w;
  214. }
  215. // interpolate linearly
  216. scale0 = 1.0 - t;
  217. scale1 = t;
  218. // calculate final values
  219. res->x = scale0 * from->x + scale1 * to1[0];
  220. res->y = scale0 * from->y + scale1 * to1[1];
  221. res->z = scale0 * from->z + scale1 * to1[2];
  222. res->w = scale0 * from->w + scale1 * to1[3];
  223. }
  224. /*SDOC***********************************************************************
  225. Name: gluQuatNormalize_EXT
  226. Action: Normalizes quaternion (i.e. w^2 + x^2 + y^2 + z^2 = 1)
  227. Params: GL_QUAT* (quaternion)
  228. Returns: nothing
  229. Comments: none
  230. ***********************************************************************EDOC*/
  231. void APIENTRY gluQuatNormalize_EXT(GL_QUAT *quat)
  232. {
  233. GLfloat dist, square;
  234. square = quat->x * quat->x + quat->y * quat->y + quat->z * quat->z
  235. + quat->w * quat->w;
  236. if (square > 0.0)
  237. dist = (GLfloat)(1.0 / sqrt(square));
  238. else dist = 1;
  239. quat->x *= dist;
  240. quat->y *= dist;
  241. quat->z *= dist;
  242. quat->w *= dist;
  243. }
  244. /*SDOC***********************************************************************
  245. Name: gluQuatGetValue_EXT
  246. Action: Disassembles quaternion to an axis and an angle
  247. Params: GL_QUAT* (quaternion), GLfloat* (x, y, z - axis), GLfloat (angle)
  248. Returns: nothing
  249. Comments: NOTE: vector has been split into x, y, z so that you do not have
  250. to change your vector library (i.e. greater portability)
  251. NOTE2: angle is in RADIANS
  252. ***********************************************************************EDOC*/
  253. void APIENTRY gluQuatGetValue_EXT(GL_QUAT *quat, GLfloat *x, GLfloat *y,
  254. GLfloat *z, GLfloat *radians)
  255. {
  256. GLfloat len;
  257. GLfloat tx, ty, tz;
  258. // cache variables
  259. tx = quat->x;
  260. ty = quat->y;
  261. tz = quat->z;
  262. len = tx * tx + ty * ty + tz * tz;
  263. if (len > DELTA)
  264. {
  265. *x = tx * (1.0f / len);
  266. *y = ty * (1.0f / len);
  267. *z = tz * (1.0f / len);
  268. *radians = (GLfloat)(2.0 * acos(quat->w));
  269. }
  270. else {
  271. *x = 0.0;
  272. *y = 0.0;
  273. *z = 1.0;
  274. *radians = 0.0;
  275. }
  276. }
  277. /*SDOC***********************************************************************
  278. Name: gluQuatSetValue_EXT
  279. Action: Assembles quaternion from an axis and an angle
  280. Params: GL_QUAT* (quaternion), GLfloat (x, y, z - axis), GLfloat (angle)
  281. Returns: nothing
  282. Comments: NOTE: vector has been split into x, y, z so that you do not have
  283. to change your vector library (i.e. greater portability)
  284. NOTE2: angle has to be in RADIANS
  285. ***********************************************************************EDOC*/
  286. void APIENTRY gluQuatSetValue_EXT(GL_QUAT *quat, GLfloat x, GLfloat y,
  287. GLfloat z, GLfloat angle)
  288. {
  289. GLfloat temp, dist;
  290. // normalize
  291. temp = x*x + y*y + z*z;
  292. dist = (GLfloat)(1.0 / sqrt(temp));
  293. x *= dist;
  294. y *= dist;
  295. z *= dist;
  296. quat->x = x;
  297. quat->y = y;
  298. quat->z = z;
  299. quat->w = (GLfloat)cos(angle / 2.0f);
  300. }
  301. /*SDOC***********************************************************************
  302. Name: gluQuatScaleAngle_EXT
  303. Action: Scales the rotation angle of a quaternion
  304. Params: GL_QUAT* (quaternion), GLfloat (scale value)
  305. Returns: nothing
  306. Comments: none
  307. ***********************************************************************EDOC*/
  308. void APIENTRY gluQuatScaleAngle_EXT(GL_QUAT * quat, GLfloat scale)
  309. {
  310. GLfloat x, y, z; // axis
  311. GLfloat angle; // and angle
  312. gluQuatGetValue_EXT(quat, &x, &y, &z, &angle);
  313. gluQuatSetValue_EXT(quat, x, y, z, (angle * scale));
  314. }
  315. /*SDOC***********************************************************************
  316. Name: gluQuatInverse_EXT
  317. Action: Inverts quaternion's rotation ( q^(-1) )
  318. Params: GL_QUAT* (quaternion)
  319. Returns: nothing
  320. Comments: none
  321. Returns the inverse of the quaternion (1/q). check conjugate
  322. ***********************************************************************EDOC*/
  323. void APIENTRY gluQuatInverse_EXT(GL_QUAT *quat)
  324. {
  325. GLfloat norm, invNorm;
  326. norm = quat->x * quat->x + quat->y * quat->y + quat->z * quat->z
  327. + quat->w * quat->w;
  328. invNorm = (GLfloat) (1.0 / norm);
  329. quat->x = -quat->x * invNorm;
  330. quat->y = -quat->y * invNorm;
  331. quat->z = -quat->z * invNorm;
  332. quat->w = quat->w * invNorm;
  333. }
  334. /*SDOC***********************************************************************
  335. Name: gluQuatSetFromAx_EXT
  336. Action: Constructs quaternion to rotate from one direction vector to
  337. another
  338. Params: GLfloat (x1, y1, z1 - from vector),
  339. GLfloat (x2, y2, z2 - to vector), GL_QUAT* (resulting quaternion)
  340. Returns: nothing
  341. Comments: Two vectors have to be UNIT vectors (so make sure you normalize
  342. them before calling this function
  343. Some parts are heavily optimized so readability is not so great :(
  344. ***********************************************************************EDOC*/
  345. void APIENTRY gluQuatSetFromAx_EXT(GLfloat x1,GLfloat y1, GLfloat z1,
  346. GLfloat x2,GLfloat y2, GLfloat z2, GL_QUAT *quat)
  347. {
  348. GLfloat tx, ty, tz, temp, dist;
  349. GLfloat cost, len, ss;
  350. // get dot product of two vectors
  351. cost = x1 * x2 + y1 * y2 + z1 * z2;
  352. // check if parallel
  353. if (cost > 0.99999f) {
  354. quat->x = quat->y = quat->z = 0.0f;
  355. quat->w = 1.0f;
  356. return;
  357. }
  358. else if (cost < -0.99999f) { // check if opposite
  359. // check if we can use cross product of from vector with [1, 0, 0]
  360. tx = 0.0;
  361. ty = x1;
  362. tz = -y1;
  363. len = sqrt(ty*ty + tz*tz);
  364. if (len < DELTA)
  365. {
  366. // nope! we need cross product of from vector with [0, 1, 0]
  367. tx = -z1;
  368. ty = 0.0;
  369. tz = x1;
  370. }
  371. // normalize
  372. temp = tx*tx + ty*ty + tz*tz;
  373. dist = (GLfloat)(1.0 / sqrt(temp));
  374. tx *= dist;
  375. ty *= dist;
  376. tz *= dist;
  377. quat->x = tx;
  378. quat->y = ty;
  379. quat->z = tz;
  380. quat->w = 0.0;
  381. return;
  382. }
  383. // ... else we can just cross two vectors
  384. tx = y1 * z2 - z1 * y2;
  385. ty = z1 * x2 - x1 * z2;
  386. tz = x1 * y2 - y1 * x2;
  387. temp = tx*tx + ty*ty + tz*tz;
  388. dist = (GLfloat)(1.0 / sqrt(temp));
  389. tx *= dist;
  390. ty *= dist;
  391. tz *= dist;
  392. // we have to use half-angle formulae (sin^2 t = ( 1 - cos (2t) ) /2)
  393. ss = (float)sqrt(0.5f * (1.0f - cost));
  394. tx *= ss;
  395. ty *= ss;
  396. tz *= ss;
  397. // scale the axis to get the normalized quaternion
  398. quat->x = tx;
  399. quat->y = ty;
  400. quat->z = tz;
  401. // cos^2 t = ( 1 + cos (2t) ) / 2
  402. // w part is cosine of half the rotation angle
  403. quat->w = (float)sqrt(0.5f * (1.0f + cost));
  404. }
  405. /*SDOC***********************************************************************
  406. Name: gluQuatMul_EXT
  407. Action: Multiplies two quaternions
  408. Params: GL_QUAT ( q1 * q2 = res)
  409. Returns: nothing
  410. Comments: NOTE: multiplication is not commutative
  411. ***********************************************************************EDOC*/
  412. void APIENTRY gluQuatMul_EXT(GL_QUAT* q1, GL_QUAT* q2, GL_QUAT* res)
  413. {
  414. res->x = q1->w * q2->x + q1->x * q2->w + q1->y * q2->z - q1->z * q2->y;
  415. res->y = q1->w * q2->y + q1->y * q2->w + q1->z * q2->x - q1->x * q2->z;
  416. res->z = q1->w * q2->z + q1->z * q2->w + q1->x * q2->y - q1->y * q2->x;
  417. res->w = q1->w * q2->w - q1->x * q2->x - q1->y * q2->y - q1->z * q2->z;
  418. // make sure the resulting quaternion is a unit quat.
  419. gluQuatNormalize_EXT(res);
  420. }
  421. /*SDOC***********************************************************************
  422. Name: gluQuatMulNoNorm_EXT
  423. Action: Multiplies two quaternions but dont normalize
  424. Params: GL_QUAT ( q1 * q2 = res)
  425. Returns: nothing
  426. Comments: NOTE: multiplication is not commutative
  427. ***********************************************************************EDOC*/
  428. void APIENTRY gluQuatMulNoNorm_EXT(GL_QUAT* q1, GL_QUAT* q2, GL_QUAT* res)
  429. {
  430. res->x = q1->w * q2->x + q1->x * q2->w + q1->y * q2->z - q1->z * q2->y;
  431. res->y = q1->w * q2->y + q1->y * q2->w + q1->z * q2->x - q1->x * q2->z;
  432. res->z = q1->w * q2->z + q1->z * q2->w + q1->x * q2->y - q1->y * q2->x;
  433. res->w = q1->w * q2->w - q1->x * q2->x - q1->y * q2->y - q1->z * q2->z;
  434. }
  435. /*SDOC***********************************************************************
  436. Name: gluQuatAdd_EXT
  437. Action: Adds two quaternions
  438. Params: GL_QUAT* (q1 + q2 = res)
  439. Returns: nothing
  440. Comments: none
  441. ***********************************************************************EDOC*/
  442. void APIENTRY gluQuatAdd_EXT(GL_QUAT* q1, GL_QUAT* q2, GL_QUAT* res)
  443. {
  444. res->x = q1->x + q2->x;
  445. res->y = q1->y + q2->y;
  446. res->z = q1->z + q2->z;
  447. res->w = q1->w + q2->w;
  448. // make sure the resulting quaternion is a unit quat.
  449. gluQuatNormalize_EXT(res);
  450. }
  451. /*SDOC***********************************************************************
  452. Name: gluQuatSub_EXT
  453. Action: Subtracts two quaternions
  454. Params: GL_QUAT* (q1 - q2 = res)
  455. Returns: nothing
  456. Comments: none
  457. ***********************************************************************EDOC*/
  458. void APIENTRY gluQuatSub_EXT(GL_QUAT* q1, GL_QUAT* q2, GL_QUAT* res)
  459. {
  460. res->x = q1->x - q2->x;
  461. res->y = q1->y - q2->y;
  462. res->z = q1->z - q2->z;
  463. res->w = q1->w - q2->w;
  464. // make sure the resulting quaternion is a unit quat.
  465. gluQuatNormalize_EXT(res);
  466. }
  467. /*SDOC***********************************************************************
  468. Name: gluQuatDiv_EXT
  469. Action: Divide two quaternions
  470. Params: GL_QUAT* (q1 / q2 = res)
  471. Returns: nothing
  472. Comments: none
  473. ***********************************************************************EDOC*/
  474. void APIENTRY gluQuatDiv_EXT(GL_QUAT* q1, GL_QUAT* q2, GL_QUAT* res)
  475. {
  476. GL_QUAT q, r, s;
  477. gluQuatCopy_EXT(q2, &q);
  478. // invert vector
  479. q.x = -q.x;
  480. q.y = -q.y;
  481. q.z = -q.z;
  482. gluQuatMul_EXT(q1, &q, &r);
  483. gluQuatMul_EXT(&q, &q, &s);
  484. res->x = r.x / s.w;
  485. res->y = r.y / s.w;
  486. res->z = r.z / s.w;
  487. res->w = r.w / s.w;
  488. }
  489. /*SDOC***********************************************************************
  490. Name: gluQuatCopy_EXT
  491. Action: copies q1 into q2
  492. Params: GL_QUAT* (q1 and q2)
  493. Returns: nothing
  494. Comments: none
  495. ***********************************************************************EDOC*/
  496. void APIENTRY gluQuatCopy_EXT(GL_QUAT* q1, GL_QUAT* q2)
  497. {
  498. q2->x = q1->x;
  499. q2->y = q1->y;
  500. q2->z = q1->z;
  501. q2->w = q1->w;
  502. }
  503. /*SDOC***********************************************************************
  504. Name: gluQuatSquare_EXT
  505. Action: Square quaternion
  506. Params: GL_QUAT* (q1 * q1 = res)
  507. Returns: nothing
  508. Comments: none
  509. ***********************************************************************EDOC*/
  510. void APIENTRY gluQuatSquare_EXT(GL_QUAT* q1, GL_QUAT* res)
  511. {
  512. GLfloat tt;
  513. tt = 2 * q1->w;
  514. res->x = tt * q1->x;
  515. res->y = tt * q1->y;
  516. res->z = tt * q1->z;
  517. res->w = (q1->w * q1->w - q1->x * q1->x - q1->y * q1->y - q1->z * q1->z);
  518. }
  519. /*SDOC***********************************************************************
  520. Name: gluQuatSqrt_EXT
  521. Action: Find square root of a quaternion
  522. Params: GL_QUAT* (sqrt(q1) = res)
  523. Returns: nothing
  524. Comments: none
  525. ***********************************************************************EDOC*/
  526. void APIENTRY gluQuatSqrt_EXT(GL_QUAT* q1, GL_QUAT* res)
  527. {
  528. GLfloat length, m, r1, r2;
  529. GL_QUAT r;
  530. length = sqrt (q1->w * q1->w + q1->x * q1->x + q1->y * q1->y);
  531. if (length != 0.0)
  532. length = 1.0 / length;
  533. else length = 1.0;
  534. r.x = q1->x * length;
  535. r.y = q1->z * length;
  536. r.z = 0.0f;
  537. r.w = q1->w * length;
  538. m = 1.0 / sqrt (r.w * r.w + r.x * r.x);
  539. r1 = sqrt ((1.0 + r.y) * 0.5);
  540. r2 = sqrt ((1.0 - r.y) * 0.5);
  541. res->x = sqrt (length) * r2 * r.x * m;
  542. res->y = sqrt (length) * r1;
  543. res->z = q1->z;
  544. res->w = sqrt (length) * r1 * r.w * m;
  545. }
  546. /*SDOC***********************************************************************
  547. Name: gluQuatDot_EXT
  548. Action: Computes the dot product of two unit quaternions
  549. Params: GL_QUAT (first and second quaternion)
  550. Returns: (GLfloat) Dot product
  551. Comments: Quaternion has to be normalized (i.e. it's a unit quaternion)
  552. ***********************************************************************EDOC*/
  553. GLfloat APIENTRY gluQuatDot_EXT(GL_QUAT* q1, GL_QUAT* q2)
  554. {
  555. return (GLfloat)(q1->w * q2->w + q1->x * q2->x + q1->y * q2->y+q1->z*q2->z);
  556. }
  557. /*SDOC***********************************************************************
  558. Name: gluQuatLength_EXT
  559. Action: Calculates the length of a quaternion
  560. Params: GL_QUAT* (quaternion)
  561. Returns: GLfloat (length)
  562. Comments: none
  563. ***********************************************************************EDOC*/
  564. GLfloat APIENTRY gluQuatLength_EXT(GL_QUAT* q1)
  565. {
  566. return sqrt (q1->w * q1->w + q1->x * q1->x + q1->y * q1->y + q1->z * q1->z);
  567. }
  568. /*SDOC***********************************************************************
  569. Name: gluQuatNegate_EXT
  570. Action: Negates vector part of a quaternion
  571. Params: GL_QUAT (source and destination quaternion)
  572. Returns: nothing
  573. Comments: Source quaternion does NOT have to be normalized
  574. ***********************************************************************EDOC*/
  575. void APIENTRY gluQuatNegate_EXT(GL_QUAT* q1, GL_QUAT* q2)
  576. {
  577. gluQuatCopy_EXT(q1, q2);
  578. gluQuatNormalize_EXT(q2);
  579. q2->x = -q2->x;
  580. q2->y = -q2->y;
  581. q2->z = -q2->z;
  582. }
  583. /*SDOC***********************************************************************
  584. Name: gluQuatExp_EXT
  585. Action: Calculates exponent of a quaternion
  586. Params: GL_QUAT* (Source and destination quaternion)
  587. Returns: nothing
  588. Comments: none
  589. ***********************************************************************EDOC*/
  590. void APIENTRY gluQuatExp_EXT(GL_QUAT* q1, GL_QUAT* q2)
  591. {
  592. GLfloat len1, len2;
  593. len1 = (GLfloat) sqrt (q1->x * q1->x + q1->y * q1->y + q1->z * q1->z);
  594. if (len1 > 0.0)
  595. len2 = (GLfloat)sin(len1) / len1;
  596. else
  597. len2 = 1.0;
  598. q2->x = q1->x * len2;
  599. q2->y = q1->y * len2;
  600. q2->z = q1->z * len2;
  601. q2->w = cos (len1);
  602. }
  603. /*SDOC***********************************************************************
  604. Name: gluQuatLog_EXT
  605. Action: Calculates natural logarithm of a quaternion
  606. Params: GL_QUAT* (Source and destination quaternion)
  607. Returns: nothing
  608. Comments: none
  609. ***********************************************************************EDOC*/
  610. void APIENTRY gluQuatLog_EXT(GL_QUAT* q1, GL_QUAT* q2)
  611. {
  612. GLfloat length;
  613. length = sqrt (q1->x * q1->x + q1->y * q1->y + q1->z * q1->z);
  614. //make sure we do not divide by 0
  615. if (q1->w != 0.0)
  616. length = atan (length / q1->w);
  617. else length = (GLfloat)M_PI/2;
  618. q2->w = 0.0f;
  619. q2->x = q1->x * length;
  620. q2->y = q1->y * length;
  621. q2->z = q1->z * length;
  622. }
  623. /*SDOC***********************************************************************
  624. Name: gluQuatLnDif_EXT
  625. Action: Computes the "natural log difference" of two quaternions,
  626. q1 and q2 as ln(qinv(q1)*q2)
  627. Params: GL_QUAT* (Source quaternions and a destination quaternion)
  628. Returns: nothing
  629. Comments: none
  630. ***********************************************************************EDOC*/
  631. /*void APIENTRY gluQuatLnDif_EXT(GL_QUAT *q1, GL_QUAT *q2, GL_QUAT *res)
  632. {
  633. GL_QUAT inv, dif, temp;
  634. GLfloat len, len1, s;
  635. qt_inverse (a, &inv);
  636. qt_mul (&inv, b, &dif);
  637. len = sqrt (dif.x*dif.x + dif.y*dif.y + dif.z*dif.z);
  638. s = qt_dot (a, b);
  639. if (s != 0.0) len1 = atan (len / s); else len1 = M_PI/2;
  640. if (len != 0.0) len1 /= len;
  641. temp.w = 0.0;
  642. temp.x = dif.x * len1;
  643. temp.y = dif.y * len1;
  644. temp.z = dif.z * len1;
  645. qt_copy (&temp, out);
  646. }*/
  647. // cleanup stuff we changed
  648. #if defined (WIN32)
  649. #pragma warning( default : 4244 ) // set it to default again
  650. #endif