/SHGeometryKit/Src/G3DQuatFunc.c

https://github.com/xxhp/HooleyBits · C · 679 lines · 436 code · 129 blank · 114 comment · 32 complexity · e0170c731ab5167a0be7420fc67f6ac4 MD5 · raw file

  1. /*
  2. * G3DQuatFunc.c created by robert on 2001-01-05 15:07:36 +0000
  3. *
  4. * Project SHGeometryKit
  5. *
  6. * Created with ProjectCenter - http://www.projectcenter.ch
  7. *
  8. * $Id: G3DQuatFunc.c,v 1.2 2002/10/27 11:51:42 probert Exp $
  9. */
  10. #include "G3DQuatFunc.h"
  11. #include "G3DDefs.h"
  12. /*
  13. * Declarations
  14. *
  15. */
  16. void G3DMultiplyQuatf(float dst[4],CFLOAT a[4],CFLOAT b[4]);
  17. void G3DMultiplyQuatd(double dst[4],CDOUBLE a[4],CDOUBLE b[4]);
  18. void G3DQuatFromAngleAxisf(float quat[4], CFLOAT angle, CFLOAT axis[3]);
  19. void G3DQuatFromAngleAxisd(double quat[4], CDOUBLE angle, CDOUBLE axis[3]);
  20. void G3DQuatFromRotationVectorf(float quat[4], CFLOAT axis[3]);
  21. void G3DQuatFromRotationVectord(double quat[4], CDOUBLE axis[3]);
  22. void G3DAngleAxisFromQuatf(float *angle, float axis[3], CFLOAT quat[4]);
  23. void G3DAngleAxisFromQuatd(double *angle, double axis[3], CDOUBLE quat[4]);
  24. void G3DMatrixFromQuatf(float m[16], CFLOAT q[4]);
  25. void G3DMatrixFromQuatd(double m[16], CDOUBLE q[4]);
  26. void G3DQuatFromMatrixf(float q[4], CFLOAT m[16]);
  27. void G3DQuatFromMatrixd(double q[4], CDOUBLE m[16]);
  28. void G3DEulerRepFromQuatf(float res[3], CFLOAT quat[4]);
  29. void G3DEulerRepFromQuatd(double res[3], CDOUBLE quat[4]);
  30. void G3DQuatFromEulerRepf(float q[4],CFLOAT euler[3]);
  31. void G3DQuatFromEulerRepd(double q[4],CDOUBLE euler[3]);
  32. void G3DInterpolateQuatf(float res[4], CFLOAT from[4], CFLOAT to[4], CFLOAT t);
  33. void G3DInterpolateQuatd(double rs[4], CDOUBLE f[4], CDOUBLE to[4], CDOUBLE t);
  34. /******************************************************************************
  35. *
  36. * Quaternion Functions
  37. *
  38. *****************************************************************************/
  39. __G3DI__ void G3DMultiplyQuatf(float dst[4],CFLOAT a[4], CFLOAT b[4])
  40. {
  41. float s1 = (a[2] - a[1]) * (b[1] - b[2]);
  42. float s2 = (a[3] + a[0]) * (b[3] + b[0]);
  43. float s3 = (a[3] - a[0]) * (b[1] + b[2]);
  44. float s4 = (a[2] + a[1]) * (b[3] - b[0]);
  45. float s5 = (a[2] - a[0]) * (b[0] - b[1]);
  46. float s6 = (a[2] + a[0]) * (b[0] + b[1]);
  47. float s7 = (a[3] + a[1]) * (b[3] - b[2]);
  48. float s8 = (a[3] - a[1]) * (b[3] + b[2]);
  49. float s9 = s6 + s7 + s8;
  50. float t = (s5 + s9)*0.5f;
  51. dst[0] = s2 + t - s9;
  52. dst[1] = s3 + t - s8;
  53. dst[2] = s4 + t - s7;
  54. dst[3] = s1 + t - s6;
  55. }
  56. __G3DI__ void G3DMultiplyQuatd(double dst[4],CDOUBLE a[4], CDOUBLE b[4])
  57. {
  58. double s1 = (a[2] - a[1]) * (b[1] - b[2]);
  59. double s2 = (a[3] + a[0]) * (b[3] + b[0]);
  60. double s3 = (a[3] - a[0]) * (b[1] + b[2]);
  61. double s4 = (a[2] + a[1]) * (b[3] - b[0]);
  62. double s5 = (a[2] - a[0]) * (b[0] - b[1]);
  63. double s6 = (a[2] + a[0]) * (b[0] + b[1]);
  64. double s7 = (a[3] + a[1]) * (b[3] - b[2]);
  65. double s8 = (a[3] - a[1]) * (b[3] + b[2]);
  66. double s9 = s6 + s7 + s8;
  67. double t = (s5 + s9)*0.5f;
  68. dst[0] = s2 + t - s9;
  69. dst[1] = s3 + t - s8;
  70. dst[2] = s4 + t - s7;
  71. dst[3] = s1 + t - s6;
  72. }
  73. __G3DI__ void G3DQuatFromAngleAxisf(float quat[4], CFLOAT angle, CFLOAT axis[3])
  74. {
  75. float ta = angle * DEG2RAD / 2.0f;
  76. float sina = -sin(ta);
  77. float len = axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2];
  78. if (len < G3DEPSILON) {
  79. quat[0] = quat[1] = quat[2] = quat[3] = 0.0f;
  80. return;
  81. }
  82. /*
  83. * Normalising the axis if needed
  84. */
  85. if (len != 1.0f) {
  86. float tmp[3];
  87. float scale;
  88. scale = 1.0f/sqrt(len);
  89. tmp[0] = axis[0] * scale;
  90. tmp[1] = axis[1] * scale;
  91. tmp[2] = axis[2] * scale;
  92. /* Imaginary part */
  93. quat[0] = sina * tmp[0];
  94. quat[1] = sina * tmp[1];
  95. quat[2] = sina * tmp[2];
  96. }
  97. else {
  98. /* Imaginary part */
  99. quat[0] = sina * axis[0];
  100. quat[1] = sina * axis[1];
  101. quat[2] = sina * axis[2];
  102. }
  103. /* Real part */
  104. quat[3] = cos(ta);
  105. }
  106. __G3DI__ void G3DQuatFromAngleAxisd(double quat[4], CDOUBLE angle, CDOUBLE axis[3])
  107. {
  108. double ta = angle * DEG2RAD / 2.0;
  109. double sina = -sin(ta);
  110. double len = axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2];
  111. if (len < G3DEPSILON) {
  112. quat[0] = quat[1] = quat[2] = quat[3] = 0.0f;
  113. return;
  114. }
  115. /*
  116. * Normalising the axis if needed
  117. */
  118. if (len != 1.0) {
  119. double tmp[3];
  120. double scale;
  121. scale = 1.0/sqrt(len);
  122. tmp[0] = axis[0] * scale;
  123. tmp[1] = axis[1] * scale;
  124. tmp[2] = axis[2] * scale;
  125. /* Imaginary part */
  126. quat[0] = sina * tmp[0];
  127. quat[1] = sina * tmp[1];
  128. quat[2] = sina * tmp[2];
  129. }
  130. else {
  131. /* Imaginary part */
  132. quat[0] = sina * axis[0];
  133. quat[1] = sina * axis[1];
  134. quat[2] = sina * axis[2];
  135. }
  136. /* Real part */
  137. quat[3] = cos(ta);
  138. }
  139. __G3DI__ void G3DQuatFromRotationVectorf(float quat[4], CFLOAT axis[3])
  140. {
  141. float len2 = axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2];
  142. float ta;
  143. float sina;
  144. float scale;
  145. float len;
  146. if (len2 < G3DEPSILON) {
  147. quat[3] = 1.0f;
  148. quat[0] = quat[1] = quat[2] = 0.0f;
  149. return;
  150. }
  151. len = sqrt(len2);
  152. ta = 0.5f * len; // length == angle
  153. sina = - sin(ta);
  154. scale = sina / len;
  155. /* Imaginary part */
  156. quat[0] = axis[0] * scale;
  157. quat[1] = axis[1] * scale;
  158. quat[2] = axis[2] * scale;
  159. /* Real part */
  160. quat[3] = cos(ta);
  161. }
  162. __G3DI__ void G3DQuatFromRotationVectord(double quat[4], CDOUBLE axis[3])
  163. {
  164. double len2 = axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2];
  165. double ta;
  166. double sina;
  167. double scale;
  168. double len;
  169. if (len2 < G3DEPSILON) {
  170. quat[3] = 1.0;
  171. quat[0] = quat[1] = quat[2] = 0.0;
  172. return;
  173. }
  174. len = sqrt(len2);
  175. ta = 0.5 * len; // length == angle
  176. sina = - sin(ta);
  177. scale = sina / len;
  178. /* Imaginary part */
  179. quat[0] = axis[0] * scale;
  180. quat[1] = axis[1] * scale;
  181. quat[2] = axis[2] * scale;
  182. /* Real part */
  183. quat[3] = cos(ta);
  184. }
  185. __G3DI__ void G3DAngleAxisFromQuatf(float *angle, float axis[3], CFLOAT quat[4])
  186. {
  187. float a = acos(quat[3]);
  188. float s = -sin(a);
  189. *angle = 2.0f * a * RAD2DEG;
  190. if (s == 0.0) {
  191. axis[0] = 0.0f;
  192. axis[1] = 0.0f;
  193. axis[2] = 1.0f;
  194. }
  195. else {
  196. float scale = 1.0f/s;
  197. axis[0] = quat[0] * scale;
  198. axis[1] = quat[1] * scale;
  199. axis[2] = quat[2] * scale;
  200. }
  201. }
  202. __G3DI__ void G3DAngleAxisFromQuatd(double *angle, double axis[3], CDOUBLE quat[4])
  203. {
  204. double a = acos(quat[3]);
  205. double s = -sin(a);
  206. *angle = 2.0 * a * RAD2DEG;
  207. if (s == 0.0) {
  208. axis[0] = 0.0f;
  209. axis[1] = 0.0f;
  210. axis[2] = 1.0f;
  211. }
  212. else {
  213. double scale = 1.0/s;
  214. axis[0] = quat[0] * scale;
  215. axis[1] = quat[1] * scale;
  216. axis[2] = quat[2] * scale;
  217. }
  218. }
  219. __G3DI__ void G3DMatrixFromQuatf(float m[16], CFLOAT q[4])
  220. {
  221. float t_sq0 = 2*SQR(q[0]);
  222. float t_sq1 = 2*SQR(q[1]);
  223. float t_sq2 = 2*SQR(q[2]);
  224. float t_q0 = 2 * q[0];
  225. float t_q1 = 2 * q[1];
  226. float t_q3 = 2 * q[3];
  227. float t_q3_q0 = t_q3 * q[0];
  228. float t_q3_q1 = t_q3 * q[1];
  229. float t_q3_q2 = t_q3 * q[2];
  230. float t_q0_q1 = t_q0 * q[1];
  231. float t_q0_q2 = t_q0 * q[2];
  232. float t_q1_q2 = t_q1 * q[2];
  233. m[0] = 1.0f-t_sq1-t_sq2;
  234. m[1] = t_q0_q1+t_q3_q2;
  235. m[2] = t_q0_q2-t_q3_q1;
  236. m[3] = 0.0f;
  237. m[4] = t_q0_q1-t_q3_q2;
  238. m[5] = 1.0f-t_sq0-t_sq2;
  239. m[6] = t_q1_q2+t_q3_q0;
  240. m[7] = 0.0f;
  241. m[8] = t_q0_q2+t_q3_q1;
  242. m[9] = t_q1_q2-t_q3_q0;
  243. m[10] = 1.0f-t_sq0-t_sq1;
  244. m[11] = 0.0f;
  245. m[12] = 0.0f;
  246. m[13] = 0.0f;
  247. m[14] = 0.0f;
  248. m[15] = 1.0f;
  249. }
  250. __G3DI__ void G3DMatrixFromQuatd(double m[16], CDOUBLE q[4])
  251. {
  252. double t_sq0 = 2*SQR(q[0]);
  253. double t_sq1 = 2*SQR(q[1]);
  254. double t_sq2 = 2*SQR(q[2]);
  255. double t_q0 = 2 * q[0];
  256. double t_q1 = 2 * q[1];
  257. double t_q3 = 2 * q[3];
  258. double t_q3_q0 = t_q3 * q[0];
  259. double t_q3_q1 = t_q3 * q[1];
  260. double t_q3_q2 = t_q3 * q[2];
  261. double t_q0_q1 = t_q0 * q[1];
  262. double t_q0_q2 = t_q0 * q[2];
  263. double t_q1_q2 = t_q1 * q[2];
  264. m[0] = 1.0f-t_sq1-t_sq2;
  265. m[1] = t_q0_q1+t_q3_q2;
  266. m[2] = t_q0_q2-t_q3_q1;
  267. m[3] = 0.0f;
  268. m[4] = t_q0_q1-t_q3_q2;
  269. m[5] = 1.0f-t_sq0-t_sq2;
  270. m[6] = t_q1_q2+t_q3_q0;
  271. m[7] = 0.0f;
  272. m[8] = t_q0_q2+t_q3_q1;
  273. m[9] = t_q1_q2-t_q3_q0;
  274. m[10] = 1.0f-t_sq0-t_sq1;
  275. m[11] = 0.0f;
  276. m[12] = 0.0;
  277. m[13] = 0.0;
  278. m[14] = 0.0;
  279. m[15] = 1.0;
  280. }
  281. __G3DI__ void G3DQuatFromMatrixf(float quat[4], CFLOAT m[16])
  282. {
  283. float tr;
  284. float q[4];
  285. /*
  286. * m[15] == 1.0f if it is a rotation matrix - and I assume it is!
  287. */
  288. tr = m[0] + m[5] + m[10];
  289. tr++;
  290. if (tr > 0.0f) {
  291. float s = 0.5f /sqrt(tr);
  292. quat[3] = 0.25f / s;
  293. quat[0] = s * (m[9]-m[6]);
  294. quat[1] = s * (m[2]-m[8]);
  295. quat[2] = s * (m[4]-m[1]);
  296. }
  297. else {
  298. float s;
  299. int i = 0;
  300. int j;
  301. int k;
  302. int nxt[3] = {1,2,0};
  303. if (m[5] > m[0]) {
  304. i = 1;
  305. }
  306. if (m[10] > (*(m+i)+i)) {
  307. i = 2;
  308. }
  309. j = nxt[i];
  310. k = nxt[j];
  311. s = sqrt(1.0f + ((*(m+i)+i) - ((*(m+j)+j) - (*(m+k)+k)))) * 2.0f;
  312. /*
  313. * s cannot be 0.0
  314. */
  315. q[i] = 0.5f / s;
  316. q[3] = ((*(m+k)+j) + (*(m+j)+k)) / s;
  317. q[j] = ((*(m+j)+i) + (*(m+i)+j)) / s;
  318. q[k] = ((*(m+k)+i) + (*(m+i)+k)) / s;
  319. quat[0] = q[0];
  320. quat[1] = q[1];
  321. quat[2] = q[2];
  322. quat[3] = q[3];
  323. }
  324. }
  325. __G3DI__ void G3DQuatFromMatrixd(double quat[4], CDOUBLE m[16])
  326. {
  327. float tr;
  328. float q[4];
  329. /*
  330. * m[15] == 1.0 if it is a rotation matrix - and I assume it is!
  331. */
  332. tr = m[0] + m[5] + m[10];
  333. tr++;
  334. if (tr > 0.0) {
  335. float s = 0.5 /sqrt(tr);
  336. quat[3] = 0.25 / s;
  337. quat[0] = s * (m[9]-m[6]);
  338. quat[1] = s * (m[2]-m[8]);
  339. quat[2] = s * (m[4]-m[1]);
  340. }
  341. else {
  342. float s;
  343. int i = 0;
  344. int j;
  345. int k;
  346. int nxt[3] = {1,2,0};
  347. if (m[5] > m[0]) {
  348. i = 1;
  349. }
  350. if (m[10] > (*(m+i)+i)) {
  351. i = 2;
  352. }
  353. j = nxt[i];
  354. k = nxt[j];
  355. s = sqrt(1.0 + ((*(m+i)+i) - ((*(m+j)+j) - (*(m+k)+k)))) * 2.0;
  356. /*
  357. * s cannot be 0.0
  358. */
  359. q[i] = 0.5 / s;
  360. q[3] = ((*(m+k)+j) + (*(m+j)+k)) / s;
  361. q[j] = ((*(m+j)+i) + (*(m+i)+j)) / s;
  362. q[k] = ((*(m+k)+i) + (*(m+i)+k)) / s;
  363. quat[0] = q[0];
  364. quat[1] = q[1];
  365. quat[2] = q[2];
  366. quat[3] = q[3];
  367. }
  368. }
  369. /* from jeffl@darwin3d.com */
  370. __G3DI__ void G3DEulerRepFromQuatf(float res[3], CFLOAT quat[4])
  371. {
  372. // UPDATE DOCUMENTATION!
  373. /*
  374. float matrix[9];
  375. dobule cx,sx;
  376. float cy,sy,yr;
  377. float cz,sz;
  378. // CONVERT QUATERNION TO MATRIX - I DON'T REALLY NEED ALL OF IT
  379. matrix[0][0] = SG_ONE - (SG_TWO * quat[SG_Y] * quat[SG_Y])
  380. - (SG_TWO * quat[SG_Z] * quat[SG_Z]);
  381. //matrix[0][1] = (SG_TWO * quat->x * quat->y) - (SG_TWO * quat->w * quat->z);
  382. //matrix[0][2] = (SG_TWO * quat->x * quat->z) + (SG_TWO * quat->w * quat->y);
  383. matrix[1][0] = (SG_TWO * quat[SG_X] * quat[SG_Y]) +
  384. (SG_TWO * quat[SG_W] * quat[SG_Z]);
  385. //matrix[1][1] = SG_ONE - (SG_TWO * quat->x * quat->x)
  386. // - (SG_TWO * quat->z * quat->z);
  387. //matrix[1][2] = (SG_TWO * quat->y * quat->z) - (SG_TWO * quat->w * quat->x);
  388. matrix[2][0] = (SG_TWO * quat[SG_X] * quat[SG_Z]) -
  389. (SG_TWO * quat[SG_W] * quat[SG_Y]);
  390. matrix[2][1] = (SG_TWO * quat[SG_Y] * quat[SG_Z]) +
  391. (SG_TWO * quat[SG_W] * quat[SG_X]);
  392. matrix[2][2] = SG_ONE - (SG_TWO * quat[SG_X] * quat[SG_X])
  393. - (SG_TWO * quat[SG_Y] * quat[SG_Y]);
  394. sy = -matrix[2][0];
  395. cy = sqrt(SG_ONE - (sy * sy));
  396. yr = atan2(sy,cy);
  397. euler[1] = yr * SG_RADIANS_TO_DEGREES ;
  398. // AVOID DIVIDE BY ZERO ERROR ONLY WHERE Y= +-90 or +-270
  399. // NOT CHECKING cy BECAUSE OF PRECISION ERRORS
  400. if (sy != SG_ONE && sy != -SG_ONE)
  401. {
  402. cx = matrix[2][2] / cy;
  403. sx = matrix[2][1] / cy;
  404. euler[0] = ((float)atan2(sx,cx)) * SG_RADIANS_TO_DEGREES ;
  405. cz = matrix[0][0] / cy;
  406. sz = matrix[1][0] / cy;
  407. euler[2] = (atan2(sz,cz)) * SG_RADIANS_TO_DEGREES ;
  408. }
  409. else
  410. {
  411. // SINCE Cos(Y) IS 0, I AM SCREWED. ADOPT THE STANDARD Z = 0
  412. // I THINK THERE IS A WAY TO FIX THIS BUT I AM NOT SURE. EULERS SUCK
  413. // NEED SOME MORE OF THE MATRIX TERMS NOW
  414. matrix[1][1] = SG_ONE - (SG_TWO * quat[SG_X] * quat[SG_X])
  415. - (SG_TWO * quat[SG_Z] * quat[SG_Z]);
  416. matrix[1][2] = (SG_TWO * quat[SG_Y] * quat[SG_Z]) -
  417. (SG_TWO * quat[SG_W] * quat[SG_X]);
  418. cx = matrix[1][1];
  419. sx = -matrix[1][2];
  420. euler[0] = (atan2(sx,cx)) * SG_RADIANS_TO_DEGREES ;
  421. cz = SG_ONE ;
  422. sz = SG_ZERO ;
  423. euler[2] = (atan2(sz,cz)) * SG_RADIANS_TO_DEGREES ;
  424. }
  425. */
  426. }
  427. __G3DI__ void G3DEulerRepFromQuatd(double res[3], CDOUBLE quat[4])
  428. {
  429. // UPDATE DOCUMENTATION!
  430. }
  431. __G3DI__ void G3DQuatFromEulerRepf(float q[4],CFLOAT euler[3])
  432. {
  433. float cr, cp, cy;
  434. float sr, sp, sy;
  435. float cpcy, spsy;
  436. float rh = euler[0]/2.0f;
  437. float ph = euler[1]/2.0f;
  438. float yh = euler[2]/2.0f;
  439. cr = (float)cos(rh);
  440. cp = (float)cos(ph);
  441. cy = (float)cos(yh);
  442. sr = (float)sin(rh);
  443. sp = (float)sin(ph);
  444. sy = (float)sin(yh);
  445. cpcy = cp*cy;
  446. spsy = sp*sy;
  447. q[0] = sr * cpcy - cr * spsy;
  448. q[1] = cr * sp * cy + sr * cp * sy;
  449. q[2] = cr * cp * sy - sr * sp * cy;
  450. q[3] = cr * cpcy + sr * spsy;
  451. }
  452. __G3DI__ void G3DQuatFromEulerRepd(double q[4],CDOUBLE euler[3])
  453. {
  454. double cr, cp, cy;
  455. double sr, sp, sy;
  456. double cpcy, spsy;
  457. double rh = euler[0]/2.0f;
  458. double ph = euler[1]/2.0f;
  459. double yh = euler[2]/2.0f;
  460. cr = (double)cos(rh);
  461. cp = (double)cos(ph);
  462. cy = (double)cos(yh);
  463. sr = (double)sin(rh);
  464. sp = (double)sin(ph);
  465. sy = (double)sin(yh);
  466. cpcy = cp*cy;
  467. spsy = sp*sy;
  468. q[0] = sr * cpcy - cr * spsy;
  469. q[1] = cr * sp * cy + sr * cp * sy;
  470. q[2] = cr * cp * sy - sr * sp * cy;
  471. q[3] = cr * cpcy + sr * spsy;
  472. }
  473. __G3DI__ void G3DInterpolateQuatf(float res[4], CFLOAT from[4], CFLOAT to[4], CFLOAT t)
  474. {
  475. float fixedTo[4];
  476. float omega, v, sinom, scale0, scale1;
  477. v = from[0]*to[0] + from[1]*to[1] + from[2]*to[2] + from[3]*to[3];
  478. if (v < 0.0f) {
  479. v = -v;
  480. fixedTo[0] = - to[0];
  481. fixedTo[1] = - to[1];
  482. fixedTo[2] = - to[2];
  483. fixedTo[3] = - to[3];
  484. }
  485. else {
  486. fixedTo[0] = to[0];
  487. fixedTo[1] = to[1];
  488. fixedTo[2] = to[2];
  489. fixedTo[3] = to[3];
  490. }
  491. /* calculate SLERP coefficients (linear if from and to are close enough) */
  492. if ((1.0f - v) > 0.0f) {
  493. omega = acos(v);
  494. sinom = sin(omega);
  495. scale0 = sin((1.0f - t) * omega) / sinom;
  496. scale1 = sin(t * omega) / sinom;
  497. }
  498. else {
  499. scale0 = 1.0f - t;
  500. scale1 = t;
  501. }
  502. res[0] = scale0 * from[0] + scale1 * fixedTo[0];
  503. res[1] = scale0 * from[1] + scale1 * fixedTo[1];
  504. res[2] = scale0 * from[2] + scale1 * fixedTo[2];
  505. res[3] = scale0 * from[3] + scale1 * fixedTo[3];
  506. }
  507. __G3DI__ void G3DInterpolateQuatd(double res[4], CDOUBLE from[4], CDOUBLE to[4], CDOUBLE t)
  508. {
  509. double fixedTo[4];
  510. double omega, v, sinom, scale0, scale1;
  511. v = from[0]*to[0] + from[1]*to[1] + from[2]*to[2] + from[3]*to[3];
  512. if (v < 0.0) {
  513. v = -v;
  514. fixedTo[0] = - to[0];
  515. fixedTo[1] = - to[1];
  516. fixedTo[2] = - to[2];
  517. fixedTo[3] = - to[3];
  518. }
  519. else {
  520. fixedTo[0] = to[0];
  521. fixedTo[1] = to[1];
  522. fixedTo[2] = to[2];
  523. fixedTo[3] = to[3];
  524. }
  525. /* calculate SLERP coefficients (linear if from and to are close enough) */
  526. if ((1.0 - v) > 0.0) {
  527. omega = acos(v);
  528. sinom = sin(omega);
  529. scale0 = sin((1.0 - t) * omega) / sinom;
  530. scale1 = sin(t * omega) / sinom;
  531. }
  532. else {
  533. scale0 = 1.0 - t;
  534. scale1 = t;
  535. }
  536. res[0] = scale0 * from[0] + scale1 * fixedTo[0];
  537. res[1] = scale0 * from[1] + scale1 * fixedTo[1];
  538. res[2] = scale0 * from[2] + scale1 * fixedTo[2];
  539. res[3] = scale0 * from[3] + scale1 * fixedTo[3];
  540. }