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
136BJ_INLINE void bj_vec2_add_scaled(bj_vec2 res, const bj_vec2 a, const bj_vec2 b, bj_real_t s)
137{
138 res[0] = a[0] + b[0] * s;
139 res[1] = a[1] + b[1] * s;
140}
141
149BJ_INLINE void bj_vec2_sub(bj_vec2 res, const bj_vec2 lhs, const bj_vec2 rhs) {
150 res[0] = lhs[0] - rhs[0];
151 res[1] = lhs[1] - rhs[1];
152}
153
161BJ_INLINE void bj_vec2_scale(bj_vec2 res, const bj_vec2 v, bj_real_t s) {
162 res[0] = v[0] * s;
163 res[1] = v[1] * s;
164}
165
173BJ_INLINE void bj_vec2_scale_each(bj_vec2 res, const bj_vec2 v, const bj_vec2 s) {
174 res[0] = v[0] * s[0];
175 res[1] = v[1] * s[1];
176}
177
185BJ_INLINE bj_real_t bj_vec2_dot(const bj_vec2 a, const bj_vec2 b) {
186 return a[0] * b[0] + a[1] * b[1];
187}
188
195BJ_INLINE bj_real_t bj_vec2_len(const bj_vec2 v) {
196 return real_sqrt(v[0] * v[0] + v[1] * v[1]);
197}
198
205BJ_INLINE void bj_vec2_normalize(bj_vec2 res, const bj_vec2 v) {
206 bj_real_t inv_len = 1.0f / real_sqrt(v[0] * v[0] + v[1] * v[1]);
207 res[0] = v[0] * inv_len;
208 res[1] = v[1] * inv_len;
209}
210
218BJ_INLINE void bj_vec2_min(bj_vec2 res, const bj_vec2 a, const bj_vec2 b) {
219 res[0] = a[0] < b[0] ? a[0] : b[0];
220 res[1] = a[1] < b[1] ? a[1] : b[1];
221}
222
230BJ_INLINE void bj_vec2_max(bj_vec2 res, const bj_vec2 a, const bj_vec2 b) {
231 res[0] = a[0] > b[0] ? a[0] : b[0];
232 res[1] = a[1] > b[1] ? a[1] : b[1];
233}
234
241BJ_INLINE void bj_vec2_copy(bj_vec2 res, const bj_vec2 src) {
242 res[0] = src[0];
243 res[1] = src[1];
244}
245
255BJ_INLINE void bj_vec3_set(bj_vec3 res, bj_real_t a, bj_real_t b, bj_real_t c) {
256 res[0] = a; res[1] = b; res[2] = c;
257}
258
267BJ_INLINE void bj_vec3_apply(bj_vec3 res, const bj_vec3 a, bj_real_t(*f)(bj_real_t)) {
268 res[0] = f(a[0]);
269 res[1] = f(a[1]);
270 res[2] = f(a[2]);
271}
272
273
281BJ_INLINE void bj_vec3_add(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs) {
282 res[0] = lhs[0] + rhs[0];
283 res[1] = lhs[1] + rhs[1];
284 res[2] = lhs[2] + rhs[2];
285}
286
297BJ_INLINE void bj_vec3_add_scaled(bj_vec3 res, const bj_vec3 a, const bj_vec3 b, bj_real_t s) {
298 res[0] = a[0] + b[0] * s;
299 res[1] = a[1] + b[1] * s;
300 res[2] = a[2] + b[2] * s;
301}
302
303
311BJ_INLINE void bj_vec3_sub(bj_vec3 res, const bj_vec3 lhs, const bj_vec3 rhs) {
312 res[0] = lhs[0] - rhs[0];
313 res[1] = lhs[1] - rhs[1];
314 res[2] = lhs[2] - rhs[2];
315}
316
324BJ_INLINE void bj_vec3_scale(bj_vec3 res, const bj_vec3 v, bj_real_t s) {
325 res[0] = v[0] * s;
326 res[1] = v[1] * s;
327 res[2] = v[2] * s;
328}
329
337BJ_INLINE bj_real_t bj_vec3_dot(const bj_vec3 a, const bj_vec3 b) {
338 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
339}
340
347BJ_INLINE bj_real_t bj_vec3_len(const bj_vec3 v) {
348 return real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
349}
350
357BJ_INLINE void bj_vec3_normalize(bj_vec3 res, const bj_vec3 v) {
358 bj_real_t inv_len = 1.0f / real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
359 res[0] = v[0] * inv_len;
360 res[1] = v[1] * inv_len;
361 res[2] = v[2] * inv_len;
362}
363
371BJ_INLINE void bj_vec3_min(bj_vec3 res, const bj_vec3 a, const bj_vec3 b) {
372 res[0] = a[0] < b[0] ? a[0] : b[0];
373 res[1] = a[1] < b[1] ? a[1] : b[1];
374 res[2] = a[2] < b[2] ? a[2] : b[2];
375}
376
384BJ_INLINE void bj_vec3_max(bj_vec3 res, const bj_vec3 a, const bj_vec3 b) {
385 res[0] = a[0] > b[0] ? a[0] : b[0];
386 res[1] = a[1] > b[1] ? a[1] : b[1];
387 res[2] = a[2] > b[2] ? a[2] : b[2];
388}
389
396BJ_INLINE void bj_vec3_copy(bj_vec3 res, const bj_vec3 src) {
397 res[0] = src[0];
398 res[1] = src[1];
399 res[2] = src[2];
400}
401
409BJ_INLINE void bj_vec3_cross(bj_vec3 res, const bj_vec3 l, const bj_vec3 r)
410{
411 res[0] = l[1] * r[2] - l[2] * r[1];
412 res[1] = l[2] * r[0] - l[0] * r[2];
413 res[2] = l[0] * r[1] - l[1] * r[0];
414}
415
426BJ_INLINE void bj_vec3_reflect(bj_vec3 res, const bj_vec3 v, const bj_vec3 n)
427{
428 const bj_real_t p = 2.f * bj_vec3_dot(v, n);
429 for (int i = 0; i < 3; ++i) {
430 res[i] = v[i] - p * n[i];
431 }
432}
433
434
445BJ_INLINE void bj_vec4_set(bj_vec2 res, bj_real_t a, bj_real_t b, bj_real_t c, bj_real_t d) {
446 res[0] = a; res[1] = b; res[2] = c; res[3] = d;
447}
448
457BJ_INLINE void bj_vec4_apply(bj_vec4 res, const bj_vec4 a, bj_real_t(*f)(bj_real_t)) {
458 res[0] = f(a[0]);
459 res[1] = f(a[1]);
460 res[2] = f(a[2]);
461 res[3] = f(a[3]);
462}
463
471BJ_INLINE void bj_vec4_add(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs) {
472 res[0] = lhs[0] + rhs[0];
473 res[1] = lhs[1] + rhs[1];
474 res[2] = lhs[2] + rhs[2];
475 res[3] = lhs[3] + rhs[3];
476}
477
488BJ_INLINE void bj_vec4_add_scaled(bj_vec4 res, const bj_vec4 a, const bj_vec4 b, bj_real_t s) {
489 res[0] = a[0] + b[0] * s;
490 res[1] = a[1] + b[1] * s;
491 res[2] = a[2] + b[2] * s;
492 res[3] = a[3] + b[3] * s;
493}
494
502BJ_INLINE void bj_vec4_sub(bj_vec4 res, const bj_vec4 lhs, const bj_vec4 rhs) {
503 res[0] = lhs[0] - rhs[0];
504 res[1] = lhs[1] - rhs[1];
505 res[2] = lhs[2] - rhs[2];
506 res[3] = lhs[3] - rhs[3];
507}
508
516BJ_INLINE void bj_vec4_scale(bj_vec4 res, const bj_vec4 v, bj_real_t s) {
517 res[0] = v[0] * s;
518 res[1] = v[1] * s;
519 res[2] = v[2] * s;
520 res[3] = v[3] * s;
521}
522
530BJ_INLINE bj_real_t bj_vec4_dot(const bj_vec4 a, const bj_vec4 b) {
531 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
532}
533
540BJ_INLINE bj_real_t bj_vec4_len(const bj_vec4 v) {
541 return real_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
542}
543
550BJ_INLINE void bj_vec4_normalize(bj_vec4 res, const bj_vec4 v) {
551 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]);
552 res[0] = v[0] * inv_len;
553 res[1] = v[1] * inv_len;
554 res[2] = v[2] * inv_len;
555 res[3] = v[3] * inv_len;
556}
557
565BJ_INLINE void bj_vec4_min(bj_vec4 res, const bj_vec4 a, const bj_vec4 b) {
566 res[0] = a[0] < b[0] ? a[0] : b[0];
567 res[1] = a[1] < b[1] ? a[1] : b[1];
568 res[2] = a[2] < b[2] ? a[2] : b[2];
569 res[3] = a[3] < b[3] ? a[3] : b[3];
570}
571
579BJ_INLINE void bj_vec4_max(bj_vec4 res, const bj_vec4 a, const bj_vec4 b) {
580 res[0] = a[0] > b[0] ? a[0] : b[0];
581 res[1] = a[1] > b[1] ? a[1] : b[1];
582 res[2] = a[2] > b[2] ? a[2] : b[2];
583 res[3] = a[3] > b[3] ? a[3] : b[3];
584}
585
592BJ_INLINE void bj_vec4_copy(bj_vec4 res, const bj_vec4 src) {
593 res[0] = src[0];
594 res[1] = src[1];
595 res[2] = src[2];
596 res[3] = src[3];
597}
598
609BJ_INLINE void bj_vec4_cross(bj_vec4 res, const bj_vec4 l, const bj_vec4 r)
610{
611 res[0] = l[1] * r[2] - l[2] * r[1];
612 res[1] = l[2] * r[0] - l[0] * r[2];
613 res[2] = l[0] * r[1] - l[1] * r[0];
614 res[3] = 1.f;
615}
616
627BJ_INLINE void bj_vec4_reflect(bj_vec4 res, const bj_vec4 v, const bj_vec4 n)
628{
629 bj_real_t p = 2.f * bj_vec4_dot(v, n);
630 for (int i = 0; i < 4; ++i) {
631 res[i] = v[i] - p * n[i];
632 }
633}
634
642BJ_INLINE void bj_mat4_identity(bj_mat4 mat)
643{
644 for (int i = 0; i < 4; ++i) {
645 for (int j = 0; j < 4; ++j) {
646 mat[i][j] = i == j ? 1.f : 0.f;
647 }
648 }
649}
650
659BJ_INLINE void bj_mat4_copy(bj_mat4 to, const bj_mat4 from)
660{
661 for (int i = 0; i < 4; ++i) {
662 bj_vec4_copy(to[i], from[i]);
663 }
664}
665
675BJ_INLINE void bj_mat4_row(bj_vec4 res, const bj_mat4 mat, int r)
676{
677 for (int k = 0; k < 4; ++k) {
678 res[k] = mat[k][r];
679 }
680}
681
691BJ_INLINE void bj_mat4_col(bj_vec4 res, const bj_mat4 mat, int c)
692{
693 for (int k = 0; k < 4; ++k) {
694 res[k] = mat[c][k];
695 }
696}
697
707BJ_INLINE void bj_mat4_transpose(bj_mat4 res, const bj_mat4 mat)
708{
709 for (int j = 0; j < 4; ++j) {
710 for (int i = 0; i < 4; ++i) {
711 res[i][j] = mat[j][i];
712 }
713 }
714}
715
725BJ_INLINE void bj_mat4_add(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
726{
727 for (int i = 0; i < 4; ++i) {
728 bj_vec4_add(res[i], lhs[i], rhs[i]);
729 }
730}
731
741BJ_INLINE void bj_mat4_sub(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
742{
743 for (int i = 0; i < 4; ++i) {
744 bj_vec4_sub(res[i], lhs[i], rhs[i]);
745 }
746}
747
757BJ_INLINE void bj_mat4_scale(bj_mat4 res, const bj_mat4 lhs, bj_real_t k)
758{
759 for (int i = 0; i < 4; ++i) {
760 bj_vec4_scale(res[i], lhs[i], k);
761 }
762}
763
776BJ_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)
777{
778 bj_vec4_scale(res[0], mat[0], x);
779 bj_vec4_scale(res[1], mat[1], y);
780 bj_vec4_scale(res[2], mat[2], z);
781 bj_vec4_copy(res[3], mat[3]);
782}
783
793BJ_INLINE void bj_mat4_mul(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
794{
795 bj_mat4 temp;
796 for (int c = 0; c < 4; ++c) {
797 for (int r = 0; r < 4; ++r) {
798 temp[c][r] = 0.f;
799 for (int k = 0; k < 4; ++k)
800 temp[c][r] += lhs[k][r] * rhs[c][k];
801 }
802 }
803 bj_mat4_copy(res, temp);
804}
805
815BJ_INLINE void bj_mat4_mul_vec4(bj_vec4 res, const bj_mat4 mat, const bj_vec4 v)
816{
817 for (int j = 0; j < 4; ++j) {
818 res[j] = 0.f;
819 for (int i = 0; i < 4; ++i) {
820 res[j] += mat[i][j] * v[i];
821 }
822 }
823}
824
836{
837 bj_mat4_identity(res);
838 res[3][0] = x;
839 res[3][1] = y;
840 res[3][2] = z;
841}
842
855{
856 bj_vec4 t = { x, y, z, 0 };
857 bj_vec4 r;
858 for (int i = 0; i < 4; ++i) {
859 bj_mat4_row(r, M, i);
860 M[3][i] += bj_vec4_dot(r, t);
861 }
862}
863
874BJ_INLINE void bj_mat4_mul_outer(bj_mat4 res, const bj_vec3 a, const bj_vec3 b)
875{
876 for (int i = 0; i < 4; ++i) {
877 for (int j = 0; j < 4; ++j) {
878 res[i][j] = i < 3 && j < 3 ? a[i] * b[j] : 0.f;
879 }
880 }
881}
882
896BJ_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)
897{
898 bj_real_t s = bj_sinf(angle);
899 bj_real_t c = bj_cosf(angle);
900 bj_vec3 u = { x, y, z };
901
902 if (bj_vec3_len(u) > 1e-4) {
903 bj_vec3_normalize(u, u);
904 bj_mat4 T;
905 bj_mat4_mul_outer(T, u, u);
906
907 bj_mat4 S = {
908 { 0, u[2], -u[1], 0},
909 {-u[2], 0, u[0], 0},
910 { u[1], -u[0], 0, 0},
911 { 0, 0, 0, 0}
912 };
913 bj_mat4_scale(S, S, s);
914
915 bj_mat4 C;
917 bj_mat4_sub(C, C, T);
918
919 bj_mat4_scale(C, C, c);
920
921 bj_mat4_add(T, T, C);
922 bj_mat4_add(T, T, S);
923
924 T[3][3] = 1.f;
925 bj_mat4_mul(res, mat, T);
926 } else {
927 bj_mat4_copy(res, mat);
928 }
929}
930
941BJ_INLINE void bj_ma4_rotate_x(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
942{
943 bj_real_t s = bj_sinf(angle);
944 bj_real_t c = bj_cosf(angle);
945 bj_mat4 R = {
946 {1.f, 0.f, 0.f, 0.f},
947 {0.f, c, s, 0.f},
948 {0.f, -s, c, 0.f},
949 {0.f, 0.f, 0.f, 1.f}
950 };
951 bj_mat4_mul(res, mat, R);
952}
953
964BJ_INLINE void bj_ma4_rotate_y(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
965{
966 bj_real_t s = bj_sinf(angle);
967 bj_real_t c = bj_cosf(angle);
968 bj_mat4 R = {
969 { c, 0.f, -s, 0.f},
970 { 0.f, 1.f, 0.f, 0.f},
971 { s, 0.f, c, 0.f},
972 { 0.f, 0.f, 0.f, 1.f}
973 };
974 bj_mat4_mul(res, mat, R);
975}
976
987BJ_INLINE void bj_ma4_rotate_z(bj_mat4 res, const bj_mat4 mat, bj_real_t angle)
988{
989 bj_real_t s = bj_sinf(angle);
990 bj_real_t c = bj_cosf(angle);
991 bj_mat4 R = {
992 { c, s, 0.f, 0.f},
993 { -s, c, 0.f, 0.f},
994 { 0.f, 0.f, 1.f, 0.f},
995 { 0.f, 0.f, 0.f, 1.f}
996 };
997 bj_mat4_mul(res, mat, R);
998}
999
1000
1015BJ_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)
1016{
1017 bj_vec2 a = { _a[0], _a[1] };
1018 bj_vec2 b = { _b[0], _b[1] };;
1019
1020 bj_real_t z_a = 0.;
1021 bj_real_t z_b = 0.;
1022
1023 if (bj_vec2_len(a) < 1.) {
1024 z_a = real_sqrt(1.f - bj_vec2_dot(a, a));
1025 }
1026 else {
1027 bj_vec2_normalize(a, a);
1028 }
1029
1030 if (bj_vec2_len(b) < 1.) {
1031 z_b = real_sqrt(1.f - bj_vec2_dot(b, b));
1032 }
1033 else {
1034 bj_vec2_normalize(b, b);
1035 }
1036
1037 bj_vec3 a_ = { a[0], a[1], z_a };
1038 bj_vec3 b_ = { b[0], b[1], z_b };
1039
1040 bj_vec3 c_;
1041 bj_vec3_cross(c_, a_, b_);
1042
1043 bj_real_t const angle = real_acos(bj_vec3_dot(a_, b_)) * s;
1044 bj_mat4_rotate(R, M, c_[0], c_[1], c_[2], angle);
1045}
1046
1056BJ_INLINE void bj_mat4_inverse(bj_mat4 res, const bj_mat4 mat) {
1057 bj_real_t s[6];
1058 bj_real_t c[6];
1059 s[0] = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
1060 s[1] = mat[0][0] * mat[1][2] - mat[1][0] * mat[0][2];
1061 s[2] = mat[0][0] * mat[1][3] - mat[1][0] * mat[0][3];
1062 s[3] = mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2];
1063 s[4] = mat[0][1] * mat[1][3] - mat[1][1] * mat[0][3];
1064 s[5] = mat[0][2] * mat[1][3] - mat[1][2] * mat[0][3];
1065
1066 c[0] = mat[2][0] * mat[3][1] - mat[3][0] * mat[2][1];
1067 c[1] = mat[2][0] * mat[3][2] - mat[3][0] * mat[2][2];
1068 c[2] = mat[2][0] * mat[3][3] - mat[3][0] * mat[2][3];
1069 c[3] = mat[2][1] * mat[3][2] - mat[3][1] * mat[2][2];
1070 c[4] = mat[2][1] * mat[3][3] - mat[3][1] * mat[2][3];
1071 c[5] = mat[2][2] * mat[3][3] - mat[3][2] * mat[2][3];
1072
1073 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]);
1074
1075 res[0][0] = (mat[1][1] * c[5] - mat[1][2] * c[4] + mat[1][3] * c[3]) * idet;
1076 res[0][1] = (-mat[0][1] * c[5] + mat[0][2] * c[4] - mat[0][3] * c[3]) * idet;
1077 res[0][2] = (mat[3][1] * s[5] - mat[3][2] * s[4] + mat[3][3] * s[3]) * idet;
1078 res[0][3] = (-mat[2][1] * s[5] + mat[2][2] * s[4] - mat[2][3] * s[3]) * idet;
1079
1080 res[1][0] = (-mat[1][0] * c[5] + mat[1][2] * c[2] - mat[1][3] * c[1]) * idet;
1081 res[1][1] = (mat[0][0] * c[5] - mat[0][2] * c[2] + mat[0][3] * c[1]) * idet;
1082 res[1][2] = (-mat[3][0] * s[5] + mat[3][2] * s[2] - mat[3][3] * s[1]) * idet;
1083 res[1][3] = (mat[2][0] * s[5] - mat[2][2] * s[2] + mat[2][3] * s[1]) * idet;
1084
1085 res[2][0] = (mat[1][0] * c[4] - mat[1][1] * c[2] + mat[1][3] * c[0]) * idet;
1086 res[2][1] = (-mat[0][0] * c[4] + mat[0][1] * c[2] - mat[0][3] * c[0]) * idet;
1087 res[2][2] = (mat[3][0] * s[4] - mat[3][1] * s[2] + mat[3][3] * s[0]) * idet;
1088 res[2][3] = (-mat[2][0] * s[4] + mat[2][1] * s[2] - mat[2][3] * s[0]) * idet;
1089
1090 res[3][0] = (-mat[1][0] * c[3] + mat[1][1] * c[1] - mat[1][2] * c[0]) * idet;
1091 res[3][1] = (mat[0][0] * c[3] - mat[0][1] * c[1] + mat[0][2] * c[0]) * idet;
1092 res[3][2] = (-mat[3][0] * s[3] + mat[3][1] * s[1] - mat[3][2] * s[0]) * idet;
1093 res[3][3] = (mat[2][0] * s[3] - mat[2][1] * s[1] + mat[2][2] * s[0]) * idet;
1094}
1095
1105BJ_INLINE void bj_mat4_orthonormalize(bj_mat4 res, const bj_mat4 mat) {
1106 bj_mat4_copy(res, mat);
1107 bj_real_t s = 1.f;
1108 bj_vec3 h;
1109
1110 bj_vec3_normalize(res[2], res[2]);
1111
1112 s = bj_vec3_dot(res[1], res[2]);
1113 bj_vec3_scale(h, res[2], s);
1114 bj_vec3_sub(res[1], res[1], h);
1115 bj_vec3_normalize(res[1], res[1]);
1116
1117 s = bj_vec3_dot(res[0], res[2]);
1118 bj_vec3_scale(h, res[2], s);
1119 bj_vec3_sub(res[0], res[0], h);
1120
1121 s = bj_vec3_dot(res[0], res[1]);
1122 bj_vec3_scale(h, res[1], s);
1123 bj_vec3_sub(res[0], res[0], h);
1124 bj_vec3_normalize(res[0], res[0]);
1125}
1126
1142 fmat[0][0] = 2.f * n / (r - l);
1143 fmat[0][1] = fmat[0][2] = fmat[0][3] = 0.f;
1144 fmat[1][1] = 2.f * n / (t - b);
1145 fmat[1][0] = fmat[1][2] = fmat[1][3] = 0.f;
1146 fmat[2][0] = (r + l) / (r - l);
1147 fmat[2][1] = (t + b) / (t - b);
1148 fmat[2][2] = -(f + n) / (f - n);
1149 fmat[2][3] = -1.f;
1150 fmat[3][2] = -2.f * (f * n) / (f - n);
1151 fmat[3][0] = fmat[3][1] = fmat[3][3] = 0.f;
1152}
1153
1169 omat[0][0] = 2.f / (r - l);
1170 omat[0][1] = omat[0][2] = omat[0][3] = 0.f;
1171 omat[1][1] = 2.f / (t - b);
1172 omat[1][0] = omat[1][2] = omat[1][3] = 0.f;
1173 omat[2][2] = -2.f / (f - n);
1174 omat[2][0] = omat[2][1] = omat[2][3] = 0.f;
1175 omat[3][0] = -(r + l) / (r - l);
1176 omat[3][1] = -(t + b) / (t - b);
1177 omat[3][2] = -(f + n) / (f - n);
1178 omat[3][3] = 1.f;
1179}
1180
1193BJ_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) {
1194 const bj_real_t a = 1.f / bj_tanf(y_fov / 2.f);
1195 pmat[0][0] = a / aspect;
1196 pmat[0][1] = 0.f;
1197 pmat[0][2] = 0.f;
1198 pmat[0][3] = 0.f;
1199 pmat[1][0] = 0.f;
1200 pmat[1][1] = a;
1201 pmat[1][2] = 0.f;
1202 pmat[1][3] = 0.f;
1203 pmat[2][0] = 0.f;
1204 pmat[2][1] = 0.f;
1205 pmat[2][2] = -((f + n) / (f - n));
1206 pmat[2][3] = -1.f;
1207 pmat[3][0] = 0.f;
1208 pmat[3][1] = 0.f;
1209 pmat[3][2] = -((2.f * f * n) / (f - n));
1210 pmat[3][3] = 0.f;
1211}
1212
1225BJ_INLINE void bj_mat4_lookat(bj_mat4 m, const bj_vec3 eye, const bj_vec3 center, const bj_vec3 up) {
1226 bj_vec3 f;
1227 bj_vec3_sub(f, center, eye);
1228 bj_vec3_normalize(f, f);
1229
1230 bj_vec3 s;
1231 bj_vec3_cross(s, f, up);
1232 bj_vec3_normalize(s, s);
1233
1234 bj_vec3 t;
1235 bj_vec3_cross(t, s, f);
1236
1237 m[0][0] = s[0];
1238 m[0][1] = t[0];
1239 m[0][2] = -f[0];
1240 m[0][3] = 0.f;
1241
1242 m[1][0] = s[1];
1243 m[1][1] = t[1];
1244 m[1][2] = -f[1];
1245 m[1][3] = 0.f;
1246
1247 m[2][0] = s[2];
1248 m[2][1] = t[2];
1249 m[2][2] = -f[2];
1250 m[2][3] = 0.f;
1251
1252 m[3][0] = 0.f;
1253 m[3][1] = 0.f;
1254 m[3][2] = 0.f;
1255 m[3][3] = 1.f;
1256
1257 bj_mat4_translation_inplace(m, -eye[0], -eye[1], -eye[2]);
1258}
1259
1262#define bj_quat_add bj_vec4_add
1263
1266#define bj_quat_sub bj_vec4_sub
1267
1270#define bj_quat_norm bj_vec4_normalize
1271
1274#define bj_quat_scale bj_vec4_scale
1275
1278#define bj_quat_dot bj_vec4_dot
1279
1287BJ_INLINE void bj_quat_identity(bj_quat q)
1288{
1289 q[0] = q[1] = q[2] = 0.f;
1290 q[3] = 1.f;
1291}
1292
1303BJ_INLINE void bj_quat_mul(bj_quat res, const bj_quat p, const bj_quat q)
1304{
1305 bj_vec3 w, tmp;
1306
1307 bj_vec3_cross(tmp, p, q);
1308 bj_vec3_scale(w, p, q[3]);
1309 bj_vec3_add(tmp, tmp, w);
1310 bj_vec3_scale(w, q, p[3]);
1311 bj_vec3_add(tmp, tmp, w);
1312
1313 bj_vec3_copy(res, tmp);
1314 res[3] = p[3] * q[3] - bj_vec3_dot(p, q);
1315}
1316
1327BJ_INLINE void bj_quat_conjugate(bj_quat res, const bj_quat q)
1328{
1329 for (int i = 0; i < 3; ++i) {
1330 res[i] = -q[i];
1331 }
1332 res[3] = q[3];
1333}
1334
1345BJ_INLINE void bj_quat_rotation(bj_quat res, bj_real_t angle, const bj_vec3 axis) {
1346 bj_vec3 axis_norm;
1347 bj_vec3_normalize(axis_norm, axis);
1348 const bj_real_t s = bj_sinf(angle / 2);
1349 const bj_real_t c = bj_cosf(angle / 2);
1350 bj_vec3_scale(res, axis_norm, s);
1351 res[3] = c;
1352}
1353
1364BJ_INLINE void bj_quat_mul_vec3(bj_vec3 res, const bj_quat q, const bj_vec3 v) {
1365 bj_vec3 t;
1366 bj_vec3 q_xyz = { q[0], q[1], q[2] };
1367 bj_vec3 u = { q[0], q[1], q[2] };
1368
1369 bj_vec3_cross(t, q_xyz, v);
1370 bj_vec3_scale(t, t, 2);
1371
1372 bj_vec3_cross(u, q_xyz, t);
1373 bj_vec3_scale(t, t, q[3]);
1374
1375 bj_vec3_add(res, v, t);
1376 bj_vec3_add(res, res, u);
1377}
1378
1387BJ_INLINE void bj_mat4_from_quat(bj_mat4 res, const bj_quat q) {
1388 bj_real_t a = q[3];
1389 bj_real_t b = q[0];
1390 bj_real_t c = q[1];
1391 bj_real_t d = q[2];
1392 bj_real_t a2 = a * a;
1393 bj_real_t b2 = b * b;
1394 bj_real_t c2 = c * c;
1395 bj_real_t d2 = d * d;
1396
1397 res[0][0] = a2 + b2 - c2 - d2;
1398 res[0][1] = 2.f * (b * c + a * d);
1399 res[0][2] = 2.f * (b * d - a * c);
1400 res[0][3] = 0.f;
1401
1402 res[1][0] = 2 * (b * c - a * d);
1403 res[1][1] = a2 - b2 + c2 - d2;
1404 res[1][2] = 2.f * (c * d + a * b);
1405 res[1][3] = 0.f;
1406
1407 res[2][0] = 2.f * (b * d + a * c);
1408 res[2][1] = 2.f * (c * d - a * b);
1409 res[2][2] = a2 - b2 - c2 + d2;
1410 res[2][3] = 0.f;
1411
1412 res[3][0] = res[3][1] = res[3][2] = 0.f;
1413 res[3][3] = 1.f;
1414}
1415
1426BJ_INLINE void bj_mat4_rotate_from_quat(bj_mat4 R, const bj_mat4 M, const bj_quat q) {
1427 bj_quat_mul_vec3(R[0], q, M[0]);
1428 bj_quat_mul_vec3(R[1], q, M[1]);
1429 bj_quat_mul_vec3(R[2], q, M[2]);
1430
1431 R[3][0] = R[3][1] = R[3][2] = 0.f;
1432 R[0][3] = M[0][3];
1433 R[1][3] = M[1][3];
1434 R[2][3] = M[2][3];
1435 R[3][3] = M[3][3];
1436}
1437
1446BJ_INLINE void bj_quat_from_mat4(bj_quat q, const bj_mat4 M) {
1447 bj_real_t r = 0.f;
1448 int i, j, k;
1449
1450 int perm[] = { 0, 1, 2, 0, 1 };
1451 int* p = perm;
1452
1453 for (i = 0; i < 3; i++) {
1454 bj_real_t m = M[i][i];
1455 if (m > r) {
1456 r = m;
1457 p = &perm[i];
1458 }
1459 }
1460
1461 i = p[0];
1462 j = p[1];
1463 k = p[2];
1464
1465 r = real_sqrt(1.f + M[i][i] - M[j][j] - M[k][k]);
1466
1467 if (r < 1e-6f) {
1468 q[0] = 0.f;
1469 q[1] = 0.f;
1470 q[2] = 0.f;
1471 q[3] = 1.f;
1472 return;
1473 }
1474
1475 bj_real_t inv = 0.5f / r;
1476
1477 q[i] = 0.5f * r;
1478 q[j] = (M[i][j] + M[j][i]) * inv;
1479 q[k] = (M[k][i] + M[i][k]) * inv;
1480 q[3] = (M[k][j] - M[j][k]) * inv;
1481}
1482
1483
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:1225
BJ_INLINE bj_real_t bj_vec4_len(const bj_vec4 v)
Computes the length of the vec4.
Definition linmath.h:540
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:218
BJ_INLINE bj_real_t bj_vec2_len(const bj_vec2 v)
Computes the length of the vec2.
Definition linmath.h:195
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:241
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:691
#define bj_sinf
Wrapper for the standard sinf() function.
Definition math.h:137
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:1141
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:1193
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:281
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:185
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:457
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:1426
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:1015
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:565
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:741
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:173
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:1446
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:874
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:149
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:964
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:627
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:815
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:267
BJ_INLINE void bj_vec2_add_scaled(bj_vec2 res, const bj_vec2 a, const bj_vec2 b, bj_real_t s)
Computes res = a + b * s for 2D vectors.
Definition linmath.h:136
BJ_INLINE void bj_mat4_add(bj_mat4 res, const bj_mat4 lhs, const bj_mat4 rhs)
Adds two 4x4 matrices.
Definition linmath.h:725
BJ_INLINE void bj_vec3_set(bj_vec3 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:255
#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:530
#define bj_cosf
Wrapper for the standard cosf() function.
Definition math.h:41
BJ_INLINE void bj_mat4_transpose(bj_mat4 res, const bj_mat4 mat)
Transposes a 4x4 matrix.
Definition linmath.h:707
BJ_INLINE void bj_vec4_add_scaled(bj_vec4 res, const bj_vec4 a, const bj_vec4 b, bj_real_t s)
Computes res = a + b * s for 4D vectors.
Definition linmath.h:488
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:471
BJ_INLINE void bj_quat_identity(bj_quat q)
Sets a quaternion to the identity quaternion.
Definition linmath.h:1287
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:311
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:230
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:987
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:579
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:445
#define bj_tanf
Wrapper for the standard tanf() function.
Definition math.h:153
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:371
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:1387
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:776
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:1168
BJ_INLINE void bj_quat_mul(bj_quat res, const bj_quat p, const bj_quat q)
Multiplies two quaternions.
Definition linmath.h:1303
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:854
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:896
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:502
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:426
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:161
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:409
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:1345
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:675
BJ_INLINE bj_real_t bj_vec3_len(const bj_vec3 v)
Computes the length of the vec3.
Definition linmath.h:347
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:337
BJ_INLINE void bj_mat4_identity(bj_mat4 mat)
Initializes a 4x4 matrix to the identity matrix.
Definition linmath.h:642
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_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:324
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:396
BJ_INLINE void bj_vec2_normalize(bj_vec2 res, const bj_vec2 v)
Normalizes the provided vec2.
Definition linmath.h:205
BJ_INLINE void bj_vec3_normalize(bj_vec3 res, const bj_vec3 v)
Normalizes the provided vec3.
Definition linmath.h:357
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:941
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:609
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:384
BJ_INLINE void bj_quat_conjugate(bj_quat res, const bj_quat q)
Computes the conjugate of a quaternion.
Definition linmath.h:1327
BJ_INLINE void bj_mat4_inverse(bj_mat4 res, const bj_mat4 mat)
Inverts a 4x4 matrix.
Definition linmath.h:1056
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:516
BJ_INLINE void bj_mat4_copy(bj_mat4 to, const bj_mat4 from)
Copies a 4x4 matrix from one to another.
Definition linmath.h:659
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:757
BJ_INLINE void bj_vec3_add_scaled(bj_vec3 res, const bj_vec3 a, const bj_vec3 b, bj_real_t s)
Computes res = a + b * s for 3D vectors.
Definition linmath.h:297
BJ_INLINE void bj_vec4_normalize(bj_vec4 res, const bj_vec4 v)
Normalizes the provided vec4.
Definition linmath.h:550
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:592
BJ_INLINE void bj_mat4_orthonormalize(bj_mat4 res, const bj_mat4 mat)
Orthonormalizes the rows of a 4x4 matrix.
Definition linmath.h:1105
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:835
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:793
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:1364
Linear math library.