/src/game/quaternion.c

https://gitlab.com/kholdfuzion/goldeneye_src · C · 326 lines · 306 code · 20 blank · 0 comment · 20 complexity · 4c1dac2f8b63756c7f01fc1a49924e47 MD5 · raw file

  1. #include <ultra64.h>
  2. #include "quaternion.h"
  3. #include "math_asinfacosf.h"
  4. #define HALF2RAD(x) (x * (M_PI_F / 32768.0f))
  5. void quaternion_set_rotation_around_xyz(vec3u angles, quatf q)
  6. {
  7. f32 cos_x = cosf(HALF2RAD(angles[0]) * 0.5f);
  8. f32 sin_x = sinf(HALF2RAD(angles[0]) * 0.5f);
  9. f32 cos_y = cosf(HALF2RAD(angles[1]) * 0.5f);
  10. f32 sin_y = sinf(HALF2RAD(angles[1]) * 0.5f);
  11. f32 cos_z = cosf(HALF2RAD(angles[2]) * 0.5f);
  12. f32 sin_z = sinf(HALF2RAD(angles[2]) * 0.5f);
  13. f32 cos_x_cos_y = cos_x * cos_y;
  14. f32 cos_x_sin_y = cos_x * sin_y;
  15. f32 sin_x_cos_y = sin_x * cos_y;
  16. f32 sin_x_sin_y = sin_x * sin_y;
  17. q[0] = ((cos_x_cos_y * cos_z) + (sin_x_sin_y * sin_z));
  18. q[1] = ((sin_x_cos_y * cos_z) - (cos_x_sin_y * sin_z));
  19. q[2] = ((cos_x_sin_y * cos_z) + (sin_x_cos_y * sin_z));
  20. q[3] = ((cos_x_cos_y * sin_z) - (sin_x_sin_y * cos_z));
  21. }
  22. void quaternion_set_rotation_around_xyzf(vec3f angles, quatf q)
  23. {
  24. f32 cos_x = cosf(angles[0] * 0.5f);
  25. f32 sin_x = sinf(angles[0] * 0.5f);
  26. f32 cos_y = cosf(angles[1] * 0.5f);
  27. f32 sin_y = sinf(angles[1] * 0.5f);
  28. f32 cos_z = cosf(angles[2] * 0.5f);
  29. f32 sin_z = sinf(angles[2] * 0.5f);
  30. f32 cos_x_cos_y = cos_x * cos_y;
  31. f32 cos_x_sin_y = cos_x * sin_y;
  32. f32 sin_x_cos_y = sin_x * cos_y;
  33. f32 sin_x_sin_y = sin_x * sin_y;
  34. q[0] = (cos_x_cos_y * cos_z) + (sin_x_sin_y * sin_z);
  35. q[1] = (sin_x_cos_y * cos_z) - (cos_x_sin_y * sin_z);
  36. q[2] = (cos_x_sin_y * cos_z) + (sin_x_cos_y * sin_z);
  37. q[3] = (cos_x_cos_y * sin_z) - (sin_x_sin_y * cos_z);
  38. }
  39. void quaternion_set_rotation_around_x(f32 angle, quatf q)
  40. {
  41. q[0] = cosf(angle * 0.5f);
  42. q[1] = sinf(angle * 0.5f);
  43. q[2] = 0.0f;
  44. q[3] = 0.0f;
  45. }
  46. void quaternion_set_rotation_around_y(f32 angle, quatf q)
  47. {
  48. q[0] = cosf(angle * 0.5f);
  49. q[1] = 0.0f;
  50. q[2] = sinf(angle * 0.5f);
  51. q[3] = 0.0f;
  52. }
  53. void quaternion_set_rotation_around_z(f32 angle, quatf q)
  54. {
  55. q[0] = cosf(angle * 0.5f);
  56. q[1] = 0.0f;
  57. q[2] = 0.0f;
  58. q[3] = sinf(angle * 0.5f);
  59. }
  60. void quaternion_to_matrix(quatf q, mat44f matrix)
  61. {
  62. f32 temp_f6 = 2.0f / ((q[0] * q[0]) + (q[1] * q[1]) + (q[2] * q[2]) + (q[3] * q[3]));
  63. f32 temp_f18 = q[1] * temp_f6;
  64. f32 temp_f16 = q[2] * temp_f6;
  65. f32 temp_f14 = q[3] * temp_f6;
  66. f32 sp34 = q[0] * temp_f18;
  67. f32 sp30 = q[0] * temp_f16;
  68. f32 sp2C = q[0] * temp_f14;
  69. f32 sp28 = q[1] * temp_f18;
  70. f32 sp24 = q[1] * temp_f16;
  71. f32 sp20 = q[1] * temp_f14;
  72. f32 sp1C = q[2] * temp_f16;
  73. f32 sp18 = q[2] * temp_f14;
  74. f32 sp14 = q[3] * temp_f14;
  75. matrix[0][0] = (1.0f - (sp1C + sp14));
  76. matrix[0][1] = (sp24 + sp2C);
  77. matrix[0][2] = (sp20 - sp30);
  78. matrix[1][0] = (sp24 - sp2C);
  79. matrix[1][1] = (1.0f - (sp28 + sp14));
  80. matrix[1][2] = (sp18 + sp34);
  81. matrix[2][0] = (sp20 + sp30);
  82. matrix[2][1] = (sp18 - sp34);
  83. matrix[2][2] = (1.0f - (sp28 + sp1C));
  84. matrix[3][0] = 0.0f;
  85. matrix[3][1] = 0.0f;
  86. matrix[3][2] = 0.0f;
  87. matrix[0][3] = 0.0f;
  88. matrix[1][3] = 0.0f;
  89. matrix[2][3] = 0.0f;
  90. matrix[3][3] = 1.0f;
  91. }
  92. void quaternion_from_matrix(mat44f arg0, quatf arg1)
  93. {
  94. f32 var1;
  95. f32 var2;
  96. f32 trace = arg0[0][0] + arg0[1][1] + arg0[2][2] + 1.0f;
  97. if (0.0f < trace) {
  98. var1 = sqrtf(trace);
  99. var2 = 0.5f / var1;
  100. arg1[0] = var1 * 0.5f;
  101. arg1[1] = (arg0[1][2] - arg0[2][1]) * var2;
  102. arg1[2] = (arg0[2][0] - arg0[0][2]) * var2;
  103. arg1[3] = (arg0[0][1] - arg0[1][0]) * var2;
  104. } else {
  105. s32 i;
  106. s32 j;
  107. s32 indices[3] = {1,2,0};
  108. s32 k;
  109. i = 0;
  110. if (arg0[0][0] < arg0[1][1]) {
  111. i = 1;
  112. }
  113. if (arg0[i][i] < arg0[2][2]) {
  114. i = 2;
  115. }
  116. j = indices[i];
  117. k = indices[j];
  118. var1 = sqrtf(arg0[i][i] - arg0[j][j] - arg0[k][k] + 1.0f);
  119. var2 = 0.5f / var1;
  120. arg1[i + 1] = var1 * 0.5f;
  121. arg1[ 0] = (arg0[j][k] - arg0[k][j]) * var2;
  122. arg1[j + 1] = (arg0[i][j] + arg0[j][i]) * var2;
  123. arg1[k + 1] = (arg0[i][k] + arg0[k][i]) * var2;
  124. }
  125. }
  126. void quaternion_to_transform_matrix(vec3f position, quatf rotation, mat44f matrix)
  127. {
  128. quaternion_to_matrix(rotation, matrix);
  129. matrix[3][0] = position[0];
  130. matrix[3][1] = position[1];
  131. matrix[3][2] = position[2];
  132. }
  133. #define EPSILON 0.00001001f
  134. void quaternion_slerp(quatf q1, quatf q2, f32 t, quatf result)
  135. {
  136. f32 dot = (q1[0] * q2[0]) + (q1[1] * q2[1]) + (q1[2] * q2[2]) + (q1[3] * q2[3]);
  137. f32 theta;
  138. f32 theta_q1;
  139. f32 theta_q2;
  140. f32 sine;
  141. f32 coeff_q1;
  142. f32 coeff_q2;
  143. if (dot < (-1.0f + EPSILON)) {
  144. result[0] = ((1.0f - t) * q1[0]) - (q2[0] * t);
  145. result[1] = ((1.0f - t) * q1[1]) - (q2[1] * t);
  146. result[2] = ((1.0f - t) * q1[2]) - (q2[2] * t);
  147. result[3] = ((1.0f - t) * q1[3]) - (q2[3] * t);
  148. }
  149. else if (dot <= (1.0f - EPSILON)) {
  150. theta = acosf(dot);
  151. theta_q1 = (1.0f - t) * theta;
  152. theta_q2 = t * theta;
  153. sine = sinf(theta);
  154. coeff_q1 = sinf(theta_q1) / sine;
  155. coeff_q2 = sinf(theta_q2) / sine;
  156. result[0] = (coeff_q1 * q1[0]) + (q2[0] * coeff_q2);
  157. result[1] = (coeff_q1 * q1[1]) + (q2[1] * coeff_q2);
  158. result[2] = (coeff_q1 * q1[2]) + (q2[2] * coeff_q2);
  159. result[3] = (coeff_q1 * q1[3]) + (q2[3] * coeff_q2);
  160. } else {
  161. result[0] = ((1.0f - t) * q1[0]) + (q2[0] * t);
  162. result[1] = ((1.0f - t) * q1[1]) + (q2[1] * t);
  163. result[2] = ((1.0f - t) * q1[2]) + (q2[2] * t);
  164. result[3] = ((1.0f - t) * q1[3]) + (q2[3] * t);
  165. }
  166. }
  167. void quaternion_7F05BC68(quatf q, f32 t, quatf result)
  168. {
  169. f32 phi_f12 = q[0];
  170. f32 phi_f16 = 1.0f;
  171. f32 temp_f0_2;
  172. f32 test2;
  173. f32 temp_f4;
  174. f32 sp20;
  175. f32 temp_f2;
  176. f32 test;
  177. if (q[0] < 0.0f) {
  178. phi_f12 = -phi_f12;
  179. phi_f16 = -phi_f16;
  180. }
  181. if (phi_f12 < -0.99998999f) {
  182. result[0] = (q[0] * t) - ((1.0f - t) * phi_f16);
  183. result[1] = (q[1] * t);
  184. result[2] = (q[2] * t);
  185. result[3] = (q[3] * t);
  186. } else if (phi_f12 <= 0.99998999f) {
  187. temp_f0_2 = acosf(phi_f12);
  188. test2 = t * temp_f0_2;
  189. temp_f4 = (1.0f - t) * temp_f0_2;
  190. sp20 = sinf(temp_f0_2);
  191. temp_f2 = sinf(test2) / sp20;
  192. test = sinf(temp_f4) / sp20;
  193. result[0] = (q[0] * temp_f2) + (test * phi_f16);
  194. result[1] = (q[1] * temp_f2);
  195. result[2] = (q[2] * temp_f2);
  196. result[3] = (q[3] * temp_f2);
  197. } else {
  198. result[0] = (q[0] * t) + ((1.0f - t) * phi_f16);
  199. result[1] = (q[1] * t);
  200. result[2] = (q[2] * t);
  201. result[3] = (q[3] * t);
  202. }
  203. }
  204. void quaternion_ensure_shortest_path(quatf q1, quatf q2)
  205. {
  206. f32 dot = (q1[0] * q2[0]) + (q1[1] * q2[1]) + (q1[2] * q2[2]) + (q1[3] * q2[3]);
  207. if (dot < 0.0f) {
  208. q2[0] = -q2[0];
  209. q2[1] = -q2[1];
  210. q2[2] = -q2[2];
  211. q2[3] = -q2[3];
  212. }
  213. }
  214. void quaternion_multiply(quatf lhs, quatf rhs, quatf result)
  215. {
  216. result[0] = (lhs[0] * rhs[0]) - (lhs[1] * rhs[1]) - (lhs[2] * rhs[2]) - (lhs[3] * rhs[3]);
  217. result[1] = (lhs[0] * rhs[1]) + (rhs[0] * lhs[1]) + (lhs[2] * rhs[3]) - (lhs[3] * rhs[2]);
  218. result[2] = (lhs[0] * rhs[2]) + (rhs[0] * lhs[2]) + (lhs[3] * rhs[1]) - (lhs[1] * rhs[3]);
  219. result[3] = (lhs[0] * rhs[3]) + (rhs[0] * lhs[3]) + (lhs[1] * rhs[2]) - (lhs[2] * rhs[1]);
  220. }
  221. void quaternion_multiply_in_place(quatf lhs, quatf rhs)
  222. {
  223. quatf result;
  224. quaternion_multiply(lhs, rhs, result);
  225. rhs[0] = result[0];
  226. rhs[1] = result[1];
  227. rhs[2] = result[2];
  228. rhs[3] = result[3];
  229. }
  230. void quaternion_7F05BFD4(quatf q1, quatf q2)
  231. {
  232. f32 angle = acosf(q1[0]);
  233. f32 sine = sinf(angle);
  234. if (sine == 0.0f) {
  235. q2[0] = 0.0f;
  236. q2[1] = 0.0f;
  237. q2[2] = 0.0f;
  238. q2[3] = 0.0f;
  239. } else {
  240. q2[0] = 0.0f;
  241. q2[1] = (q1[1] * (angle / sine));
  242. q2[2] = (q1[2] * (angle / sine));
  243. q2[3] = (q1[3] * (angle / sine));
  244. }
  245. }
  246. void quaternion_7F05C068(quatf q1, quatf q2)
  247. {
  248. f32 sine;
  249. f32 angle = sqrtf((q1[1] * q1[1]) + (q1[2] * q1[2]) + (q1[3] * q1[3]));
  250. f32 unknown;
  251. if (angle == 0.0f) {
  252. q2[0] = 1.0f;
  253. q2[1] = 0.0f;
  254. q2[2] = 0.0f;
  255. q2[3] = 0.0f;
  256. } else {
  257. sine = sinf(angle);
  258. unknown = sine / angle;
  259. q2[0] = cosf(angle);
  260. q2[1] = (q1[1] * unknown);
  261. q2[2] = (q1[2] * unknown);
  262. q2[3] = (q1[3] * unknown);
  263. }
  264. }
  265. void quaternion_7F05C138(quatf arg0, quatf arg1, quatf arg2, quatf result)
  266. {
  267. quatf conjugate;
  268. quatf sp50;
  269. quatf sp40;
  270. quatf sp30;
  271. quatf sp20;
  272. conjugate[0] = arg1[0];
  273. conjugate[1] = -arg1[1];
  274. conjugate[2] = -arg1[2];
  275. conjugate[3] = -arg1[3];
  276. quaternion_multiply(conjugate, arg0, sp50);
  277. quaternion_multiply(conjugate, arg2, sp40);
  278. quaternion_7F05BFD4(sp50, sp30);
  279. quaternion_7F05BFD4(sp40, sp20);
  280. sp30[0] = -(sp30[0] + sp20[0]) * 0.25f;
  281. sp30[1] = -(sp30[1] + sp20[1]) * 0.25f;
  282. sp30[2] = -(sp30[2] + sp20[2]) * 0.25f;
  283. sp30[3] = -(sp30[3] + sp20[3]) * 0.25f;
  284. quaternion_7F05C068(sp30, sp50);
  285. quaternion_multiply(arg1, sp50, result);
  286. }
  287. void quaternion_7F05C250(quatf q1, quatf q2, quatf q3, quatf q4, f32 t, quatf result)
  288. {
  289. quatf q5;
  290. quatf q6;
  291. f32 t2 = (t + t) * (1.0f - t);
  292. quaternion_ensure_shortest_path(q1, q4);
  293. quaternion_slerp(q1, q4, t, q5);
  294. quaternion_ensure_shortest_path(q2, q3);
  295. quaternion_slerp(q2, q3, t, q6);
  296. quaternion_ensure_shortest_path(q5, q6);
  297. quaternion_slerp(q5, q6, t2, result);
  298. }
  299. void quaternion_7F05C2F0(quatf q1, quatf q2, quatf q3, quatf q4, f32 t, quatf result)
  300. {
  301. quatf q5;
  302. quatf q6;
  303. quaternion_7F05C138(q1, q2, q3, q5);
  304. quaternion_7F05C138(q2, q3, q4, q6);
  305. quaternion_7F05C250(q2, q5, q6, q3, t, result);
  306. }