GCC Code Coverage Report


libs/base/src/base/
File: mat4.cc
Date: 2025-03-19 20:55:25
Lines:
229/231
99.1%
Functions:
42/42
100.0%
Branches:
62/124
50.0%

Line Branch Exec Source
1 #include "base/mat4.h"
2
3 #include "base/quat.h"
4
5 namespace eu
6 {
7 [[nodiscard]]
8 m4
9 13 m4::from_col_major
10 (
11 float t00, float t01, float t02, float t03,
12 float t10, float t11, float t12, float t13,
13 float t20, float t21, float t22, float t23,
14 float t30, float t31, float t32, float t33
15 )
16 {
17 return
18 {
19 t00, t01, t02, t03,
20 t10, t11, t12, t13,
21 t20, t21, t22, t23,
22 t30, t31, t32, t33
23 13 };
24 }
25
26 [[nodiscard]]
27 m4
28 1 m4::from_major(const v4& major)
29 {
30 1 const float zero = 0;
31 return from_row_major
32 1 (
33 1 major.x, zero, zero, zero,
34 1 zero, major.y, zero, zero,
35 1 zero, zero, major.z, zero,
36 1 zero, zero, zero, major.w
37 1 );
38 }
39
40 [[nodiscard]]
41 m4
42 6 m4::from_translation(const v3& v)
43 {
44 6 const float one = 1;
45 6 const float z = 0;
46 return from_row_major
47 6 (
48 6 one, z, z, v.x,
49 6 z, one, z, v.y,
50 6 z, z, one, v.z,
51 z, z, z, one
52 6 );
53 }
54
55 v4
56 17 m4::get_transformed(const v4& p) const
57 {
58 17 return *this * p;
59 }
60
61 v3
62 16 m4::get_transformed_point(const v3& p) const
63 {
64
3/6
✓ Branch 0 (2 → 3) taken 16 times.
✗ Branch 1 (2 → 8) not taken.
✓ Branch 2 (3 → 4) taken 16 times.
✗ Branch 3 (3 → 8) not taken.
✓ Branch 4 (4 → 5) taken 16 times.
✗ Branch 5 (4 → 8) not taken.
16 return get_transformed(v4{p, 1.0f}).to_vec3_persp_div();
65 }
66
67 v3
68 1 m4::get_transformed_vec(const v3& p) const
69 {
70
3/6
✓ Branch 0 (2 → 3) taken 1 times.
✗ Branch 1 (2 → 8) not taken.
✓ Branch 2 (3 → 4) taken 1 times.
✗ Branch 3 (3 → 8) not taken.
✓ Branch 4 (4 → 5) taken 1 times.
✗ Branch 5 (4 → 8) not taken.
1 return get_transformed(v4{p, 0.0f}).to_vec3(0.0f);
71 }
72
73 n3
74 1 m4::get_transformed_vec(const n3& p) const
75 {
76
2/4
✓ Branch 0 (2 → 3) taken 1 times.
✗ Branch 1 (2 → 7) not taken.
✓ Branch 2 (3 → 4) taken 1 times.
✗ Branch 3 (3 → 7) not taken.
1 return n3{ get_transformed_vec(static_cast<v3>(p))};
77 }
78
79 v3
80 1 m4::get_translation() const
81 {
82 1 return {get(0, 3), get(1, 3), get(2, 3)};
83 }
84
85 [[nodiscard]]
86 m4
87 2 m4::from_rot_x(const An& a)
88 {
89 2 const auto c = cos(a);
90 2 const auto s = sin(a);
91 return from_row_major
92 2 (
93 1, 0, 0, 0,
94 0, c, -s, 0,
95 0, s, c, 0,
96 0, 0, 0, 1
97 2 );
98 }
99
100 m4
101 1 m4::from_rot_y(const An& a)
102 {
103 1 const auto c = cos(a);
104 1 const auto s = sin(a);
105 return from_row_major
106 1 (
107 c, 0, s, 0,
108 0, 1, 0, 0,
109 -s, 0, c, 0,
110 0, 0, 0, 1
111 1 );
112 }
113
114 [[nodiscard]]
115 m4
116 1 m4::from_rot_z(const An& a)
117 {
118 1 const auto c = cos(a);
119 1 const auto s = sin(a);
120 return from_row_major
121 1 (
122 c, -s, 0, 0,
123 s, c, 0, 0,
124 0, 0, 1, 0,
125 0, 0, 0, 1
126 1 );
127 }
128
129 [[nodiscard]]
130 m4
131 6 m4::from(const AA& aa)
132 {
133 6 const float rcos = cos(aa.angle);
134 6 const float rsin = sin(aa.angle);
135
136 6 const auto u = aa.axis.x;
137 6 const auto v = aa.axis.y;
138 6 const auto w = aa.axis.z;
139
140 return m4::from_col_major
141 6 (
142 6 rcos + u * u * (1 - rcos),
143 6 w * rsin + v * u * (1 - rcos),
144 6 -v * rsin + w * u * (1 - rcos),
145 0,
146
147 6 -w * rsin + u * v * (1 - rcos),
148 6 rcos + v * v * (1 - rcos),
149 6 u * rsin + w * v * (1 - rcos),
150 0,
151
152 6 v * rsin + u * w * (1 - rcos),
153 6 -u * rsin + v * w * (1 - rcos),
154 6 rcos + w * w * (1 - rcos),
155 0,
156
157 0,
158 0,
159 0,
160 1
161 6 );
162 }
163
164
165 [[nodiscard]] std::optional<m4>
166 1 m4::from(const Q& q)
167 {
168
1/2
✓ Branch 0 (2 → 3) taken 1 times.
✗ Branch 1 (2 → 13) not taken.
1 const auto aa = AA::from(q);
169
1/2
✗ Branch 0 (4 → 5) not taken.
✓ Branch 1 (4 → 6) taken 1 times.
1 if (!aa)
170 { return std::nullopt; }
171
1/2
✓ Branch 0 (7 → 8) taken 1 times.
✗ Branch 1 (7 → 12) not taken.
1 return m4::from(*aa);
172 }
173
174
175 v4
176 2 m4::get_major() const
177 {
178
1/2
✓ Branch 0 (6 → 7) taken 2 times.
✗ Branch 1 (6 → 10) not taken.
2 return {get(0, 0), get(1, 1), get(2, 2), get(3, 3)};
179 }
180
181 n3
182 6 get_axis(const m4& m, int col)
183 {
184
3/6
✓ Branch 0 (2 → 3) taken 6 times.
✗ Branch 1 (2 → 8) not taken.
✓ Branch 2 (3 → 4) taken 6 times.
✗ Branch 3 (3 → 8) not taken.
✓ Branch 4 (4 → 5) taken 6 times.
✗ Branch 5 (4 → 8) not taken.
6 return n3{m.get_column(col).to_vec3(0.0f)};
185 }
186
187 n3
188 2 m4::get_x_axis() const
189 {
190 2 return get_axis(*this, 0);
191 }
192
193 n3
194 2 m4::get_y_axis() const
195 {
196 2 return get_axis(*this, 1);
197 }
198
199 n3
200 2 m4::get_z_axis() const
201 {
202 2 return get_axis(*this, 2);
203 }
204
205 m4
206 2 m4::get_transposed() const
207 {
208 // https://www.j3d.org/matrix_faq/matrfaq_latest.html
209 return from_col_major
210 2 (
211 get(0, 0), get(0, 1), get(0, 2), get(0, 3),
212 get(1, 0), get(1, 1), get(1, 2), get(1, 3),
213 get(2, 0), get(2, 1), get(2, 2), get(2, 3),
214 get(3, 0), get(3, 1), get(3, 2), get(3, 3)
215 2 );
216 }
217
218 bool
219 2 m4::invert()
220 {
221 // from the glu source?
222 // https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
223
224 float inv[16];
225
226 2 float* m = data;
227
228 2 inv[0] =
229 2 m[5] * m[10] * m[15] - m[5] * m[11] * m[14] -
230 2 m[9] * m[6] * m[15] + m[9] * m[7] * m[14] +
231 2 m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
232 ;
233
234 2 inv[4] =
235 2 -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] +
236 2 m[8] * m[6] * m[15] - m[8] * m[7] * m[14] -
237 2 m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
238 ;
239
240 2 inv[8] =
241 2 m[4] * m[9] * m[15] - m[4] * m[11] * m[13] -
242 2 m[8] * m[5] * m[15] + m[8] * m[7] * m[13] +
243 2 m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
244 ;
245
246 2 inv[12] =
247 2 -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] +
248 2 m[8] * m[5] * m[14] - m[8] * m[6] * m[13] -
249 2 m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
250 ;
251
252 2 inv[1] =
253 2 -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] +
254 2 m[9] * m[2] * m[15] - m[9] * m[3] * m[14] -
255 2 m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
256 ;
257
258 2 inv[5] =
259 2 m[0] * m[10] * m[15] - m[0] * m[11] * m[14] -
260 2 m[8] * m[2] * m[15] + m[8] * m[3] * m[14] +
261 2 m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
262 ;
263
264 2 inv[9] =
265 2 -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] +
266 2 m[8] * m[1] * m[15] - m[8] * m[3] * m[13] -
267 2 m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
268 ;
269
270 2 inv[13] =
271 2 m[0] * m[9] * m[14] - m[0] * m[10] * m[13] -
272 2 m[8] * m[1] * m[14] + m[8] * m[2] * m[13] +
273 2 m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
274 ;
275
276 2 inv[2] =
277 2 m[1] * m[6] * m[15] - m[1] * m[7] * m[14] -
278 2 m[5] * m[2] * m[15] + m[5] * m[3] * m[14] +
279 2 m[13] * m[2] * m[7] - m[13] * m[3] * m[6]
280 ;
281
282 2 inv[6] =
283 2 -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] +
284 2 m[4] * m[2] * m[15] - m[4] * m[3] * m[14] -
285 2 m[12] * m[2] * m[7] + m[12] * m[3] * m[6]
286 ;
287
288 2 inv[10] =
289 2 m[0] * m[5] * m[15] - m[0] * m[7] * m[13] -
290 2 m[4] * m[1] * m[15] + m[4] * m[3] * m[13] +
291 2 m[12] * m[1] * m[7] - m[12] * m[3] * m[5]
292 ;
293
294 2 inv[14] =
295 2 -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] +
296 2 m[4] * m[1] * m[14] - m[4] * m[2] * m[13] -
297 2 m[12] * m[1] * m[6] + m[12] * m[2] * m[5]
298 ;
299
300 2 inv[3] =
301 2 -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] +
302 2 m[5] * m[2] * m[11] - m[5] * m[3] * m[10] -
303 2 m[9] * m[2] * m[7] + m[9] * m[3] * m[6]
304 ;
305
306 2 inv[7] =
307 2 m[0] * m[6] * m[11] - m[0] * m[7] * m[10] -
308 2 m[4] * m[2] * m[11] + m[4] * m[3] * m[10] +
309 2 m[8] * m[2] * m[7] - m[8] * m[3] * m[6]
310 ;
311
312 2 inv[11] =
313 2 -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] +
314 2 m[4] * m[1] * m[11] - m[4] * m[3] * m[9] -
315 2 m[8] * m[1] * m[7] + m[8] * m[3] * m[5]
316 ;
317
318 2 inv[15] =
319 2 m[0] * m[5] * m[10] - m[0] * m[6] * m[9] -
320 2 m[4] * m[1] * m[10] + m[4] * m[2] * m[9] +
321 2 m[8] * m[1] * m[6] - m[8] * m[2] * m[5]
322 ;
323
324 2 const auto inv_det =
325 2 m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] +
326 2 m[3] * inv[12];
327
328
1/2
✗ Branch 0 (2 → 3) not taken.
✓ Branch 1 (2 → 4) taken 2 times.
2 if(inv_det == 0)
329 {
330 return false;
331 }
332
333 2 const auto det = 1.0f / inv_det;
334
335
2/2
✓ Branch 0 (6 → 5) taken 32 times.
✓ Branch 1 (6 → 7) taken 2 times.
34 for(int index = 0; index < 16; index += 1)
336 {
337 32 data[index] = inv[index] * det;
338 }
339
340 2 return true;
341 }
342
343 m4
344 1 m4::get_inverted() const
345 {
346 1 auto r = *this;
347 1 const auto was_inverted = r.invert();
348
1/4
✗ Branch 0 (3 → 4) not taken.
✓ Branch 1 (3 → 10) taken 1 times.
✗ Branch 2 (7 → 8) not taken.
✗ Branch 3 (7 → 12) not taken.
1 ASSERT(was_inverted);
349 1 return r;
350 }
351
352 void
353 1 m4::operator+=(const m4& rhs)
354 {
355 #define OP(i) data[i] += rhs.data[i]
356 1 OP(0); OP(1); OP(2); OP(3);
357 1 OP(4); OP(5); OP(6); OP(7);
358 1 OP(8); OP(9); OP(10); OP(11);
359 1 OP(12); OP(13); OP(14); OP(15);
360 #undef OP
361 1 }
362
363 void
364 1 m4::operator-=(const m4& rhs)
365 {
366 #define OP(i) data[i] -= rhs.data[i]
367 1 OP(0); OP(1); OP(2); OP(3);
368 1 OP(4); OP(5); OP(6); OP(7);
369 1 OP(8); OP(9); OP(10); OP(11);
370 1 OP(12); OP(13); OP(14); OP(15);
371 #undef OP
372 1 }
373
374 [[nodiscard]]
375 m4
376 1 m4::create_ortho_lrud(float l, float r, float t, float b, float n, float f)
377 {
378 // http://www.songho.ca/opengl/gl_projectionmatrix.html
379 return from_row_major
380 1 (
381 1 2 / (r - l), 0, 0, -(r + l) / (r - l),
382 1 0, 2 / (t - b), 0, -(t + b) / (t - b),
383 1 0, 0, -2 / (f - n), -(f + n) / (f - n),
384 0, 0, 0, 1
385 1 );
386 }
387
388 [[nodiscard]]
389 m4
390 1 m4::create_perspective(const An& fov, float a, float near, float far)
391 {
392
2/4
✓ Branch 0 (2 → 3) taken 1 times.
✗ Branch 1 (2 → 7) not taken.
✓ Branch 2 (3 → 4) taken 1 times.
✗ Branch 3 (3 → 7) not taken.
1 const float t = 1 / tan(fov / 2);
393 1 const float zm = far - near;
394 1 const float zp = far + near;
395 return from_row_major
396 1 (
397 t / a, 0, 0, 0,
398 0, t, 0, 0,
399 1 0, 0, -zp / zm, (-2 * far * near) / zm,
400 0, 0, -1, 0
401 1 );
402 }
403
404 m4
405 4 m4::get_translated(const v3& t) const
406 {
407
2/4
✓ Branch 0 (2 → 3) taken 4 times.
✗ Branch 1 (2 → 7) not taken.
✓ Branch 2 (3 → 4) taken 4 times.
✗ Branch 3 (3 → 7) not taken.
4 return *this * from_translation(t);
408 }
409
410 m4
411 4 m4::get_rotated(const AA& aa) const
412 {
413
2/4
✓ Branch 0 (2 → 3) taken 4 times.
✗ Branch 1 (2 → 7) not taken.
✓ Branch 2 (3 → 4) taken 4 times.
✗ Branch 3 (3 → 7) not taken.
4 return *this * from(aa);
414 }
415
416 const float*
417 1 m4::get_column_major_data_ptr() const
418 {
419 1 return data;
420 }
421
422 float*
423 1 m4::get_column_major_data_ptr()
424 {
425 1 return data;
426 }
427
428
429 float
430 1281 m4::get(int row, int col) const
431 {
432 1281 return data[col * 4 + row];
433 }
434
435 v4
436 182 m4::get_column(int col) const
437 {
438 182 const auto base = col * 4;
439 return
440 {
441 182 data[base + 0],
442 182 data[base + 1],
443 182 data[base + 2],
444 182 data[base + 3]
445
1/2
✓ Branch 0 (2 → 3) taken 182 times.
✗ Branch 1 (2 → 6) not taken.
182 };
446 }
447
448 v4
449 244 m4::get_row(int r) const
450 {
451
1/2
✓ Branch 0 (6 → 7) taken 244 times.
✗ Branch 1 (6 → 10) not taken.
244 return {get(r, 0), get(r, 1), get(r, 2), get(r, 3)};
452 }
453
454
455 2 std::string string_from(const m4& m)
456 {
457 16 const auto s = [](const v4& v) { return fmt::format("{} {} {} {}", v.x, v.y, v.z, v.w); };
458
8/16
✓ Branch 0 (2 → 3) taken 2 times.
✗ Branch 1 (2 → 34) not taken.
✓ Branch 2 (3 → 4) taken 2 times.
✗ Branch 3 (3 → 34) not taken.
✓ Branch 4 (4 → 5) taken 2 times.
✗ Branch 5 (4 → 30) not taken.
✓ Branch 6 (5 → 6) taken 2 times.
✗ Branch 7 (5 → 30) not taken.
✓ Branch 8 (6 → 7) taken 2 times.
✗ Branch 9 (6 → 26) not taken.
✓ Branch 10 (7 → 8) taken 2 times.
✗ Branch 11 (7 → 26) not taken.
✓ Branch 12 (8 → 9) taken 2 times.
✗ Branch 13 (8 → 22) not taken.
✓ Branch 14 (9 → 10) taken 2 times.
✗ Branch 15 (9 → 22) not taken.
4 return fmt::format("{}\n{}\n{}\n{}", s(m.get_row(0)), s(m.get_row(1)), s(m.get_row(2)), s(m.get_row(3)));
459 }
460
461
462 m4
463 1 operator+(const m4& lhs, const m4& rhs)
464 {
465 1 m4 t = lhs;
466 1 t += rhs;
467 1 return t;
468 }
469
470
471 m4
472 1 operator-(const m4& lhs, const m4& rhs)
473 {
474 1 m4 t = lhs;
475 1 t -= rhs;
476 1 return t;
477 }
478
479 float
480 232 get_component_multiply_sum(const v4& lhs, const v4& rhs)
481 {
482 232 const auto x = lhs.x * rhs.x;
483 232 const auto y = lhs.y * rhs.y;
484 232 const auto z = lhs.z * rhs.z;
485 232 const auto w = lhs.w* rhs.w;
486 232 return x + y + z + w;
487 }
488
489 10 m4 operator*(const m4& lhs, const m4& rhs)
490 {
491 160 const auto op = [&lhs, &rhs](int r, int c) -> float
492 {
493
2/4
✓ Branch 0 (2 → 3) taken 160 times.
✗ Branch 1 (2 → 8) not taken.
✓ Branch 2 (3 → 4) taken 160 times.
✗ Branch 3 (3 → 7) not taken.
160 return get_component_multiply_sum(lhs.get_row(r), rhs.get_column(c));
494 10 };
495 return m4::from_row_major
496
17/34
✓ Branch 0 (2 → 3) taken 10 times.
✗ Branch 1 (2 → 22) not taken.
✓ Branch 2 (3 → 4) taken 10 times.
✗ Branch 3 (3 → 22) not taken.
✓ Branch 4 (4 → 5) taken 10 times.
✗ Branch 5 (4 → 22) not taken.
✓ Branch 6 (5 → 6) taken 10 times.
✗ Branch 7 (5 → 22) not taken.
✓ Branch 8 (6 → 7) taken 10 times.
✗ Branch 9 (6 → 22) not taken.
✓ Branch 10 (7 → 8) taken 10 times.
✗ Branch 11 (7 → 22) not taken.
✓ Branch 12 (8 → 9) taken 10 times.
✗ Branch 13 (8 → 22) not taken.
✓ Branch 14 (9 → 10) taken 10 times.
✗ Branch 15 (9 → 22) not taken.
✓ Branch 16 (10 → 11) taken 10 times.
✗ Branch 17 (10 → 22) not taken.
✓ Branch 18 (11 → 12) taken 10 times.
✗ Branch 19 (11 → 22) not taken.
✓ Branch 20 (12 → 13) taken 10 times.
✗ Branch 21 (12 → 22) not taken.
✓ Branch 22 (13 → 14) taken 10 times.
✗ Branch 23 (13 → 22) not taken.
✓ Branch 24 (14 → 15) taken 10 times.
✗ Branch 25 (14 → 22) not taken.
✓ Branch 26 (15 → 16) taken 10 times.
✗ Branch 27 (15 → 22) not taken.
✓ Branch 28 (16 → 17) taken 10 times.
✗ Branch 29 (16 → 22) not taken.
✓ Branch 30 (17 → 18) taken 10 times.
✗ Branch 31 (17 → 22) not taken.
✓ Branch 32 (18 → 19) taken 10 times.
✗ Branch 33 (18 → 22) not taken.
10 (
497 op(0, 0), op(0, 1), op(0, 2), op(0, 3),
498 op(1, 0), op(1, 1), op(1, 2), op(1, 3),
499 op(2, 0), op(2, 1), op(2, 2), op(2, 3),
500 op(3, 0), op(3, 1), op(3, 2), op(3, 3)
501 20 );
502 }
503
504
505 18 v4 operator*(const m4& lhs, const v4& rhs)
506 {
507 72 const auto op = [&lhs, &rhs](int r) -> float
508 {
509
1/2
✓ Branch 0 (2 → 3) taken 72 times.
✗ Branch 1 (2 → 6) not taken.
72 return get_component_multiply_sum(lhs.get_row(r), rhs);
510 18 };
511
512
5/10
✓ Branch 0 (2 → 3) taken 18 times.
✗ Branch 1 (2 → 10) not taken.
✓ Branch 2 (3 → 4) taken 18 times.
✗ Branch 3 (3 → 10) not taken.
✓ Branch 4 (4 → 5) taken 18 times.
✗ Branch 5 (4 → 10) not taken.
✓ Branch 6 (5 → 6) taken 18 times.
✗ Branch 7 (5 → 10) not taken.
✓ Branch 8 (6 → 7) taken 18 times.
✗ Branch 9 (6 → 10) not taken.
18 return {op(0), op(1), op(2), op(3)};
513 }
514
515
2/4
✓ Branch 0 (2 → 3) taken 1 times.
✗ Branch 1 (2 → 10) not taken.
✓ Branch 2 (3 → 4) taken 1 times.
✗ Branch 3 (3 → 8) not taken.
1 ADD_CATCH_FORMATTER_IMPL(m4)
516 }
517