Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mtk3d.cpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*===============================================================
  3. * Project: Mongoose Tool Kit
  4. * Author : Terry 'Mongoose' Hendrix
  5. * Website: http://www.westga.edu/~stu7440/
  6. * Email : stu7440@westga.edu
  7. * Object :
  8. * Comment: 3d math util functions.
  9. *
  10. * FIXME: OpenGL matrices are col major OOPS!
  11. * some are using col some aren't
  12. *
  13. *-- History -----------------------------------------------
  14. *
  15. * 2001.11.23:
  16. * Mongoose - Move to OpenGL compatible matrices
  17. *
  18. * 2000-03-25:
  19. * Mongoose - Recreated from GooseEgg prototyping
  20. *
  21. * 1999-06-14:
  22. * Mongoose - Created
  23. ==============================================================*/
  24. #include <math.h>
  25. #include <stdio.h>
  26. #include "mtk3d.h"
  27. /*
  28. double mtk3d_norm3d(double u[3])
  29. {
  30. return(sqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]));
  31. }
  32. double mtk3d_norm2d(double u[2])
  33. {
  34. return(sqrt(u[0]*u[0]+u[1]*u[1]));
  35. }
  36. */
  37. vec_t mtkRandNum(vec_t from, vec_t to)
  38. {
  39. return from + (to*rand()/(RAND_MAX+1.0));
  40. }
  41. // Heh, this is scary... try to avoid many indexing computations
  42. void mtkVectorMatrixMult4dv(double v[4], matrix_t m, double result[4])
  43. {
  44. #ifdef OBSOLETE
  45. int i, j;
  46. for (i = 0; i < 4; i++)
  47. {
  48. result[i] = 0;
  49. for (j = 0; j < 4; j++)
  50. {
  51. result[i] += m[i][j] * v[j];
  52. }
  53. }
  54. #else
  55. /////////////////////////////////////////////
  56. // 0,0 - 0; 0,1 - 1; 0,2 - 2; 0,3 - 3
  57. // 1,0 - 4; 1,1 - 5; 1,2 - 6; 1,3 - 7
  58. // 2,0 - 8; 2,1 - 9; 2,2 - 10; 2,3 - 11
  59. // 3,0 - 12; 3,1 - 13; 3,2 - 14; 3,3 - 15
  60. /////////////////////////////////////////////
  61. // Col major?
  62. //result[0] = m[ 0] * v[0] + m[ 4] * v[1] + m[ 8] * v[2] + m[12] * v[3];
  63. //result[1] = m[ 1] * v[0] + m[ 5] * v[1] + m[ 9] * v[2] + m[13] * v[3];
  64. //result[2] = m[ 2] * v[0] + m[ 6] * v[1] + m[10] * v[2] + m[14] * v[3];
  65. result[0] = m[ 0] * v[0] + m[ 1] * v[1] + m[ 2] * v[2] + m[ 3] * v[3];
  66. result[1] = m[ 4] * v[0] + m[ 5] * v[1] + m[ 6] * v[2] + m[ 7] * v[3];
  67. result[2] = m[ 8] * v[0] + m[ 9] * v[1] + m[10] * v[2] + m[11] * v[3];
  68. result[3] = m[12] * v[0] + m[13] * v[1] + m[14] * v[2] + m[15] * v[3];
  69. #endif
  70. }
  71. void mtkMatrixPrint(matrix_t matrix)
  72. {
  73. #ifdef OBSOLETE
  74. printf("matrix = {\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
  75. matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
  76. matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
  77. matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
  78. matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
  79. #else
  80. printf("matrix = {\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
  81. matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
  82. matrix[ 4], matrix[ 5], matrix[ 6], matrix[ 7],
  83. matrix[ 8], matrix[ 9], matrix[10], matrix[11],
  84. matrix[12], matrix[13], matrix[14], matrix[15]);
  85. #endif
  86. }
  87. vec_t mtkDist2d(vec_t x, vec_t y, vec_t x2, vec_t y2)
  88. {
  89. return (sqrt( ((x2 - x)*(x2 - x)) + ((y2 - y)*(y2 - y)) ));
  90. }
  91. vec_t mtkDist3d(vec_t x, vec_t y, vec_t z,
  92. vec_t x2, vec_t y2, vec_t z2)
  93. {
  94. return (sqrt( ((x2 - x)*(x2 - x))+((y2 - y)*(y2 - y))+((z2 - z)*(z2 - z))));
  95. }
  96. vec_t mtkDegToRad(vec_t degrees)
  97. {
  98. return ((degrees / 180.0) * MTK_PI); // degrees * (180.0 / MTK_PI);
  99. }
  100. vec_t mtkRadToDeg(vec_t rad)
  101. {
  102. return ((rad / MTK_PI) * 180.0); // rad * (MTK_PI / 180.0);
  103. }
  104. void mtkVectorMatrixMult(vec3_t v, matrix_t m, vec3_t result)
  105. {
  106. result[0] = m[ 0] * v[0] + m[ 1] * v[1] + m[ 2] * v[2] + m[ 3] * v[3];
  107. result[1] = m[ 4] * v[0] + m[ 5] * v[1] + m[ 6] * v[2] + m[ 7] * v[3];
  108. result[2] = m[ 8] * v[0] + m[ 9] * v[1] + m[10] * v[2] + m[11] * v[3];
  109. }
  110. // Vector from two points
  111. void mtkVectorSubtract(vec3_t a, vec3_t b, vec3_t result)
  112. {
  113. result[0] = a[0] - b[0];
  114. result[1] = a[1] - b[1];
  115. result[2] = a[2] - b[2];
  116. }
  117. void mtkVectorAdd(vec3_t a, vec3_t b, vec3_t result)
  118. {
  119. result[0] = a[0] + b[0];
  120. result[1] = a[1] + b[1];
  121. result[2] = a[2] + b[2];
  122. }
  123. // Magnitude
  124. vec_t mtkVectorNorm(vec3_t v)
  125. {
  126. return (vec_t)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  127. }
  128. void mtkVectorNormalize(vec3_t v, vec3_t result)
  129. {
  130. vec_t mag = mtkVectorNorm(v);
  131. result[0] = v[0] / mag;
  132. result[1] = v[1] / mag;
  133. result[2] = v[2] / mag;
  134. }
  135. void mtkVectorCrossProduct(vec3_t a, vec3_t b, vec3_t normal)
  136. {
  137. normal[0] = a[1]*b[2] - a[2]*b[1];
  138. normal[0] = a[2]*b[0] - a[0]*b[2];
  139. normal[0] = a[0]*b[1] - a[1]*b[0];
  140. }
  141. vec_t mtkVectorDotProduct(vec3_t a, vec3_t b)
  142. {
  143. return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
  144. }
  145. // Heh, this is scary... try to avoid many indexing computations
  146. void mtkMatrixMult(matrix_t m1, matrix_t m2, matrix_t mp)
  147. {
  148. #ifdef MTK3D_MULT_DIM_MATRIX
  149. int i,j;
  150. for (i = 0; i < 4; i++)
  151. {
  152. for (j = 0 ; j < 4; j++)
  153. {
  154. mp[i][j] = m1[i][0] * m2[0][j] +
  155. m1[i][1] * m2[1][j] +
  156. m1[i][2] * m2[2][j] +
  157. m1[i][3] * m2[3][j];
  158. }
  159. }
  160. #else
  161. /////////////////////////////////////////////
  162. // 0,0 - 0; 0,1 - 1; 0,2 - 2; 0,3 - 3
  163. // 1,0 - 4; 1,1 - 5; 1,2 - 6; 1,3 - 7
  164. // 2,0 - 8; 2,1 - 9; 2,2 - 10; 2,3 - 11
  165. // 3,0 - 12; 3,1 - 13; 3,2 - 14; 3,3 - 15
  166. /////////////////////////////////////////////
  167. mp[ 0] = m1[0] * m2[0] + m1[1] * m2[4] + m1[2] * m2[ 8] + m1[3] * m2[12];
  168. mp[ 1] = m1[0] * m2[1] + m1[1] * m2[5] + m1[2] * m2[ 9] + m1[3] * m2[13];
  169. mp[ 2] = m1[0] * m2[2] + m1[1] * m2[6] + m1[2] * m2[10] + m1[3] * m2[14];
  170. mp[ 3] = m1[0] * m2[3] + m1[1] * m2[7] + m1[2] * m2[11] + m1[3] * m2[15];
  171. mp[ 4] = m1[4] * m2[0] + m1[5] * m2[4] + m1[6] * m2[ 8] + m1[7] * m2[12];
  172. mp[ 5] = m1[4] * m2[1] + m1[5] * m2[5] + m1[6] * m2[ 9] + m1[7] * m2[13];
  173. mp[ 6] = m1[4] * m2[2] + m1[5] * m2[6] + m1[6] * m2[10] + m1[7] * m2[14];
  174. mp[ 7] = m1[4] * m2[3] + m1[5] * m2[7] + m1[6] * m2[11] + m1[7] * m2[15];
  175. mp[ 8] = m1[8] * m2[0] + m1[9] * m2[4] + m1[10] * m2[ 8] + m1[11] * m2[12];
  176. mp[ 9] = m1[8] * m2[1] + m1[9] * m2[5] + m1[10] * m2[ 9] + m1[11] * m2[13];
  177. mp[10] = m1[8] * m2[2] + m1[9] * m2[6] + m1[10] * m2[10] + m1[11] * m2[14];
  178. mp[11] = m1[8] * m2[3] + m1[9] * m2[7] + m1[10] * m2[11] + m1[11] * m2[15];
  179. mp[12] = m1[12] * m2[0] + m1[13] * m2[4] + m1[14] * m2[ 8] + m1[15] * m2[12];
  180. mp[13] = m1[12] * m2[1] + m1[13] * m2[5] + m1[14] * m2[ 9] + m1[15] * m2[13];
  181. mp[14] = m1[12] * m2[2] + m1[13] * m2[6] + m1[14] * m2[10] + m1[15] * m2[14];
  182. mp[15] = m1[12] * m2[3] + m1[13] * m2[7] + m1[14] * m2[11] + m1[15] * m2[15];
  183. #endif
  184. }
  185. void mtkMatrixConvert3x3ToMtk(float *m3x3, matrix_t dest)
  186. {
  187. if (!m3x3)
  188. {
  189. mtkMatrixIdentity(dest);
  190. return;
  191. }
  192. dest[0] = m3x3[0]; dest[1] = m3x3[1]; dest[2 ] = m3x3[2];
  193. dest[4] = m3x3[3]; dest[5] = m3x3[4]; dest[6 ] = m3x3[5];
  194. dest[8] = m3x3[6]; dest[9] = m3x3[7]; dest[10] = m3x3[8];
  195. // yeah, wolf
  196. dest[11] = dest[12] = dest[13] = dest[14] = 0.0f;
  197. dest[15] = 1.0f;
  198. }
  199. void mtkMatrixCopy(matrix_t source, matrix_t dest)
  200. {
  201. #ifdef OBSOLETE
  202. int i,j;
  203. for(i = 0; i < 4; i++)
  204. {
  205. for(j = 0 ; j < 4; j++)
  206. {
  207. dest[i][j] = source[i][j];
  208. }
  209. }
  210. #else
  211. dest[ 0] = source[ 0];
  212. dest[ 1] = source[ 1];
  213. dest[ 2] = source[ 2];
  214. dest[ 3] = source[ 3];
  215. dest[ 4] = source[ 4];
  216. dest[ 5] = source[ 5];
  217. dest[ 6] = source[ 6];
  218. dest[ 7] = source[ 7];
  219. dest[ 8] = source[8];
  220. dest[ 9] = source[9];
  221. dest[10] = source[10];
  222. dest[11] = source[11];
  223. dest[12] = source[12];
  224. dest[13] = source[13];
  225. dest[14] = source[14];
  226. dest[15] = source[15];
  227. #endif
  228. }
  229. void mtkMatrixTransform(matrix_t t, vec3_t p)
  230. {
  231. vec_t m1[4];
  232. m1[0] = p[0];
  233. m1[1] = p[1];
  234. m1[2] = p[2];
  235. m1[3] = 1;
  236. #ifdef OBSOLETE
  237. p[0] = t[0][0]*m1[0] + t[1][0]*m1[1] + t[2][0]*m1[2] + t[3][0]*m1[3];
  238. p[1] = t[0][1]*m1[0] + t[1][1]*m1[1] + t[2][1]*m1[2] + t[3][1]*m1[3];
  239. p[2] = t[0][2]*m1[0] + t[1][2]*m1[1] + t[2][2]*m1[2] + t[3][2]*m1[3];
  240. #else
  241. p[0] = t[0] * m1[0] + t[4] * m1[1] + t[ 8] * m1[2] + t[12] * m1[3];
  242. p[1] = t[1] * m1[0] + t[5] * m1[1] + t[ 9] * m1[2] + t[13] * m1[3];
  243. p[2] = t[2] * m1[0] + t[6] * m1[1] + t[10] * m1[2] + t[14] * m1[3];
  244. #endif
  245. }
  246. void mtkMatrixIdentity(matrix_t matrix)
  247. {
  248. #ifdef OBSOLETE
  249. matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0; matrix[0][3] = 0;
  250. matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0; matrix[1][3] = 0;
  251. matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1; matrix[2][3] = 0;
  252. matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
  253. #else
  254. matrix[ 0] = 1; matrix[ 1] = 0; matrix[ 2] = 0; matrix[ 3] = 0;
  255. matrix[ 4] = 0; matrix[ 5] = 1; matrix[ 6] = 0; matrix[ 7] = 0;
  256. matrix[ 8] = 0; matrix[ 9] = 0; matrix[10] = 1; matrix[11] = 0;
  257. matrix[12] = 0; matrix[13] = 0; matrix[14] = 0; matrix[15] = 1;
  258. #endif
  259. }
  260. // FIXME: Might want to make scale matrix, etc consts
  261. void mtkMatrixScale(matrix_t matrix, vec_t sx, vec_t sy, vec_t sz)
  262. {
  263. matrix_t tmp, smatrix;
  264. #ifdef OBSOLETE
  265. smatrix[0][0] = sx;smatrix[0][1] = 0; smatrix[0][2] = 0; smatrix[0][3] = 0;
  266. smatrix[1][0] = 0; smatrix[1][1] = sy;smatrix[1][2] = 0; smatrix[1][3] = 0;
  267. smatrix[2][0] = 0; smatrix[2][1] = 0; smatrix[2][2] = sz;smatrix[2][3] = 0;
  268. smatrix[3][0] = 0; smatrix[3][1] = 0; smatrix[3][2] = 0; smatrix[3][3] = 1;
  269. #else
  270. smatrix[ 0] = sx;smatrix[ 1] = 0; smatrix[ 2] = 0; smatrix[ 3] = 0;
  271. smatrix[ 4] = 0; smatrix[ 5] = sy;smatrix[ 6] = 0; smatrix[ 7] = 0;
  272. smatrix[ 8] = 0; smatrix[ 9] = 0; smatrix[10] = sz;smatrix[11] = 0;
  273. smatrix[12] = 0; smatrix[13] = 0; smatrix[14] = 0; smatrix[15] = 1;
  274. #endif
  275. mtkMatrixMult(matrix, smatrix, tmp);
  276. mtkMatrixCopy(tmp, matrix);
  277. }
  278. void mtkMatrixRotate(matrix_t matrix, vec_t ax, vec_t ay, vec_t az)
  279. {
  280. matrix_t xmat, ymat, zmat, tmp, tmp2;
  281. #ifdef OBSOLETE
  282. xmat[0][0]=1; xmat[0][1]=0; xmat[0][2]=0; xmat[0][3]=0;
  283. xmat[1][0]=0; xmat[1][1]=cos(ax); xmat[1][2]=sin(ax); xmat[1][3]=0;
  284. xmat[2][0]=0; xmat[2][1]=-sin(ax); xmat[2][2]=cos(ax); xmat[2][3]=0;
  285. xmat[3][0]=0; xmat[3][1]=0; xmat[3][2]=0; xmat[3][3]=1;
  286. ymat[0][0]=cos(ay); ymat[0][1]=0; ymat[0][2]=-sin(ay); ymat[0][3]=0;
  287. ymat[1][0]=0; ymat[1][1]=1; ymat[1][2]=0; ymat[1][3]=0;
  288. ymat[2][0]=sin(ay); ymat[2][1]=0; ymat[2][2]=cos(ay); ymat[2][3]=0;
  289. ymat[3][0]=0; ymat[3][1]=0; ymat[3][2]=0; ymat[3][3]=1;
  290. zmat[0][0]=cos(az); zmat[0][1]=sin(az); zmat[0][2]=0; zmat[0][3]=0;
  291. zmat[1][0]=-sin(az); zmat[1][1]=cos(az); zmat[1][2]=0; zmat[1][3]=0;
  292. zmat[2][0]=0; zmat[2][1]=0; zmat[2][2]=1; zmat[2][3]=0;
  293. zmat[3][0]=0; zmat[3][1]=0; zmat[3][2]=0; zmat[3][3]=1;
  294. #else
  295. xmat[ 0]=1; xmat[ 1]=0; xmat[ 2]=0; xmat[ 3]=0;
  296. xmat[ 4]=0; xmat[ 5]=cos(ax); xmat[ 6]=sin(ax); xmat[ 7]=0;
  297. xmat[ 8]=0; xmat[ 9]=-sin(ax); xmat[10]=cos(ax); xmat[11]=0;
  298. xmat[12]=0; xmat[13]=0; xmat[14]=0; xmat[15]=1;
  299. ymat[ 0]=cos(ay); ymat[ 1]=0; ymat[ 2]=-sin(ay); ymat[ 3]=0;
  300. ymat[ 4]=0; ymat[ 5]=1; ymat[ 6]=0; ymat[ 7]=0;
  301. ymat[ 8]=sin(ay); ymat[ 9]=0; ymat[10]=cos(ay); ymat[11]=0;
  302. ymat[12]=0; ymat[13]=0; ymat[14]=0; ymat[15]=1;
  303. zmat[ 0]=cos(az); zmat[ 1]=sin(az); zmat[ 2]=0; zmat[ 3]=0;
  304. zmat[ 4]=-sin(az); zmat[ 5]=cos(az); zmat[ 6]=0; zmat[ 7]=0;
  305. zmat[ 8]=0; zmat[ 9]=0; zmat[10]=1; zmat[11]=0;
  306. zmat[12]=0; zmat[13]=0; zmat[14]=0; zmat[15]=1;
  307. #endif
  308. mtkMatrixMult(matrix, ymat, tmp);
  309. mtkMatrixMult(tmp, xmat, tmp2);
  310. mtkMatrixMult(tmp2, zmat, matrix);
  311. }
  312. void mtkMatrixTranslate(matrix_t matrix, vec_t tx, vec_t ty, vec_t tz)
  313. {
  314. matrix_t tmat, tmp;
  315. #ifdef OBSOLETE
  316. tmat[0][0]=1; tmat[0][1]=0; tmat[0][2]=0; tmat[0][3]=0;
  317. tmat[1][0]=0; tmat[1][1]=1; tmat[1][2]=0; tmat[1][3]=0;
  318. tmat[2][0]=0; tmat[2][1]=0; tmat[2][2]=1; tmat[2][3]=0;
  319. tmat[3][0]=tx; tmat[3][1]=ty; tmat[3][2]=tz; tmat[3][3]=1;
  320. #else
  321. tmat[ 0]=1; tmat[ 1]=0; tmat[ 2]=0; tmat[ 3]=0;
  322. tmat[ 4]=0; tmat[ 5]=1; tmat[ 6]=0; tmat[ 7]=0;
  323. tmat[ 8]=0; tmat[ 9]=0; tmat[10]=1; tmat[11]=0;
  324. tmat[12]=tx; tmat[13]=ty; tmat[14]=tz; tmat[15]=1;
  325. #endif
  326. mtkMatrixMult(matrix, tmat, tmp);
  327. mtkMatrixCopy(tmp, matrix);
  328. }
  329. ////////////////////////////////
  330. void mtkQuaternionCopy(quaternion_t source, quaternion_t dest)
  331. {
  332. dest.x = source.x;
  333. dest.y = source.y;
  334. dest.z = source.z;
  335. dest.w = source.w;
  336. }
  337. void mtkQuaternionSlerp(quaternion_t qI, quaternion_t qA, quaternion_t qB,
  338. float time)
  339. {
  340. /*******************************************************************
  341. * Spherical Linear Interpolation algorthim
  342. *-----------------------------------------------------------------
  343. *
  344. * Interpolate between A and B rotations ( Find qI )
  345. *
  346. * qI = (((qB . qA)^ -1)^ Time) qA
  347. *
  348. * http://www.magic-software.com/Documentation/quat.pdf
  349. *
  350. * Thanks to digiben for algorithms and basis of the notes in
  351. * this func
  352. *
  353. *******************************************************************/
  354. float result, scaleA, scaleB, theta, sinTheta;
  355. // Don't bother if it's the same rotation, it's the same as the result
  356. if (&qA == &qB ||
  357. qA.x == qB.x && qA.y == qB.y && qA.z == qB.z && qA.w == qB.w)
  358. {
  359. mtkQuaternionCopy(qA, qI);
  360. return;
  361. }
  362. // A . B
  363. result = (qA.x * qB.x) + (qA.y * qB.y) + (qA.z * qB.z) + (qA.w * qB.w);
  364. // If the dot product is less than 0, the angle is greater than 90 degrees
  365. if (result < 0.0f)
  366. {
  367. // Negate quaternion B and the result of the dot product
  368. qB.x = -qB.x;
  369. qB.y = -qB.y;
  370. qB.z = -qB.z;
  371. qB.w = -qB.w;
  372. result = -result;
  373. }
  374. // Set the first and second scale for the interpolation
  375. scaleA = 1 - time;
  376. scaleB = time;
  377. // Next, we want to actually calculate the spherical interpolation. Since this
  378. // calculation is quite computationally expensive, we want to only perform it
  379. // if the angle between the 2 quaternions is large enough to warrant it. If the
  380. // angle is fairly small, we can actually just do a simpler linear interpolation
  381. // of the 2 quaternions, and skip all the complex math. We create a "delta" value
  382. // of 0.1 to say that if the cosine of the angle (result of the dot product) between
  383. // the 2 quaternions is smaller than 0.1, then we do NOT want to perform the full on
  384. // interpolation using. This is because you won't really notice the difference.
  385. // Check if the angle between the 2 quaternions was big enough
  386. // to warrant such calculations
  387. if (1 - result > 0.1f)
  388. {
  389. // Get the angle between the 2 quaternions, and then
  390. // store the sin() of that angle
  391. theta = (float)acos(result);
  392. sinTheta = (float)sin(theta);
  393. // Calculate the scale for qA and qB, according to
  394. // the angle and it's sine value
  395. scaleA = (float)sin((1 - time) * theta) / sinTheta;
  396. scaleB = (float)sin((time * theta)) / sinTheta;
  397. }
  398. // Calculate the x, y, z and w values for the quaternion by using a special
  399. // form of linear interpolation for quaternions.
  400. qI.x = (scaleA * qA.x) + (scaleB * qB.x);
  401. qI.y = (scaleA * qA.y) + (scaleB * qB.y);
  402. qI.z = (scaleA * qA.z) + (scaleB * qB.z);
  403. qI.w = (scaleA * qA.w) + (scaleB * qB.w);
  404. }
  405. void mtkQuaternionFrom3x3Matrix(float *m3x3, quaternion_t q)
  406. {
  407. matrix_t matrix;
  408. mtkMatrixConvert3x3ToMtk(m3x3, matrix);
  409. mtkQuaternionFromMatrix(matrix, q);
  410. }
  411. void mtkQuaternionFromMatrix(matrix_t matrix, quaternion_t q)
  412. {
  413. float diagonal, scale;
  414. diagonal = matrix[0] + matrix[5] + matrix[10] + 1;
  415. scale = 0.0f;
  416. mtkQuaternionIdentity(q);
  417. // diagonal is greater than 'zero'
  418. if (diagonal > 0.00000001)
  419. {
  420. scale = float(sqrt(diagonal) * 2);
  421. q.x = (matrix[9] - matrix[6]) / scale;
  422. q.y = (matrix[2] - matrix[8]) / scale;
  423. q.z = (matrix[4] - matrix[1]) / scale;
  424. q.w = 0.25f * scale;
  425. }
  426. else
  427. {
  428. // If the first element of the diagonal is the greatest value
  429. if (matrix[0] > matrix[5] && matrix[0] > matrix[10])
  430. {
  431. // Find the scale according to the first element, and double it
  432. scale = (float)sqrt(1.0f + matrix[0] - matrix[5] - matrix[10]) * 2.0f;
  433. // Calculate the x, y, x and w of the quaternion
  434. q.x = 0.25f * scale;
  435. q.y = (matrix[4] + matrix[1]) / scale;
  436. q.z = (matrix[2] + matrix[8]) / scale;
  437. q.w = (matrix[9] - matrix[6]) / scale;
  438. }
  439. // Else if the second element of the diagonal is the greatest value
  440. else if (matrix[5] > matrix[10])
  441. {
  442. // Find the scale according to the second element, and double it
  443. scale = (float)sqrt(1.0f + matrix[5] - matrix[0] - matrix[10]) * 2.0f;
  444. // Calculate the x, y, x and w of the quaternion
  445. q.x = (matrix[4] + matrix[1]) / scale;
  446. q.y = 0.25f * scale;
  447. q.z = (matrix[9] + matrix[6]) / scale;
  448. q.w = (matrix[2] - matrix[8]) / scale;
  449. }
  450. // Else the third element of the diagonal is the greatest value
  451. else
  452. {
  453. // Find the scale according to the third element, and double it
  454. scale = (float)sqrt(1.0f + matrix[10] - matrix[0] - matrix[5]) * 2.0f;
  455. // Calculate the x, y, x and w of the quaternion
  456. q.x = (matrix[2] + matrix[8]) / scale;
  457. q.y = (matrix[9] + matrix[6]) / scale;
  458. q.z = 0.25f * scale;
  459. q.w = (matrix[4] - matrix[1]) / scale;
  460. }
  461. }
  462. }
  463. void mtkQuaternionToMatrix(quaternion_t q, matrix_t m)
  464. {
  465. #ifdef OBSOLETE
  466. float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
  467. x2 = q.x + q.x; y2 = q.y + q.y; z2 = q.z + q.z;
  468. xx = q.x * x2; xy = q.x * y2; xz = q.x * z2;
  469. yy = q.y * y2; yz = q.y * z2; zz = q.z * z2;
  470. wx = q.w * x2; wy = q.w * y2; wz = q.w * z2;
  471. m[ 0] = 1.0 - (yy + zz);
  472. m[ 1] = xy - wz;
  473. m[ 2] = xz + wy;
  474. m[ 3] = 0.0;
  475. m[ 4] = xy + wz;
  476. m[ 5] = 1.0 - (xx + zz);
  477. m[ 6] = yz - wx;
  478. m[ 7] = 0.0;
  479. m[ 8] = xz - wy;
  480. m[ 9] = yz + wx;
  481. m[10] = 1.0 - (xx + yy);
  482. m[11] = 0.0;
  483. m[12] = 0;
  484. m[13] = 0;
  485. m[14] = 0;
  486. m[15] = 1;
  487. #else
  488. m[ 0] = 1.0f - 2.0f * (q.y*q.y + q.z*q.z);
  489. m[ 1] = 2.0f * (q.x*q.y - q.w*q.z);
  490. m[ 2] = 2.0f * (q.x*q.z + q.w*q.y);
  491. m[ 3] = 0.0f;
  492. m[ 4] = 2.0f * (q.x*q.y + q.w*q.z);
  493. m[ 5] = 1.0f - 2.0f * (q.x*q.x + q.z*q.z);
  494. m[ 6] = 2.0f * (q.y*q.z - q.w*q.x);
  495. m[ 7] = 0.0f;
  496. m[ 8] = 2.0f * (q.x*q.z - q.w*q.y);
  497. m[ 9] = 2.0f * (q.y*q.z + q.w*q.x);
  498. m[10] = 1.0 - 2.0f * (q.x*q.x + q.y*q.y);
  499. m[11] = 0.0f;
  500. m[12] = 0.0f;
  501. m[13] = 0.0f;
  502. m[14] = 0.0f;
  503. m[15] = 1.0f;
  504. #endif
  505. }
  506. void mtkQuaternionIdentity(quaternion_t q)
  507. {
  508. q.w = 1.0;
  509. q.x = 0.0;
  510. q.y = 0.0;
  511. q.z = 0.0;
  512. }
  513. void mtkQuaternionSet(quaternion_t q, float angle, float x, float y, float z)
  514. {
  515. float temp, dist;
  516. // Normalize
  517. temp = x*x + y*y + z*z;
  518. dist = (float)(1.0 / sqrt(temp));
  519. x *= dist;
  520. y *= dist;
  521. z *= dist;
  522. q.x = x;
  523. q.y = y;
  524. q.z = z;
  525. q.w = (float)cos(angle / 2.0f);
  526. }
  527. void mtkQuaternionMult(quaternion_t a, quaternion_t b, quaternion_t result)
  528. {
  529. result.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
  530. result.y = a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z;
  531. result.z = a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x;
  532. result.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
  533. // Quaternion needs to be a unit quaternion
  534. mtkQuaternionNormalize(result);
  535. }
  536. void mtkQuaternionNormalize(quaternion_t q)
  537. {
  538. float dist, square;
  539. square = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
  540. if (square > 0.00000001)
  541. {
  542. dist = (float)(1.0 / sqrt(square));
  543. }
  544. else
  545. {
  546. dist = 1;
  547. }
  548. q.x *= dist;
  549. q.y *= dist;
  550. q.z *= dist;
  551. q.w *= dist;
  552. }