linmath.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #ifndef LINMATH_H
  2. #define LINMATH_H
  3. #include <string.h>
  4. #include <math.h>
  5. #include <string.h>
  6. /* 2021-03-21 Camilla Löwy <[email protected]>
  7. * - Replaced double constants with float equivalents
  8. */
  9. #ifdef LINMATH_NO_INLINE
  10. #define LINMATH_H_FUNC static
  11. #else
  12. #define LINMATH_H_FUNC static inline
  13. #endif
  14. #define LINMATH_H_DEFINE_VEC(n) \
  15. typedef float vec##n[n]; \
  16. LINMATH_H_FUNC void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
  17. { \
  18. int i; \
  19. for(i=0; i<n; ++i) \
  20. r[i] = a[i] + b[i]; \
  21. } \
  22. LINMATH_H_FUNC void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
  23. { \
  24. int i; \
  25. for(i=0; i<n; ++i) \
  26. r[i] = a[i] - b[i]; \
  27. } \
  28. LINMATH_H_FUNC void vec##n##_scale(vec##n r, vec##n const v, float const s) \
  29. { \
  30. int i; \
  31. for(i=0; i<n; ++i) \
  32. r[i] = v[i] * s; \
  33. } \
  34. LINMATH_H_FUNC float vec##n##_mul_inner(vec##n const a, vec##n const b) \
  35. { \
  36. float p = 0.f; \
  37. int i; \
  38. for(i=0; i<n; ++i) \
  39. p += b[i]*a[i]; \
  40. return p; \
  41. } \
  42. LINMATH_H_FUNC float vec##n##_len(vec##n const v) \
  43. { \
  44. return sqrtf(vec##n##_mul_inner(v,v)); \
  45. } \
  46. LINMATH_H_FUNC void vec##n##_norm(vec##n r, vec##n const v) \
  47. { \
  48. float k = 1.f / vec##n##_len(v); \
  49. vec##n##_scale(r, v, k); \
  50. } \
  51. LINMATH_H_FUNC void vec##n##_min(vec##n r, vec##n const a, vec##n const b) \
  52. { \
  53. int i; \
  54. for(i=0; i<n; ++i) \
  55. r[i] = a[i]<b[i] ? a[i] : b[i]; \
  56. } \
  57. LINMATH_H_FUNC void vec##n##_max(vec##n r, vec##n const a, vec##n const b) \
  58. { \
  59. int i; \
  60. for(i=0; i<n; ++i) \
  61. r[i] = a[i]>b[i] ? a[i] : b[i]; \
  62. } \
  63. LINMATH_H_FUNC void vec##n##_dup(vec##n r, vec##n const src) \
  64. { \
  65. int i; \
  66. for(i=0; i<n; ++i) \
  67. r[i] = src[i]; \
  68. }
  69. LINMATH_H_DEFINE_VEC(2)
  70. LINMATH_H_DEFINE_VEC(3)
  71. LINMATH_H_DEFINE_VEC(4)
  72. LINMATH_H_FUNC void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
  73. {
  74. r[0] = a[1]*b[2] - a[2]*b[1];
  75. r[1] = a[2]*b[0] - a[0]*b[2];
  76. r[2] = a[0]*b[1] - a[1]*b[0];
  77. }
  78. LINMATH_H_FUNC void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
  79. {
  80. float p = 2.f * vec3_mul_inner(v, n);
  81. int i;
  82. for(i=0;i<3;++i)
  83. r[i] = v[i] - p*n[i];
  84. }
  85. LINMATH_H_FUNC void vec4_mul_cross(vec4 r, vec4 const a, vec4 const b)
  86. {
  87. r[0] = a[1]*b[2] - a[2]*b[1];
  88. r[1] = a[2]*b[0] - a[0]*b[2];
  89. r[2] = a[0]*b[1] - a[1]*b[0];
  90. r[3] = 1.f;
  91. }
  92. LINMATH_H_FUNC void vec4_reflect(vec4 r, vec4 const v, vec4 const n)
  93. {
  94. float p = 2.f*vec4_mul_inner(v, n);
  95. int i;
  96. for(i=0;i<4;++i)
  97. r[i] = v[i] - p*n[i];
  98. }
  99. typedef vec4 mat4x4[4];
  100. LINMATH_H_FUNC void mat4x4_identity(mat4x4 M)
  101. {
  102. int i, j;
  103. for(i=0; i<4; ++i)
  104. for(j=0; j<4; ++j)
  105. M[i][j] = i==j ? 1.f : 0.f;
  106. }
  107. LINMATH_H_FUNC void mat4x4_dup(mat4x4 M, mat4x4 const N)
  108. {
  109. int i;
  110. for(i=0; i<4; ++i)
  111. vec4_dup(M[i], N[i]);
  112. }
  113. LINMATH_H_FUNC void mat4x4_row(vec4 r, mat4x4 const M, int i)
  114. {
  115. int k;
  116. for(k=0; k<4; ++k)
  117. r[k] = M[k][i];
  118. }
  119. LINMATH_H_FUNC void mat4x4_col(vec4 r, mat4x4 const M, int i)
  120. {
  121. int k;
  122. for(k=0; k<4; ++k)
  123. r[k] = M[i][k];
  124. }
  125. LINMATH_H_FUNC void mat4x4_transpose(mat4x4 M, mat4x4 const N)
  126. {
  127. // Note: if M and N are the same, the user has to
  128. // explicitly make a copy of M and set it to N.
  129. int i, j;
  130. for(j=0; j<4; ++j)
  131. for(i=0; i<4; ++i)
  132. M[i][j] = N[j][i];
  133. }
  134. LINMATH_H_FUNC void mat4x4_add(mat4x4 M, mat4x4 const a, mat4x4 const b)
  135. {
  136. int i;
  137. for(i=0; i<4; ++i)
  138. vec4_add(M[i], a[i], b[i]);
  139. }
  140. LINMATH_H_FUNC void mat4x4_sub(mat4x4 M, mat4x4 const a, mat4x4 const b)
  141. {
  142. int i;
  143. for(i=0; i<4; ++i)
  144. vec4_sub(M[i], a[i], b[i]);
  145. }
  146. LINMATH_H_FUNC void mat4x4_scale(mat4x4 M, mat4x4 const a, float k)
  147. {
  148. int i;
  149. for(i=0; i<4; ++i)
  150. vec4_scale(M[i], a[i], k);
  151. }
  152. LINMATH_H_FUNC void mat4x4_scale_aniso(mat4x4 M, mat4x4 const a, float x, float y, float z)
  153. {
  154. vec4_scale(M[0], a[0], x);
  155. vec4_scale(M[1], a[1], y);
  156. vec4_scale(M[2], a[2], z);
  157. vec4_dup(M[3], a[3]);
  158. }
  159. LINMATH_H_FUNC void mat4x4_mul(mat4x4 M, mat4x4 const a, mat4x4 const b)
  160. {
  161. mat4x4 temp;
  162. int k, r, c;
  163. for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
  164. temp[c][r] = 0.f;
  165. for(k=0; k<4; ++k)
  166. temp[c][r] += a[k][r] * b[c][k];
  167. }
  168. mat4x4_dup(M, temp);
  169. }
  170. LINMATH_H_FUNC void mat4x4_mul_vec4(vec4 r, mat4x4 const M, vec4 const v)
  171. {
  172. int i, j;
  173. for(j=0; j<4; ++j) {
  174. r[j] = 0.f;
  175. for(i=0; i<4; ++i)
  176. r[j] += M[i][j] * v[i];
  177. }
  178. }
  179. LINMATH_H_FUNC void mat4x4_translate(mat4x4 T, float x, float y, float z)
  180. {
  181. mat4x4_identity(T);
  182. T[3][0] = x;
  183. T[3][1] = y;
  184. T[3][2] = z;
  185. }
  186. LINMATH_H_FUNC void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
  187. {
  188. vec4 t = {x, y, z, 0};
  189. vec4 r;
  190. int i;
  191. for (i = 0; i < 4; ++i) {
  192. mat4x4_row(r, M, i);
  193. M[3][i] += vec4_mul_inner(r, t);
  194. }
  195. }
  196. LINMATH_H_FUNC void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 const a, vec3 const b)
  197. {
  198. int i, j;
  199. for(i=0; i<4; ++i) for(j=0; j<4; ++j)
  200. M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
  201. }
  202. LINMATH_H_FUNC void mat4x4_rotate(mat4x4 R, mat4x4 const M, float x, float y, float z, float angle)
  203. {
  204. float s = sinf(angle);
  205. float c = cosf(angle);
  206. vec3 u = {x, y, z};
  207. if(vec3_len(u) > 1e-4) {
  208. vec3_norm(u, u);
  209. mat4x4 T;
  210. mat4x4_from_vec3_mul_outer(T, u, u);
  211. mat4x4 S = {
  212. { 0, u[2], -u[1], 0},
  213. {-u[2], 0, u[0], 0},
  214. { u[1], -u[0], 0, 0},
  215. { 0, 0, 0, 0}
  216. };
  217. mat4x4_scale(S, S, s);
  218. mat4x4 C;
  219. mat4x4_identity(C);
  220. mat4x4_sub(C, C, T);
  221. mat4x4_scale(C, C, c);
  222. mat4x4_add(T, T, C);
  223. mat4x4_add(T, T, S);
  224. T[3][3] = 1.f;
  225. mat4x4_mul(R, M, T);
  226. } else {
  227. mat4x4_dup(R, M);
  228. }
  229. }
  230. LINMATH_H_FUNC void mat4x4_rotate_X(mat4x4 Q, mat4x4 const M, float angle)
  231. {
  232. float s = sinf(angle);
  233. float c = cosf(angle);
  234. mat4x4 R = {
  235. {1.f, 0.f, 0.f, 0.f},
  236. {0.f, c, s, 0.f},
  237. {0.f, -s, c, 0.f},
  238. {0.f, 0.f, 0.f, 1.f}
  239. };
  240. mat4x4_mul(Q, M, R);
  241. }
  242. LINMATH_H_FUNC void mat4x4_rotate_Y(mat4x4 Q, mat4x4 const M, float angle)
  243. {
  244. float s = sinf(angle);
  245. float c = cosf(angle);
  246. mat4x4 R = {
  247. { c, 0.f, -s, 0.f},
  248. { 0.f, 1.f, 0.f, 0.f},
  249. { s, 0.f, c, 0.f},
  250. { 0.f, 0.f, 0.f, 1.f}
  251. };
  252. mat4x4_mul(Q, M, R);
  253. }
  254. LINMATH_H_FUNC void mat4x4_rotate_Z(mat4x4 Q, mat4x4 const M, float angle)
  255. {
  256. float s = sinf(angle);
  257. float c = cosf(angle);
  258. mat4x4 R = {
  259. { c, s, 0.f, 0.f},
  260. { -s, c, 0.f, 0.f},
  261. { 0.f, 0.f, 1.f, 0.f},
  262. { 0.f, 0.f, 0.f, 1.f}
  263. };
  264. mat4x4_mul(Q, M, R);
  265. }
  266. LINMATH_H_FUNC void mat4x4_invert(mat4x4 T, mat4x4 const M)
  267. {
  268. float s[6];
  269. float c[6];
  270. s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
  271. s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
  272. s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
  273. s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
  274. s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
  275. s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
  276. c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
  277. c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
  278. c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
  279. c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
  280. c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
  281. c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
  282. /* Assumes it is invertible */
  283. float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
  284. T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
  285. T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
  286. T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
  287. T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
  288. T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
  289. T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
  290. T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
  291. T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
  292. T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
  293. T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
  294. T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
  295. T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
  296. T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
  297. T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
  298. T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
  299. T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
  300. }
  301. LINMATH_H_FUNC void mat4x4_orthonormalize(mat4x4 R, mat4x4 const M)
  302. {
  303. mat4x4_dup(R, M);
  304. float s = 1.f;
  305. vec3 h;
  306. vec3_norm(R[2], R[2]);
  307. s = vec3_mul_inner(R[1], R[2]);
  308. vec3_scale(h, R[2], s);
  309. vec3_sub(R[1], R[1], h);
  310. vec3_norm(R[1], R[1]);
  311. s = vec3_mul_inner(R[0], R[2]);
  312. vec3_scale(h, R[2], s);
  313. vec3_sub(R[0], R[0], h);
  314. s = vec3_mul_inner(R[0], R[1]);
  315. vec3_scale(h, R[1], s);
  316. vec3_sub(R[0], R[0], h);
  317. vec3_norm(R[0], R[0]);
  318. }
  319. LINMATH_H_FUNC void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
  320. {
  321. M[0][0] = 2.f*n/(r-l);
  322. M[0][1] = M[0][2] = M[0][3] = 0.f;
  323. M[1][1] = 2.f*n/(t-b);
  324. M[1][0] = M[1][2] = M[1][3] = 0.f;
  325. M[2][0] = (r+l)/(r-l);
  326. M[2][1] = (t+b)/(t-b);
  327. M[2][2] = -(f+n)/(f-n);
  328. M[2][3] = -1.f;
  329. M[3][2] = -2.f*(f*n)/(f-n);
  330. M[3][0] = M[3][1] = M[3][3] = 0.f;
  331. }
  332. LINMATH_H_FUNC void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
  333. {
  334. M[0][0] = 2.f/(r-l);
  335. M[0][1] = M[0][2] = M[0][3] = 0.f;
  336. M[1][1] = 2.f/(t-b);
  337. M[1][0] = M[1][2] = M[1][3] = 0.f;
  338. M[2][2] = -2.f/(f-n);
  339. M[2][0] = M[2][1] = M[2][3] = 0.f;
  340. M[3][0] = -(r+l)/(r-l);
  341. M[3][1] = -(t+b)/(t-b);
  342. M[3][2] = -(f+n)/(f-n);
  343. M[3][3] = 1.f;
  344. }
  345. LINMATH_H_FUNC void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
  346. {
  347. /* NOTE: Degrees are an unhandy unit to work with.
  348. * linmath.h uses radians for everything! */
  349. float const a = 1.f / tanf(y_fov / 2.f);
  350. m[0][0] = a / aspect;
  351. m[0][1] = 0.f;
  352. m[0][2] = 0.f;
  353. m[0][3] = 0.f;
  354. m[1][0] = 0.f;
  355. m[1][1] = a;
  356. m[1][2] = 0.f;
  357. m[1][3] = 0.f;
  358. m[2][0] = 0.f;
  359. m[2][1] = 0.f;
  360. m[2][2] = -((f + n) / (f - n));
  361. m[2][3] = -1.f;
  362. m[3][0] = 0.f;
  363. m[3][1] = 0.f;
  364. m[3][2] = -((2.f * f * n) / (f - n));
  365. m[3][3] = 0.f;
  366. }
  367. LINMATH_H_FUNC void mat4x4_look_at(mat4x4 m, vec3 const eye, vec3 const center, vec3 const up)
  368. {
  369. /* Adapted from Android's OpenGL Matrix.java. */
  370. /* See the OpenGL GLUT documentation for gluLookAt for a description */
  371. /* of the algorithm. We implement it in a straightforward way: */
  372. /* TODO: The negation of of can be spared by swapping the order of
  373. * operands in the following cross products in the right way. */
  374. vec3 f;
  375. vec3_sub(f, center, eye);
  376. vec3_norm(f, f);
  377. vec3 s;
  378. vec3_mul_cross(s, f, up);
  379. vec3_norm(s, s);
  380. vec3 t;
  381. vec3_mul_cross(t, s, f);
  382. m[0][0] = s[0];
  383. m[0][1] = t[0];
  384. m[0][2] = -f[0];
  385. m[0][3] = 0.f;
  386. m[1][0] = s[1];
  387. m[1][1] = t[1];
  388. m[1][2] = -f[1];
  389. m[1][3] = 0.f;
  390. m[2][0] = s[2];
  391. m[2][1] = t[2];
  392. m[2][2] = -f[2];
  393. m[2][3] = 0.f;
  394. m[3][0] = 0.f;
  395. m[3][1] = 0.f;
  396. m[3][2] = 0.f;
  397. m[3][3] = 1.f;
  398. mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
  399. }
  400. typedef float quat[4];
  401. #define quat_add vec4_add
  402. #define quat_sub vec4_sub
  403. #define quat_norm vec4_norm
  404. #define quat_scale vec4_scale
  405. #define quat_mul_inner vec4_mul_inner
  406. LINMATH_H_FUNC void quat_identity(quat q)
  407. {
  408. q[0] = q[1] = q[2] = 0.f;
  409. q[3] = 1.f;
  410. }
  411. LINMATH_H_FUNC void quat_mul(quat r, quat const p, quat const q)
  412. {
  413. vec3 w;
  414. vec3_mul_cross(r, p, q);
  415. vec3_scale(w, p, q[3]);
  416. vec3_add(r, r, w);
  417. vec3_scale(w, q, p[3]);
  418. vec3_add(r, r, w);
  419. r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
  420. }
  421. LINMATH_H_FUNC void quat_conj(quat r, quat const q)
  422. {
  423. int i;
  424. for(i=0; i<3; ++i)
  425. r[i] = -q[i];
  426. r[3] = q[3];
  427. }
  428. LINMATH_H_FUNC void quat_rotate(quat r, float angle, vec3 const axis) {
  429. vec3 axis_norm;
  430. vec3_norm(axis_norm, axis);
  431. float s = sinf(angle / 2);
  432. float c = cosf(angle / 2);
  433. vec3_scale(r, axis_norm, s);
  434. r[3] = c;
  435. }
  436. LINMATH_H_FUNC void quat_mul_vec3(vec3 r, quat const q, vec3 const v)
  437. {
  438. /*
  439. * Method by Fabian 'ryg' Giessen (of Farbrausch)
  440. t = 2 * cross(q.xyz, v)
  441. v' = v + q.w * t + cross(q.xyz, t)
  442. */
  443. vec3 t;
  444. vec3 q_xyz = {q[0], q[1], q[2]};
  445. vec3 u = {q[0], q[1], q[2]};
  446. vec3_mul_cross(t, q_xyz, v);
  447. vec3_scale(t, t, 2);
  448. vec3_mul_cross(u, q_xyz, t);
  449. vec3_scale(t, t, q[3]);
  450. vec3_add(r, v, t);
  451. vec3_add(r, r, u);
  452. }
  453. LINMATH_H_FUNC void mat4x4_from_quat(mat4x4 M, quat const q)
  454. {
  455. float a = q[3];
  456. float b = q[0];
  457. float c = q[1];
  458. float d = q[2];
  459. float a2 = a*a;
  460. float b2 = b*b;
  461. float c2 = c*c;
  462. float d2 = d*d;
  463. M[0][0] = a2 + b2 - c2 - d2;
  464. M[0][1] = 2.f*(b*c + a*d);
  465. M[0][2] = 2.f*(b*d - a*c);
  466. M[0][3] = 0.f;
  467. M[1][0] = 2*(b*c - a*d);
  468. M[1][1] = a2 - b2 + c2 - d2;
  469. M[1][2] = 2.f*(c*d + a*b);
  470. M[1][3] = 0.f;
  471. M[2][0] = 2.f*(b*d + a*c);
  472. M[2][1] = 2.f*(c*d - a*b);
  473. M[2][2] = a2 - b2 - c2 + d2;
  474. M[2][3] = 0.f;
  475. M[3][0] = M[3][1] = M[3][2] = 0.f;
  476. M[3][3] = 1.f;
  477. }
  478. LINMATH_H_FUNC void mat4x4o_mul_quat(mat4x4 R, mat4x4 const M, quat const q)
  479. {
  480. /* XXX: The way this is written only works for orthogonal matrices. */
  481. /* TODO: Take care of non-orthogonal case. */
  482. quat_mul_vec3(R[0], q, M[0]);
  483. quat_mul_vec3(R[1], q, M[1]);
  484. quat_mul_vec3(R[2], q, M[2]);
  485. R[3][0] = R[3][1] = R[3][2] = 0.f;
  486. R[0][3] = M[0][3];
  487. R[1][3] = M[1][3];
  488. R[2][3] = M[2][3];
  489. R[3][3] = M[3][3]; // typically 1.0, but here we make it general
  490. }
  491. LINMATH_H_FUNC void quat_from_mat4x4(quat q, mat4x4 const M)
  492. {
  493. float r=0.f;
  494. int i;
  495. int perm[] = { 0, 1, 2, 0, 1 };
  496. int *p = perm;
  497. for(i = 0; i<3; i++) {
  498. float m = M[i][i];
  499. if( m < r )
  500. continue;
  501. m = r;
  502. p = &perm[i];
  503. }
  504. r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
  505. if(r < 1e-6) {
  506. q[0] = 1.f;
  507. q[1] = q[2] = q[3] = 0.f;
  508. return;
  509. }
  510. q[0] = r/2.f;
  511. q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
  512. q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
  513. q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
  514. }
  515. LINMATH_H_FUNC void mat4x4_arcball(mat4x4 R, mat4x4 const M, vec2 const _a, vec2 const _b, float s)
  516. {
  517. vec2 a; memcpy(a, _a, sizeof(a));
  518. vec2 b; memcpy(b, _b, sizeof(b));
  519. float z_a = 0.f;
  520. float z_b = 0.f;
  521. if(vec2_len(a) < 1.f) {
  522. z_a = sqrtf(1.f - vec2_mul_inner(a, a));
  523. } else {
  524. vec2_norm(a, a);
  525. }
  526. if(vec2_len(b) < 1.f) {
  527. z_b = sqrtf(1.f - vec2_mul_inner(b, b));
  528. } else {
  529. vec2_norm(b, b);
  530. }
  531. vec3 a_ = {a[0], a[1], z_a};
  532. vec3 b_ = {b[0], b[1], z_b};
  533. vec3 c_;
  534. vec3_mul_cross(c_, a_, b_);
  535. float const angle = acos(vec3_mul_inner(a_, b_)) * s;
  536. mat4x4_rotate(R, M, c_[0], c_[1], c_[2], angle);
  537. }
  538. #endif