GCC Code Coverage Report


./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
229 of 239, 0 excluded
95.8%
Functions:
42 of 44, 0 excluded
95.5%
Branches:
62 of 130, 0 excluded
47.7%

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