kiba-engine
mat.h
1 #pragma once
2 
3 #include <kiba/defines.h>
4 #include <kiba/math/math.h>
5 #include <kiba/math/vec.h>
6 
7 static inline f32 radians_to_degrees(f32 angle) { return angle * (180.f / PI_F32); }
8 
9 static inline f32 degrees_to_radians(f32 angle) { return angle * (PI_F32 / 180.f); }
10 
11 typedef union {
12  vec4 rows[4];
13 
14  struct {
15  f32 _v00, _v01, _v02, _v03;
16  f32 _v10, _v11, _v12, _v13;
17  f32 _v20, _v21, _v22, _v23;
18  f32 _v30, _v31, _v32, _v33;
19  };
20  f32 raw[4][4];
21 } mat4;
22 
23 STATIC_ASSERT(sizeof(mat4) == sizeof(f32[4][4]), "mat4's general layout must be identical to its raw format");
24 
25 static mat4 mat4_identity(void) {
26  return (mat4){
27  .raw[0][0] = 1,
28  .raw[1][1] = 1,
29  .raw[2][2] = 1,
30  .raw[3][3] = 1,
31  };
32 }
33 
34 void mat4_print(mat4 m);
35 
36 void mat4_print(mat4 m) {
37  UNUSED(m);
38  for (u32 i = 0; i < 4; ++i) {
39  KB_DEBUG("{f32} {f32} {f32} {f32}", m.raw[i][0], m.raw[i][1], m.raw[i][2], m.raw[i][3]);
40  }
41 }
42 
43 mat4 mat4_transpose(mat4 m);
44 
45 mat4 mat4_transpose(mat4 m) {
46  return (mat4){
47  .raw[0][0] = m.raw[0][0],
48  .raw[0][1] = m.raw[1][0],
49  .raw[0][2] = m.raw[2][0],
50  .raw[0][3] = m.raw[3][0],
51  .raw[1][0] = m.raw[0][1],
52  .raw[1][1] = m.raw[1][1],
53  .raw[1][2] = m.raw[2][1],
54  .raw[1][3] = m.raw[3][1],
55  .raw[2][0] = m.raw[0][2],
56  .raw[2][1] = m.raw[1][2],
57  .raw[2][2] = m.raw[2][2],
58  .raw[2][3] = m.raw[3][2],
59  .raw[3][0] = m.raw[0][3],
60  .raw[3][1] = m.raw[1][3],
61  .raw[3][2] = m.raw[2][3],
62  .raw[3][3] = m.raw[3][3],
63  };
64 }
65 
66 static mat4 mat4_rotate(mat4 input, f32 angle_radians, vec3 axis) {
67  f32 sin_a = sin_f32(angle_radians);
68  f32 cos_a = cos_f32(angle_radians);
69  mat4 rot_mat = {
70  .raw[0][0] = cos_a + axis.x * axis.x * (1.f - cos_a),
71  .raw[0][1] = axis.x * axis.y * (1.f - cos_a) - axis.z * sin_a,
72  .raw[0][2] = axis.x * axis.z * (1.f - cos_a) + axis.y * sin_a,
73  .raw[0][3] = 0.f,
74  .raw[1][0] = axis.y * axis.x * (1.f - cos_a) + axis.z * sin_a,
75  .raw[1][1] = cos_a + axis.y * axis.y * (1.f - cos_a),
76  .raw[1][2] = axis.y * axis.z * (1.f - cos_a) - axis.x * sin_a,
77  .raw[1][3] = 0.f,
78  .raw[2][0] = axis.z * axis.x * (1.f - cos_a) - axis.y * sin_a,
79  .raw[2][1] = axis.z * axis.y * (1.f - cos_a) + axis.x * sin_a,
80  .raw[2][2] = cos_a + axis.z * axis.z * (1.f - cos_a),
81  .raw[2][3] = 0.f,
82  .raw[3][0] = 0.f,
83  .raw[3][1] = 0.f,
84  .raw[3][2] = 0.f,
85  .raw[3][3] = 1.f,
86  };
87 
88  UNUSED(input);
89  return rot_mat;
90 }
91 
92 static mat4 mat4_look_at(vec3 eye, vec3 center, vec3 up) {
93  vec3 forward = vec3_normalize(vec3_sub(center, eye));
94  vec3 u = vec3_normalize(vec3_cross_product(forward, up));
95  vec3 v = vec3_normalize(vec3_cross_product(u, forward));
96  vec3 w = vec3_mul_scalar(forward, -1.f);
97  vec3 translation = vec3_create(vec3_dot(eye, u), vec3_dot(eye, v), vec3_dot(eye, w));
98  return (mat4){
99  .raw[0][0] = u.x,
100  .raw[1][0] = u.y,
101  .raw[2][0] = u.z,
102  .raw[0][1] = v.x,
103  .raw[1][1] = v.y,
104  .raw[2][1] = v.z,
105  .raw[0][2] = w.x,
106  .raw[1][2] = w.y,
107  .raw[2][2] = w.z,
108  .raw[0][3] = 0.f,
109  .raw[1][3] = 0.f,
110  .raw[2][3] = 0.f,
111  .raw[3][3] = 1.f,
112  .raw[3][0] = -translation.x,
113  .raw[3][1] = -translation.y,
114  .raw[3][2] = -translation.z,
115  };
116 }
117 
118 static inline mat4 mat4_perspective(f32 vert_angle_radians, f32 aspect_ratio, f32 near, f32 far) {
119  f32 f = 1.f / tanf(vert_angle_radians / 2);
120  return (mat4){
121  .raw[0][0] = f / aspect_ratio,
122  .raw[1][1] = -f,
123  .raw[2][2] = far / (near - far),
124  .raw[2][3] = -1.f,
125  .raw[3][2] = -(far * near) / (far - near),
126  .raw[3][3] = 1.f,
127  };
128 }
129 
130 static inline f32 mat3_minor(const mat4 m, usize row, usize col) {
131  const usize first_r = (row + 1) % 3;
132  const usize second_r = (row + 2) % 3;
133  const usize first_c = (col + 1) % 3;
134  const usize second_c = (col + 2) % 3;
135  return m.raw[first_r][first_c] * m.raw[second_r][second_c] - m.raw[first_r][second_c] * m.raw[second_r][first_c];
136 }
137 
138 static inline mat4 mat3_cofactor(const mat4 m) {
139  mat4 res = mat4_identity();
140  for (usize r = 0; r < 3; ++r) {
141  for (usize c = 0; c < 3; ++c) {
142  res.raw[r][c] = mat3_minor(m, r, c);
143  }
144  }
145  return res;
146 }
147 
148 static inline mat4 mat3_adjoint(const mat4 m) { return mat4_transpose(mat3_cofactor(m)); }
149 
150 static inline f32 mat3_det(const mat4 m) {
151  return m._v00 * m._v11 * m._v22 + m._v01 * m._v12 * m._v20 + m._v02 * m._v10 * m._v21 - m._v00 * m._v12 * m._v21
152  - m._v01 * m._v10 * m._v22 - m._v02 * m._v11 * m._v20;
153 }
154 
155 static inline mat4 mat3_inverse(const mat4 m) {
156  const f32 det = mat3_det(m);
157  if (det == 0.f) {
158  return mat4_identity();
159  }
160  mat4 res = mat3_adjoint(m);
161  for (usize r = 0; r < 3; ++r) {
162  for (usize c = 0; c < 3; ++c) {
163  res.raw[r][c] /= det;
164  }
165  }
166  return res;
167 }
Global typedefs and macros.
#define UNUSED(x)
Mark parameter as unused.
Definition: defines.h:21
#define KB_DEBUG(...)
Log entry with debug log level.
Definition: log.h:163
#define STATIC_ASSERT
Performs a static assert.
Definition: log.h:75
Definition: mat.h:11
Definition: vec.h:6
Definition: vec.h:106