Banjo API 0.0.1
Multi-purpose C99 API
Loading...
Searching...
No Matches
linmath.h
1
22#pragma once
23
24#include <banjo/math.h>
25
26#define bj_real_t float
27
28#ifndef BJ_COMPILER_DOXYGEN
29# define real_sqrt bj_sqrtf
30# define real_acos bj_acosf
31# define BJ_INLINE static inline
32#endif
33
43typedef bj_real_t bj_vec2[2];
44
54typedef bj_real_t bj_vec3[3];
55
65typedef bj_real_t bj_vec4[4];
66
76typedef bj_vec4 bj_mat4[4];
77
87typedef bj_real_t bj_quat[4];
88
97BJ_INLINE void bj_vec2_set(bj_vec2 res, bj_real_t a, bj_real_t b) {
98 res[0] = a; res[1] = b;
99}
100
109BJ_INLINE void bj_vec2_apply(bj_vec2 res, const bj_vec2 a, bj_real_t(*f)(bj_real_t)) {
110 res[0] = f(a[0]);
111 res[1] = f(a[1]);
112}
113
121BJ_INLINE void bj_vec2_add(bj_vec2 res, const bj_vec2 lhs, const bj_vec2 rhs) {
122 res[0] = lhs[0] + rhs[0];
123 res[1] = lhs[1] + rhs[1];
124}
125
133BJ_INLINE void bj_vec2_sub(bj_vec2 res, const bj_vec2 lhs, const bj_vec2 rhs) {
134 res[0] = lhs[0] - rhs[0];
135 res[1] = lhs[1] - rhs[1];
136}
137
145BJ_INLINE void bj_vec2_scale(bj_vec2 res, const bj_vec2 v, bj_real_t s) {
146 res[0] = v[0] * s;
147 res[1] = v[1] * s;
148}
149
157BJ_INLINE void bj_vec2_scale_each(bj_vec2 res, const bj_vec2 v, const bj_vec2 s) {
158 res[0] = v[0] * s[0];
159 res[1] = v[1] * s[1];
160}
161
169BJ_INLINE bj_real_t bj_vec2_dot(const bj_vec2 a, const bj_vec2 b) {
170 return a[0] * b[0] + a[1] * b[1];
171}
172
179BJ_INLINE bj_real_t bj_vec2_len(const bj_vec2 v) {
180 return real_sqrt(v[0] * v[0] + v[1] * v[1]);
181}
182
189BJ_INLINE void bj_vec2_normalize(bj_vec2 res, const bj_vec2 v) {
190 bj_real_t inv_len = 1.0f / real_sqrt(v[0] * v[0] + v[1] * v[1]);
191 res[0] = v[0] * inv_len;
192 res[1] = v[1] * inv_len;
193}
194
202BJ_INLINE void bj_vec2_min(bj_vec2 res, const bj_vec2 a, const bj_vec2 b) {
203 res[0] = a[0] < b[0] ? a[0] : b[0];
204 res[1] = a[1] < b[1] ? a[1] : b[1];
205}
206
214BJ_INLINE void bj_vec2_max(bj_vec2 res, const bj_vec2 a, const bj_vec2 b) {
215 res[0] = a[0] > b[0] ? a[0] : b[0];
216 res[1] = a[1] > b[1] ? a[1] : b[1];
217}
218
225BJ_INLINE void bj_vec2_copy(bj_vec2 res, const bj_vec2 src) {
226 res[0] = src[0];
227 res[1] = src[1];
228}
229
239BJ_INLINE void bj_vec3_set(bj_vec2 res, bj_real_t a, bj_real_t b, bj_real_t c) {
240 res[0] = a; res[1] = b; res[2] = c;
241}
242
251BJ_INLINE void bj_vec3_apply(bj_vec3 res, const bj_vec3 a, bj_real_t(*f)(bj_real_t)) {
252 res[0] = f(a[0]);
253 res[1] = f(a[1]);
254 res[2] = f(a[2]);
255}
256
257
265BJ_INLINE void bj_vec3_add(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs) {
266 res[0] = lhs[0] + rhs[0];
267 res[1] = lhs[1] + rhs[1];
268 res[2] = lhs[2] + rhs[2];
269}
270
278BJ_INLINE void bj_vec3_sub(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs) {
279 res[0] = lhs[0] - rhs[0];
280 res[1] = lhs[1] - rhs[1];
281 res[2] = lhs[2] - rhs[2];
282}
283
291BJ_INLINE void bj_vec3_scale(bj_vec3 res, const bj_vec3 v, bj_real_t s) {
292 res[0] = v[0] * s;
293 res[1] = v[1] * s;
294 res[2] = v[2] * s;
295}
296
304BJ_INLINE bj_real_t bj_vec3_dot(const bj_vec3 a, const bj_vec3 b) {
305 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
306}
307
314BJ_INLINE bj_real_t bj_vec3_len(const bj_vec3 v) {
315 return real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
316}
317
324BJ_INLINE void bj_vec3_normalize(bj_vec3 res, const bj_vec3 v) {
325 bj_real_t inv_len = 1.0f / real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
326 res[0] = v[0] * inv_len;
327 res[1] = v[1] * inv_len;
328 res[2] = v[2] * inv_len;
329}
330
338BJ_INLINE void bj_vec3_min(bj_vec3 res, const bj_vec3 a, const bj_vec3 b) {
339 res[0] = a[0] < b[0] ? a[0] : b[0];
340 res[1] = a[1] < b[1] ? a[1] : b[1];
341 res[2] = a[2] < b[2] ? a[2] : b[2];
342}
343
351BJ_INLINE void bj_vec3_max(bj_vec3 res, const bj_vec3 a, const bj_vec3 b) {
352 res[0] = a[0] > b[0] ? a[0] : b[0];
353 res[1] = a[1] > b[1] ? a[1] : b[1];
354 res[2] = a[2] > b[2] ? a[2] : b[2];
355}
356
363BJ_INLINE void bj_vec3_copy(bj_vec3 res, const bj_vec3 src) {
364 res[0] = src[0];
365 res[1] = src[1];
366 res[2] = src[2];
367}
368
376BJ_INLINE void bj_vec3_cross(bj_vec3 res, const bj_vec3 l, const bj_vec3 r)
377{
378 res[0] = l[1] * r[2] - l[2] * r[1];
379 res[1] = l[2] * r[0] - l[0] * r[2];
380 res[2] = l[0] * r[1] - l[1] * r[0];
381}
382
393BJ_INLINE void bj_vec3_reflect(bj_vec3 res, const bj_vec3 v, const bj_vec3 n)
394{
395 const bj_real_t p = 2.f * bj_vec3_dot(v, n);
396 for (int i = 0; i < 3; ++i) {
397 res[i] = v[i] - p * n[i];
398 }
399}
400
401
412BJ_INLINE void bj_vec4_set(bj_vec2 res, bj_real_t a, bj_real_t b, bj_real_t c, bj_real_t d) {
413 res[0] = a; res[1] = b; res[2] = c; res[3] = d;
414}
415
424BJ_INLINE void bj_vec4_apply(bj_vec4 res, const bj_vec4 a, bj_real_t(*f)(bj_real_t)) {
425 res[0] = f(a[0]);
426 res[1] = f(a[1]);
427 res[2] = f(a[2]);
428 res[3] = f(a[4]);
429}
430
438BJ_INLINE void bj_vec4_add(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs) {
439 res[0] = lhs[0] + rhs[0];
440 res[1] = lhs[1] + rhs[1];
441 res[2] = lhs[2] + rhs[2];
442 res[3] = lhs[3] + rhs[3];
443}
444
452BJ_INLINE void bj_vec4_sub(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs) {
453 res[0] = lhs[0] - rhs[0];
454 res[1] = lhs[1] - rhs[1];
455 res[2] = lhs[2] - rhs[2];
456 res[3] = lhs[3] - rhs[3];
457}
458
466BJ_INLINE void bj_vec4_scale(bj_vec4 res, const bj_vec4 v, bj_real_t s) {
467 res[0] = v[0] * s;
468 res[1] = v[1] * s;
469 res[2] = v[2] * s;
470 res[3] = v[3] * s;
471}
472
480BJ_INLINE bj_real_t bj_vec4_dot(const bj_vec4 a, const bj_vec4 b) {
481 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
482}
483
490BJ_INLINE bj_real_t bj_vec4_len(const bj_vec4 v) {
491 return real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
492}
493
500BJ_INLINE void bj_vec4_normalize(bj_vec4 res, const bj_vec4 v) {
501 bj_real_t inv_len = 1.0f / real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
502 res[0] = v[0] * inv_len;
503 res[1] = v[1] * inv_len;
504 res[2] = v[2] * inv_len;
505 res[3] = v[3] * inv_len;
506}
507
515BJ_INLINE void bj_vec4_min(bj_vec4 res, const bj_vec4 a, const bj_vec4 b) {
516 res[0] = a[0] < b[0] ? a[0] : b[0];
517 res[1] = a[1] < b[1] ? a[1] : b[1];
518 res[2] = a[2] < b[2] ? a[2] : b[2];
519 res[3] = a[3] < b[3] ? a[3] : b[3];
520}
521
529BJ_INLINE void bj_vec4_max(bj_vec4 res, const bj_vec4 a, const bj_vec4 b) {
530 res[0] = a[0] > b[0] ? a[0] : b[0];
531 res[1] = a[1] > b[1] ? a[1] : b[1];
532 res[2] = a[2] > b[2] ? a[2] : b[2];
533 res[3] = a[3] > b[3] ? a[3] : b[3];
534}
535
542BJ_INLINE void bj_vec4_copy(bj_vec4 res, const bj_vec4 src) {
543 res[0] = src[0];
544 res[1] = src[1];
545 res[2] = src[2];
546 res[3] = src[3];
547}
548
559BJ_INLINE void bj_vec4_cross(bj_vec4 res, const bj_vec4 l, const bj_vec4 r)
560{
561 res[0] = l[1] * r[2] - l[2] * r[1];
562 res[1] = l[2] * r[0] - l[0] * r[2];
563 res[2] = l[0] * r[1] - l[1] * r[0];
564 res[3] = 1.f;
565}
566
577BJ_INLINE void bj_vec4_reflect(bj_vec4 res, const bj_vec4 v, const bj_vec4 n)
578{
579 bj_real_t p = 2.f * bj_vec4_dot(v, n);
580 for (int i = 0; i < 4; ++i) {
581 res[i] = v[i] - p * n[i];
582 }
583}
584
592BJ_INLINE void bj_mat4_identity(bj_mat4 mat)
593{
594 for (int i = 0; i < 4; ++i) {
595 for (int j = 0; j < 4; ++j) {
596 mat[i][j] = i == j ? 1.f : 0.f;
597 }
598 }
599}
600
609BJ_INLINE void bj_mat4_copy(bj_mat4 to, const bj_mat4 from)
610{
611 for (int i = 0; i < 4; ++i) {
612 bj_vec4_copy(to[i], from[i]);
613 }
614}
615
625BJ_INLINE void bj_mat4_row(bj_vec4 res, const bj_mat4 mat, int r)
626{
627 for (int k = 0; k < 4; ++k) {
628 res[k] = mat[k][r];
629 }
630}
631
641BJ_INLINE void bj_mat4_col(bj_vec4 res, const bj_mat4 mat, int c)
642{
643 for (int k = 0; k < 4; ++k) {
644 res[k] = mat[c][k];
645 }
646}
647
657BJ_INLINE void bj_mat4_transpose(bj_mat4 res, const bj_mat4 mat)
658{
659 for (int j = 0; j < 4; ++j) {
660 for (int i = 0; i < 4; ++i) {
661 res[i][j] = mat[j][i];
662 }
663 }
664}
665
675BJ_INLINE void bj_mat4_add(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
676{
677 for (int i = 0; i < 4; ++i) {
678 bj_vec4_add(res[i], lhs[i], rhs[i]);
679 }
680}
681
691BJ_INLINE void bj_mat4_sub(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
692{
693 for (int i = 0; i < 4; ++i) {
694 bj_vec4_sub(res[i], lhs[i], rhs[i]);
695 }
696}
697
707BJ_INLINE void bj_mat4_scale(bj_mat4 res, const bj_mat4 lhs, bj_real_t k)
708{
709 for (int i = 0; i < 4; ++i) {
710 bj_vec4_scale(res[i], lhs[i], k);
711 }
712}
713
726BJ_INLINE void bj_mat4_scale_xyz(bj_mat4 res, const bj_mat4 mat, bj_real_t x, bj_real_t y, bj_real_t z)
727{
728 bj_vec4_scale(res[0], mat[0], x);
729 bj_vec4_scale(res[1], mat[1], y);
730 bj_vec4_scale(res[2], mat[2], z);
731 bj_vec4_copy(res[3], mat[3]);
732}
733
743BJ_INLINE void bj_mat4_mul(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
744{
745 bj_mat4 temp;
746 for (int c = 0; c < 4; ++c) {
747 for (int r = 0; r < 4; ++r) {
748 temp[c][r] = 0.f;
749 for (int k = 0; k < 4; ++k)
750 temp[c][r] += lhs[k][r] * rhs[c][k];
751 }
752 }
753 bj_mat4_copy(res, temp);
754}
755
765BJ_INLINE void bj_mat4_mul_vec4(bj_vec4 res, const bj_mat4 mat, const bj_vec4 v)
766{
767 for (int j = 0; j < 4; ++j) {
768 res[j] = 0.f;
769 for (int i = 0; i < 4; ++i) {
770 res[j] += mat[i][j] * v[i];
771 }
772 }
773}
774
786{
787 bj_mat4_identity(res);
788 res[3][0] = x;
789 res[3][1] = y;
790 res[3][2] = z;
791}
792
805{
806 bj_vec4 t = { x, y, z, 0 };
807 bj_vec4 r;
808 for (int i = 0; i < 4; ++i) {
809 bj_mat4_row(r, M, i);
810 M[3][i] += bj_vec4_dot(r, t);
811 }
812}
813
824BJ_INLINE void bj_mat4_mul_outer(bj_mat4 res, const bj_vec3 a, const bj_vec3 b)
825{
826 for (int i = 0; i < 4; ++i) {
827 for (int j = 0; j < 4; ++j) {
828 res[i][j] = i < 3 && j < 3 ? a[i] * b[j] : 0.f;
829 }
830 }
831}
832
846BJ_INLINE void bj_mat4_rotate(bj_mat4 res, const bj_mat4 mat, bj_real_t x, bj_real_t y, bj_real_t z, bj_real_t angle)
847{
848 bj_real_t s = bj_sinf(angle);
849 bj_real_t c = bj_cosf(angle);
850 bj_vec3 u = { x, y, z };
851
852 if (bj_vec3_len(u) > 1e-4) {
853 bj_vec3_normalize(u, u);
854 bj_mat4 T;
855 bj_mat4_mul_outer(T, u, u);
856
857 bj_mat4 S = {
858 { 0, u[2], -u[1], 0},
859 {-u[2], 0, u[0], 0},
860 { u[1], -u[0], 0, 0},
861 { 0, 0, 0, 0}
862 };
863 bj_mat4_scale(S, S, s);
864
865 bj_mat4 C;
867 bj_mat4_sub(C, C, T);
868
869 bj_mat4_scale(C, C, c);
870
871 bj_mat4_add(T, T, C);
872 bj_mat4_add(T, T, S);
873
874 T[3][3] = 1.f;
875 bj_mat4_mul(res, mat, T);
876 } else {
877 bj_mat4_copy(res, mat);
878 }
879}
880
891BJ_INLINE void bj_ma4_rotate_x(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
892{
893 bj_real_t s = bj_sinf(angle);
894 bj_real_t c = bj_cosf(angle);
895 bj_mat4 R = {
896 {1.f, 0.f, 0.f, 0.f},
897 {0.f, c, s, 0.f},
898 {0.f, -s, c, 0.f},
899 {0.f, 0.f, 0.f, 1.f}
900 };
901 bj_mat4_mul(res, mat, R);
902}
903
914BJ_INLINE void bj_ma4_rotate_y(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
915{
916 bj_real_t s = bj_sinf(angle);
917 bj_real_t c = bj_cosf(angle);
918 bj_mat4 R = {
919 { c, 0.f, -s, 0.f},
920 { 0.f, 1.f, 0.f, 0.f},
921 { s, 0.f, c, 0.f},
922 { 0.f, 0.f, 0.f, 1.f}
923 };
924 bj_mat4_mul(res, mat, R);
925}
926
937BJ_INLINE void bj_ma4_rotate_z(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
938{
939 bj_real_t s = bj_sinf(angle);
940 bj_real_t c = bj_cosf(angle);
941 bj_mat4 R = {
942 { c, s, 0.f, 0.f},
943 { -s, c, 0.f, 0.f},
944 { 0.f, 0.f, 1.f, 0.f},
945 { 0.f, 0.f, 0.f, 1.f}
946 };
947 bj_mat4_mul(res, mat, R);
948}
949
950
965BJ_INLINE void bj_mat4_rotate_arcball(bj_mat4 R, const bj_mat4 M, bj_vec2 const _a, bj_vec2 const _b, bj_real_t s)
966{
967 bj_vec2 a = { _a[0], _a[1] };
968 bj_vec2 b = { _b[0], _b[1] };;
969
970 bj_real_t z_a = 0.;
971 bj_real_t z_b = 0.;
972
973 if (bj_vec2_len(a) < 1.) {
974 z_a = real_sqrt(1.f - bj_vec2_dot(a, a));
975 }
976 else {
977 bj_vec2_normalize(a, a);
978 }
979
980 if (bj_vec2_len(b) < 1.) {
981 z_b = real_sqrt(1.f - bj_vec2_dot(b, b));
982 }
983 else {
984 bj_vec2_normalize(b, b);
985 }
986
987 bj_vec3 a_ = { a[0], a[1], z_a };
988 bj_vec3 b_ = { b[0], b[1], z_b };
989
990 bj_vec3 c_;
991 bj_vec3_cross(c_, a_, b_);
992
993 bj_real_t const angle = real_acos(bj_vec3_dot(a_, b_)) * s;
994 bj_mat4_rotate(R, M, c_[0], c_[1], c_[2], angle);
995}
996
1006BJ_INLINE void bj_mat4_inverse(bj_mat4 res, const bj_mat4 mat) {
1007 bj_real_t s[6];
1008 bj_real_t c[6];
1009 s[0] = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
1010 s[1] = mat[0][0] * mat[1][2] - mat[1][0] * mat[0][2];
1011 s[2] = mat[0][0] * mat[1][3] - mat[1][0] * mat[0][3];
1012 s[3] = mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2];
1013 s[4] = mat[0][1] * mat[1][3] - mat[1][1] * mat[0][3];
1014 s[5] = mat[0][2] * mat[1][3] - mat[1][2] * mat[0][3];
1015
1016 c[0] = mat[2][0] * mat[3][1] - mat[3][0] * mat[2][1];
1017 c[1] = mat[2][0] * mat[3][2] - mat[3][0] * mat[2][2];
1018 c[2] = mat[2][0] * mat[3][3] - mat[3][0] * mat[2][3];
1019 c[3] = mat[2][1] * mat[3][2] - mat[3][1] * mat[2][2];
1020 c[4] = mat[2][1] * mat[3][3] - mat[3][1] * mat[2][3];
1021 c[5] = mat[2][2] * mat[3][3] - mat[3][2] * mat[2][3];
1022
1023 bj_real_t 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]);
1024
1025 res[0][0] = (mat[1][1] * c[5] - mat[1][2] * c[4] + mat[1][3] * c[3]) * idet;
1026 res[0][1] = (-mat[0][1] * c[5] + mat[0][2] * c[4] - mat[0][3] * c[3]) * idet;
1027 res[0][2] = (mat[3][1] * s[5] - mat[3][2] * s[4] + mat[3][3] * s[3]) * idet;
1028 res[0][3] = (-mat[2][1] * s[5] + mat[2][2] * s[4] - mat[2][3] * s[3]) * idet;
1029
1030 res[1][0] = (-mat[1][0] * c[5] + mat[1][2] * c[2] - mat[1][3] * c[1]) * idet;
1031 res[1][1] = (mat[0][0] * c[5] - mat[0][2] * c[2] + mat[0][3] * c[1]) * idet;
1032 res[1][2] = (-mat[3][0] * s[5] + mat[3][2] * s[2] - mat[3][3] * s[1]) * idet;
1033 res[1][3] = (mat[2][0] * s[5] - mat[2][2] * s[2] + mat[2][3] * s[1]) * idet;
1034
1035 res[2][0] = (mat[1][0] * c[4] - mat[1][1] * c[2] + mat[1][3] * c[0]) * idet;
1036 res[2][1] = (-mat[0][0] * c[4] + mat[0][1] * c[2] - mat[0][3] * c[0]) * idet;
1037 res[2][2] = (mat[3][0] * s[4] - mat[3][1] * s[2] + mat[3][3] * s[0]) * idet;
1038 res[2][3] = (-mat[2][0] * s[4] + mat[2][1] * s[2] - mat[2][3] * s[0]) * idet;
1039
1040 res[3][0] = (-mat[1][0] * c[3] + mat[1][1] * c[1] - mat[1][2] * c[0]) * idet;
1041 res[3][1] = (mat[0][0] * c[3] - mat[0][1] * c[1] + mat[0][2] * c[0]) * idet;
1042 res[3][2] = (-mat[3][0] * s[3] + mat[3][1] * s[1] - mat[3][2] * s[0]) * idet;
1043 res[3][3] = (mat[2][0] * s[3] - mat[2][1] * s[1] + mat[2][2] * s[0]) * idet;
1044}
1045
1055BJ_INLINE void bj_mat4_orthonormalize(bj_mat4 res, const bj_mat4 mat) {
1056 bj_mat4_copy(res, mat);
1057 bj_real_t s = 1.f;
1058 bj_vec3 h;
1059
1060 bj_vec3_normalize(res[2], res[2]);
1061
1062 s = bj_vec3_dot(res[1], res[2]);
1063 bj_vec3_scale(h, res[2], s);
1064 bj_vec3_sub(res[1], res[1], h);
1065 bj_vec3_normalize(res[1], res[1]);
1066
1067 s = bj_vec3_dot(res[0], res[2]);
1068 bj_vec3_scale(h, res[2], s);
1069 bj_vec3_sub(res[0], res[0], h);
1070
1071 s = bj_vec3_dot(res[0], res[1]);
1072 bj_vec3_scale(h, res[1], s);
1073 bj_vec3_sub(res[0], res[0], h);
1074 bj_vec3_normalize(res[0], res[0]);
1075}
1076
1092 fmat[0][0] = 2.f * n / (r - l);
1093 fmat[0][1] = fmat[0][2] = fmat[0][3] = 0.f;
1094 fmat[1][1] = 2.f * n / (t - b);
1095 fmat[1][0] = fmat[1][2] = fmat[1][3] = 0.f;
1096 fmat[2][0] = (r + l) / (r - l);
1097 fmat[2][1] = (t + b) / (t - b);
1098 fmat[2][2] = -(f + n) / (f - n);
1099 fmat[2][3] = -1.f;
1100 fmat[3][2] = -2.f * (f * n) / (f - n);
1101 fmat[3][0] = fmat[3][1] = fmat[3][3] = 0.f;
1102}
1103
1119 omat[0][0] = 2.f / (r - l);
1120 omat[0][1] = omat[0][2] = omat[0][3] = 0.f;
1121 omat[1][1] = 2.f / (t - b);
1122 omat[1][0] = omat[1][2] = omat[1][3] = 0.f;
1123 omat[2][2] = -2.f / (f - n);
1124 omat[2][0] = omat[2][1] = omat[2][3] = 0.f;
1125 omat[3][0] = -(r + l) / (r - l);
1126 omat[3][1] = -(t + b) / (t - b);
1127 omat[3][2] = -(f + n) / (f - n);
1128 omat[3][3] = 1.f;
1129}
1130
1143BJ_INLINE void bj_mat4_perspective(bj_mat4 pmat, bj_real_t y_fov, bj_real_t aspect, bj_real_t n, bj_real_t f) {
1144 const bj_real_t a = 1.f / bj_tanf(y_fov / 2.f);
1145 pmat[0][0] = a / aspect;
1146 pmat[0][1] = 0.f;
1147 pmat[0][2] = 0.f;
1148 pmat[0][3] = 0.f;
1149 pmat[1][0] = 0.f;
1150 pmat[1][1] = a;
1151 pmat[1][2] = 0.f;
1152 pmat[1][3] = 0.f;
1153 pmat[2][0] = 0.f;
1154 pmat[2][1] = 0.f;
1155 pmat[2][2] = -((f + n) / (f - n));
1156 pmat[2][3] = -1.f;
1157 pmat[3][0] = 0.f;
1158 pmat[3][1] = 0.f;
1159 pmat[3][2] = -((2.f * f * n) / (f - n));
1160 pmat[3][3] = 0.f;
1161}
1162
1175BJ_INLINE void bj_mat4_lookat(bj_mat4 m, const bj_vec3 eye, const bj_vec3 center, const bj_vec3 up) {
1176 bj_vec3 f;
1177 bj_vec3_sub(f, center, eye);
1178 bj_vec3_normalize(f, f);
1179
1180 bj_vec3 s;
1181 bj_vec3_cross(s, f, up);
1182 bj_vec3_normalize(s, s);
1183
1184 bj_vec3 t;
1185 bj_vec3_cross(t, s, f);
1186
1187 m[0][0] = s[0];
1188 m[0][1] = t[0];
1189 m[0][2] = -f[0];
1190 m[0][3] = 0.f;
1191
1192 m[1][0] = s[1];
1193 m[1][1] = t[1];
1194 m[1][2] = -f[1];
1195 m[1][3] = 0.f;
1196
1197 m[2][0] = s[2];
1198 m[2][1] = t[2];
1199 m[2][2] = -f[2];
1200 m[2][3] = 0.f;
1201
1202 m[3][0] = 0.f;
1203 m[3][1] = 0.f;
1204 m[3][2] = 0.f;
1205 m[3][3] = 1.f;
1206
1207 bj_mat4_translation_inplace(m, -eye[0], -eye[1], -eye[2]);
1208}
1209
1212#define bj_quat_add bj_vec4_add
1213
1216#define bj_quat_sub bj_vec4_sub
1217
1220#define bj_quat_norm bj_vec4_normalize
1221
1224#define bj_quat_scale bj_vec4_scale
1225
1228#define bj_quat_dot bj_vec4_dot
1229
1237BJ_INLINE void bj_quat_identity(bj_quat q)
1238{
1239 q[0] = q[1] = q[2] = 0.f;
1240 q[3] = 1.f;
1241}
1242
1253BJ_INLINE void bj_quat_mul(bj_quat res, const bj_quat p, const bj_quat q)
1254{
1255 bj_vec3 w, tmp;
1256
1257 bj_vec3_cross(tmp, p, q);
1258 bj_vec3_scale(w, p, q[3]);
1259 bj_vec3_add(tmp, tmp, w);
1260 bj_vec3_scale(w, q, p[3]);
1261 bj_vec3_add(tmp, tmp, w);
1262
1263 bj_vec3_copy(res, tmp);
1264 res[3] = p[3] * q[3] - bj_vec3_dot(p, q);
1265}
1266
1277BJ_INLINE void bj_quat_conjugate(bj_quat res, const bj_quat q)
1278{
1279 for (int i = 0; i < 3; ++i) {
1280 res[i] = -q[i];
1281 }
1282 res[3] = q[3];
1283}
1284
1295BJ_INLINE void bj_quat_rotation(bj_quat res, bj_real_t angle, const bj_vec3 axis) {
1296 bj_vec3 axis_norm;
1297 bj_vec3_normalize(axis_norm, axis);
1298 const bj_real_t s = bj_sinf(angle / 2);
1299 const bj_real_t c = bj_cosf(angle / 2);
1300 bj_vec3_scale(res, axis_norm, s);
1301 res[3] = c;
1302}
1303
1314BJ_INLINE void bj_quat_mul_vec3(bj_vec3 res, const bj_quat q, const bj_vec3 v) {
1315 bj_vec3 t;
1316 bj_vec3 q_xyz = { q[0], q[1], q[2] };
1317 bj_vec3 u = { q[0], q[1], q[2] };
1318
1319 bj_vec3_cross(t, q_xyz, v);
1320 bj_vec3_scale(t, t, 2);
1321
1322 bj_vec3_cross(u, q_xyz, t);
1323 bj_vec3_scale(t, t, q[3]);
1324
1325 bj_vec3_add(res, v, t);
1326 bj_vec3_add(res, res, u);
1327}
1328
1337BJ_INLINE void bj_mat4_from_quat(bj_mat4 res, const bj_quat q) {
1338 bj_real_t a = q[3];
1339 bj_real_t b = q[0];
1340 bj_real_t c = q[1];
1341 bj_real_t d = q[2];
1342 bj_real_t a2 = a * a;
1343 bj_real_t b2 = b * b;
1344 bj_real_t c2 = c * c;
1345 bj_real_t d2 = d * d;
1346
1347 res[0][0] = a2 + b2 - c2 - d2;
1348 res[0][1] = 2.f * (b * c + a * d);
1349 res[0][2] = 2.f * (b * d - a * c);
1350 res[0][3] = 0.f;
1351
1352 res[1][0] = 2 * (b * c - a * d);
1353 res[1][1] = a2 - b2 + c2 - d2;
1354 res[1][2] = 2.f * (c * d + a * b);
1355 res[1][3] = 0.f;
1356
1357 res[2][0] = 2.f * (b * d + a * c);
1358 res[2][1] = 2.f * (c * d - a * b);
1359 res[2][2] = a2 - b2 - c2 + d2;
1360 res[2][3] = 0.f;
1361
1362 res[3][0] = res[3][1] = res[3][2] = 0.f;
1363 res[3][3] = 1.f;
1364}
1365
1376BJ_INLINE void bj_mat4_rotate_from_quat(bj_mat4 R, const bj_mat4 M, const bj_quat q) {
1377 bj_quat_mul_vec3(R[0], q, M[0]);
1378 bj_quat_mul_vec3(R[1], q, M[1]);
1379 bj_quat_mul_vec3(R[2], q, M[2]);
1380
1381 R[3][0] = R[3][1] = R[3][2] = 0.f;
1382 R[0][3] = M[0][3];
1383 R[1][3] = M[1][3];
1384 R[2][3] = M[2][3];
1385 R[3][3] = M[3][3];
1386}
1387
1396BJ_INLINE void bj_quat_from_mat4(bj_quat q, const bj_mat4 M) {
1397 bj_real_t r = 0.f;
1398 int i, j, k;
1399
1400 int perm[] = { 0, 1, 2, 0, 1 };
1401 int* p = perm;
1402
1403 for (i = 0; i < 3; i++) {
1404 bj_real_t m = M[i][i];
1405 if (m > r) {
1406 r = m;
1407 p = &perm[i];
1408 }
1409 }
1410
1411 i = p[0];
1412 j = p[1];
1413 k = p[2];
1414
1415 r = real_sqrt(1.f + M[i][i] - M[j][j] - M[k][k]);
1416
1417 if (r < 1e-6f) {
1418 q[0] = 0.f;
1419 q[1] = 0.f;
1420 q[2] = 0.f;
1421 q[3] = 1.f;
1422 return;
1423 }
1424
1425 bj_real_t inv = 0.5f / r;
1426
1427 q[i] = 0.5f * r;
1428 q[j] = (M[i][j] + M[j][i]) * inv;
1429 q[k] = (M[k][i] + M[i][k]) * inv;
1430 q[3] = (M[k][j] - M[j][k]) * inv;
1431}
1432
BJ_INLINE void bj_mat4_lookat(bj_mat4 m, const bj_vec3 eye, const bj_vec3 center, const bj_vec3 up)
Generates a look-at matrix.
Definition linmath.h:1175
BJ_INLINE bj_real_t bj_vec4_len(const bj_vec4 v)
Computes the length of the vec4.
Definition linmath.h:490
BJ_INLINE void bj_vec2_min(bj_vec2 res, const bj_vec2 a, const bj_vec2 b)
Computes the component-wise minimum of two 2D vectors.
Definition linmath.h:202
BJ_INLINE bj_real_t bj_vec2_len(const bj_vec2 v)
Computes the length of the vec2.
Definition linmath.h:179
bj_real_t bj_vec4[4]
Defines a 4D vector type.
Definition linmath.h:65
BJ_INLINE void bj_vec2_copy(bj_vec2 res, const bj_vec2 src)
Copies the contents of one 2D vector to another.
Definition linmath.h:225
BJ_INLINE void bj_mat4_col(bj_vec4 res, const bj_mat4 mat, int c)
Retrieves a specific column from a 4x4 matrix.
Definition linmath.h:641
BJ_INLINE void bj_mat4_frustum(bj_mat4 fmat, bj_real_t l, bj_real_t r, bj_real_t b, bj_real_t t, bj_real_t n, bj_real_t f)
Generates a perspective projection matrix for a frustum.
Definition linmath.h:1091
BJ_INLINE void bj_mat4_perspective(bj_mat4 pmat, bj_real_t y_fov, bj_real_t aspect, bj_real_t n, bj_real_t f)
Generates a perspective projection matrix based on field of view.
Definition linmath.h:1143
BJ_INLINE void bj_vec3_add(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs)
Set res to the result of lhs+rhs.
Definition linmath.h:265
BJ_INLINE bj_real_t bj_vec2_dot(const bj_vec2 a, const bj_vec2 b)
Computes the dot product of a abnd b
Definition linmath.h:169
BJ_INLINE void bj_vec4_apply(bj_vec4 res, const bj_vec4 a, bj_real_t(*f)(bj_real_t))
Invoke the given function to each scalar of the bj_vec4.
Definition linmath.h:424
BJ_INLINE void bj_mat4_rotate_from_quat(bj_mat4 R, const bj_mat4 M, const bj_quat q)
Applies a quaternion rotation to each column of a matrix.
Definition linmath.h:1376
BJ_INLINE void bj_mat4_rotate_arcball(bj_mat4 R, const bj_mat4 M, bj_vec2 const _a, bj_vec2 const _b, bj_real_t s)
Rotates a matrix based on arcball-style rotation from two 2D vectors.
Definition linmath.h:965
BJ_INLINE void bj_vec4_min(bj_vec4 res, const bj_vec4 a, const bj_vec4 b)
Computes the component-wise minimum of two 4D vectors.
Definition linmath.h:515
BJ_INLINE void bj_mat4_sub(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
Subtracts one 4x4 matrix from another.
Definition linmath.h:691
BJ_INLINE void bj_vec2_scale_each(bj_vec2 res, const bj_vec2 v, const bj_vec2 s)
Multiply each scalar of v by the respecting scalar in s.
Definition linmath.h:157
BJ_INLINE void bj_quat_from_mat4(bj_quat q, const bj_mat4 M)
Converts a 4x4 rotation matrix to a quaternion.
Definition linmath.h:1396
BJ_INLINE void bj_mat4_mul_outer(bj_mat4 res, const bj_vec3 a, const bj_vec3 b)
Computes the outer product of two 3D vectors and stores the result in a 4x4 matrix.
Definition linmath.h:824
BJ_INLINE void bj_vec2_sub(bj_vec2 res, const bj_vec2 lhs, const bj_vec2 rhs)
Set res to the result of lhs-rhs.
Definition linmath.h:133
BJ_INLINE void bj_ma4_rotate_y(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
Rotates a 4x4 matrix around the Y axis by a given angle.
Definition linmath.h:914
BJ_INLINE void bj_vec4_reflect(bj_vec4 res, const bj_vec4 v, const bj_vec4 n)
Reflects a 4D vector around a given normal.
Definition linmath.h:577
BJ_INLINE void bj_mat4_mul_vec4(bj_vec4 res, const bj_mat4 mat, const bj_vec4 v)
Multiplies a 4x4 matrix by a 4D vector.
Definition linmath.h:765
BJ_INLINE void bj_vec3_apply(bj_vec3 res, const bj_vec3 a, bj_real_t(*f)(bj_real_t))
Invoke the given function to each scalar of the bj_vec3.
Definition linmath.h:251
BJ_INLINE void bj_mat4_add(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
Adds two 4x4 matrices.
Definition linmath.h:675
#define bj_real_t
Alias for float type.
Definition linmath.h:26
bj_real_t bj_quat[4]
Defines a quaternion type.
Definition linmath.h:87
BJ_INLINE bj_real_t bj_vec4_dot(const bj_vec4 a, const bj_vec4 b)
Computes the dot product of a abnd b
Definition linmath.h:480
BJ_INLINE void bj_mat4_transpose(bj_mat4 res, const bj_mat4 mat)
Transposes a 4x4 matrix.
Definition linmath.h:657
BJ_INLINE void bj_vec4_add(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs)
Set res to the result of lhs+rhs.
Definition linmath.h:438
BJ_INLINE void bj_quat_identity(bj_quat q)
Sets a quaternion to the identity quaternion.
Definition linmath.h:1237
BJ_INLINE void bj_vec3_sub(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs)
Set res to the result of lhs-rhs.
Definition linmath.h:278
BJ_INLINE void bj_vec2_max(bj_vec2 res, const bj_vec2 a, const bj_vec2 b)
Computes the component-wise maximum of two 2D vectors.
Definition linmath.h:214
BJ_INLINE void bj_ma4_rotate_z(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
Rotates a 4x4 matrix around the Z-axis by a given angle.
Definition linmath.h:937
BJ_INLINE void bj_vec4_max(bj_vec4 res, const bj_vec4 a, const bj_vec4 b)
Computes the component-wise maximum of two 4D vectors.
Definition linmath.h:529
BJ_INLINE void bj_vec4_set(bj_vec2 res, bj_real_t a, bj_real_t b, bj_real_t c, bj_real_t d)
Directly set the scalar values of a bj_vec4 object.
Definition linmath.h:412
BJ_INLINE void bj_vec3_min(bj_vec3 res, const bj_vec3 a, const bj_vec3 b)
Computes the component-wise minimum of two 3D vectors.
Definition linmath.h:338
BJ_INLINE void bj_mat4_from_quat(bj_mat4 res, const bj_quat q)
Converts a quaternion to a 4x4 rotation matrix.
Definition linmath.h:1337
BJ_INLINE void bj_mat4_scale_xyz(bj_mat4 res, const bj_mat4 mat, bj_real_t x, bj_real_t y, bj_real_t z)
Scales the X, Y, and Z components of a 4x4 matrix.
Definition linmath.h:726
bj_vec4 bj_mat4[4]
Defines a 4x4 matrix type.
Definition linmath.h:76
BJ_INLINE void bj_mat4_ortho(bj_mat4 omat, bj_real_t l, bj_real_t r, bj_real_t b, bj_real_t t, bj_real_t n, bj_real_t f)
Generates an orthographic projection matrix.
Definition linmath.h:1118
BJ_INLINE void bj_quat_mul(bj_quat res, const bj_quat p, const bj_quat q)
Multiplies two quaternions.
Definition linmath.h:1253
BJ_INLINE void bj_mat4_translation_inplace(bj_mat4 M, bj_real_t x, bj_real_t y, bj_real_t z)
Applies a translation transformation to a 4x4 matrix in-place.
Definition linmath.h:804
BJ_INLINE void bj_mat4_rotate(bj_mat4 res, const bj_mat4 mat, bj_real_t x, bj_real_t y, bj_real_t z, bj_real_t angle)
Rotates a 4x4 matrix by a given axis and angle.
Definition linmath.h:846
BJ_INLINE void bj_vec4_sub(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs)
Set res to the result of lhs-rhs.
Definition linmath.h:452
BJ_INLINE void bj_vec2_set(bj_vec2 res, bj_real_t a, bj_real_t b)
Directly set the scalar values of a bj_vec2 object.
Definition linmath.h:97
BJ_INLINE void bj_vec3_reflect(bj_vec3 res, const bj_vec3 v, const bj_vec3 n)
Reflects a 3D vector around a given normal.
Definition linmath.h:393
BJ_INLINE void bj_vec2_scale(bj_vec2 res, const bj_vec2 v, bj_real_t s)
Set res to the result of multiplying v by s.
Definition linmath.h:145
BJ_INLINE void bj_vec3_cross(bj_vec3 res, const bj_vec3 l, const bj_vec3 r)
Computes the 3D cross product of two 3D vectors.
Definition linmath.h:376
BJ_INLINE void bj_quat_rotation(bj_quat res, bj_real_t angle, const bj_vec3 axis)
Creates a rotation quaternion based on an angle and axis.
Definition linmath.h:1295
BJ_INLINE void bj_mat4_row(bj_vec4 res, const bj_mat4 mat, int r)
Retrieves a specific row from a 4x4 matrix.
Definition linmath.h:625
BJ_INLINE bj_real_t bj_vec3_len(const bj_vec3 v)
Computes the length of the vec3.
Definition linmath.h:314
BJ_INLINE bj_real_t bj_vec3_dot(const bj_vec3 a, const bj_vec3 b)
Computes the dot product of a abnd b
Definition linmath.h:304
BJ_INLINE void bj_mat4_identity(bj_mat4 mat)
Initializes a 4x4 matrix to the identity matrix.
Definition linmath.h:592
BJ_INLINE void bj_vec2_add(bj_vec2 res, const bj_vec2 lhs, const bj_vec2 rhs)
Set res to the result of lhs+rhs.
Definition linmath.h:121
BJ_INLINE void bj_vec2_apply(bj_vec2 res, const bj_vec2 a, bj_real_t(*f)(bj_real_t))
Invoke the given function to each scalar of the bj_vec2.
Definition linmath.h:109
BJ_INLINE void bj_vec3_set(bj_vec2 res, bj_real_t a, bj_real_t b, bj_real_t c)
Directly set the scalar values of a bj_vec3 object.
Definition linmath.h:239
BJ_INLINE void bj_vec3_scale(bj_vec3 res, const bj_vec3 v, bj_real_t s)
Set res to the result of multiplying v by s.
Definition linmath.h:291
BJ_INLINE void bj_vec3_copy(bj_vec3 res, const bj_vec3 src)
Copies the contents of one 3D vector to another.
Definition linmath.h:363
BJ_INLINE void bj_vec2_normalize(bj_vec2 res, const bj_vec2 v)
Normalizes the provided vec2.
Definition linmath.h:189
BJ_INLINE void bj_vec3_normalize(bj_vec3 res, const bj_vec3 v)
Normalizes the provided vec3.
Definition linmath.h:324
BJ_INLINE void bj_ma4_rotate_x(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
Rotates a 4x4 matrix around the X axis by a given angle.
Definition linmath.h:891
BJ_INLINE void bj_vec4_cross(bj_vec4 res, const bj_vec4 l, const bj_vec4 r)
Computes the 3D cross product of two 4D vectors, assuming w = 1.0.
Definition linmath.h:559
BJ_INLINE void bj_vec3_max(bj_vec3 res, const bj_vec3 a, const bj_vec3 b)
Computes the component-wise maximum of two 3D vectors.
Definition linmath.h:351
BJ_INLINE void bj_quat_conjugate(bj_quat res, const bj_quat q)
Computes the conjugate of a quaternion.
Definition linmath.h:1277
BJ_INLINE void bj_mat4_inverse(bj_mat4 res, const bj_mat4 mat)
Inverts a 4x4 matrix.
Definition linmath.h:1006
BJ_INLINE void bj_vec4_scale(bj_vec4 res, const bj_vec4 v, bj_real_t s)
Set res to the result of multiplying v by s.
Definition linmath.h:466
BJ_INLINE void bj_mat4_copy(bj_mat4 to, const bj_mat4 from)
Copies a 4x4 matrix from one to another.
Definition linmath.h:609
BJ_INLINE void bj_mat4_scale(bj_mat4 res, const bj_mat4 lhs, bj_real_t k)
Scales a 4x4 matrix by a scalar.
Definition linmath.h:707
BJ_INLINE void bj_vec4_normalize(bj_vec4 res, const bj_vec4 v)
Normalizes the provided vec4.
Definition linmath.h:500
BJ_INLINE void bj_vec4_copy(bj_vec4 res, const bj_vec4 src)
Copies the contents of one 4D vector to another.
Definition linmath.h:542
BJ_INLINE void bj_mat4_orthonormalize(bj_mat4 res, const bj_mat4 mat)
Orthonormalizes the rows of a 4x4 matrix.
Definition linmath.h:1055
BJ_INLINE void bj_mat4_translation(bj_mat4 res, bj_real_t x, bj_real_t y, bj_real_t z)
Creates a 4x4 translation matrix.
Definition linmath.h:785
bj_real_t bj_vec3[3]
Defines a 3D vector type.
Definition linmath.h:54
BJ_INLINE void bj_mat4_mul(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
Multiplies two 4x4 matrices.
Definition linmath.h:743
bj_real_t bj_vec2[2]
Defines a 2D vector type.
Definition linmath.h:43
BJ_INLINE void bj_quat_mul_vec3(bj_vec3 res, const bj_quat q, const bj_vec3 v)
Applies a quaternion rotation to a 3D vector.
Definition linmath.h:1314
Linear math library.