Skip to main content

mat4.ixx File

4x4 matrix type and utilities. More...

Included Headers

#include <cassert> #include <functional> #include <cstddef> #include <cmath> #include <helios.math.concepts> #include <helios.math.types:vec4> #include <helios.math.utils> #include <helios.math.TransformType>

Namespaces Index

namespacehelios
namespacemath

Classes Index

structmat4<T>

Represents a 4x4 matrix, stored in column-major order. More...

Description

4x4 matrix type and utilities.

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <cassert>
8#include <functional>
9#include <cstddef>
10#include <cmath>
11
12export module helios.math.types:mat4;
13
14import helios.math.TransformType;
15import :vec3;
16import :vec4;
17
18import helios.math.utils;
19import helios.math.concepts;
20
21
22export namespace helios::math {
23
24
25
37 template<helios::math::concepts::IsNumeric T>
38 struct mat4 {
39 private:
46 T m[16];
47
48 public:
52 explicit constexpr mat4() noexcept : m{} {};
53
60 explicit constexpr mat4(const T f) noexcept
61 : m{ f, T{}, T{}, T{},
62 T{}, f, T{}, T{},
63 T{}, T{}, f, T{},
64 T{}, T{}, T{}, f} {}
65
72 explicit constexpr mat4(const vec3<T> f) noexcept
73 : m{ f[0], T{}, T{}, T{},
74 T{}, f[1], T{}, T{},
75 T{}, T{}, f[2], T{},
76 T{}, T{}, T{}, static_cast<T>(1)} {}
77
86 constexpr mat4(
87 const T f0_0, const T f1_0, const T f2_0, const T f3_0,
88 const T f0_1, const T f1_1, const T f2_1, const T f3_1,
89 const T f0_2, const T f1_2, const T f2_2, const T f3_2,
90 const T f0_3, const T f1_3, const T f2_3, const T f3_3
91 ) : m{
92 f0_0, f1_0, f2_0, f3_0,
93 f0_1, f1_1, f2_1, f3_1,
94 f0_2, f1_2, f2_2, f3_2,
95 f0_3, f1_3, f2_3, f3_3
96 } { }
97
98
106 static mat4<T> identity() noexcept {
107 return mat4<T>(1);
108 }
109
110
132 constexpr const T& operator()(const size_t row, const size_t col) const {
133 assert(row < 4 && col < 4 && "mat4 - Index out of bounds.");
134 return m[row + col * 4];
135 }
136
137
159 constexpr T& operator()(const size_t row, const size_t col) {
160 assert(row < 4 && col < 4 && "mat4 - Index out of bounds.");
161 return m[row + col * 4];
162 }
163
164
180 constexpr bool same(const mat4<T>& rgt) const {
181
182 static const T eps = static_cast<T>(helios::math::EPSILON_LENGTH);
183
184 const auto* leftPtr = value_ptr(*this);
185 const auto* rgtPtr = value_ptr(rgt);
186
187 for (int i = 0; i < 16; i++) {
188 if (std::fabs(leftPtr[i] - rgtPtr[i]) > eps) {
189 return false;
190 }
191 }
192
193 return true;
194 }
195
196
205 constexpr bool operator==(const mat4<T>& rgt) const {
206
207 const auto* leftPtr = value_ptr(*this);
208 const auto* rgtPtr = value_ptr(rgt);
209
210 for (int i = 0; i < 16; i++) {
211 if (leftPtr[i] != rgtPtr[i]) {
212 return false;
213 }
214 }
215
216 return true;
217 }
218
219
228 constexpr mat4<T> operator*(const mat4<T>& m) const {
229 mat4<T> A{};
230 for (int row = 0; row < 4; row++) {
231 for (int col = 0; col < 4; col++) {
232 T sum = T{};
233 sum += (*this)(row, 0) * m(0, col);
234 sum += (*this)(row, 1) * m(1, col);
235 sum += (*this)(row, 2) * m(2, col);
236 sum += (*this)(row, 3) * m(3, col);
237 A(row, col) = sum;
238 }
239 }
240
241 return A;
242 }
243
244
254 constexpr vec4<T> operator*(const vec4<T>& v) const {
255 const auto m = *this;
256 return vec4<T>{
257 m(0, 0) * v[0] + m(0, 1) * v[1] + m(0, 2) * v[2] + m(0, 3) * v[3],
258 m(1, 0) * v[0] + m(1, 1) * v[1] + m(1, 2) * v[2] + m(1, 3) * v[3],
259 m(2, 0) * v[0] + m(2, 1) * v[1] + m(2, 2) * v[2] + m(2, 3) * v[3],
260 m(3, 0) * v[0] + m(3, 1) * v[1] + m(3, 2) * v[2] + m(3, 3) * v[3]
261 };
262 }
263
264
272 constexpr mat4<T> operator*(const T v) const {
273 const auto m = *this;
274 return mat4<T>{
275 m(0, 0) * v, m(0, 1) * v, m(0, 2) * v, m(0, 3) * v,
276 m(1, 0) * v, m(1, 1) * v, m(1, 2) * v, m(1, 3) * v,
277 m(2, 0) * v, m(2, 1) * v, m(2, 2) * v, m(2, 3) * v,
278 m(3, 0) * v, m(3, 1) * v, m(3, 2) * v, m(3, 3) * v
279 };
280 }
281
295 const auto m = *this;
297 m(0, 0), m(0, 1), m(0, 2), m(0, 3),
298 m(1, 0), m(1, 1), m(1, 2), m(1, 3),
299 m(2, 0), m(2, 1), m(2, 2), m(2, 3),
300 m(3, 0), m(3, 1), m(3, 2), m(3, 3)
301 };
302 }
303
310 helios::math::vec4<T> column(unsigned int i) const noexcept {
311 assert(i <= 3 && "unexpected value for column");
312 const auto m = *this;
314 m(0, i), m(1, i), m(2, i), m(3, i)
315 };
316 }
317
325 constexpr helios::math::mat4<T> inverse() const noexcept {
326 const auto m = *this;
327
328 const auto a = column(0).toVec3();
329 const auto b = column(1).toVec3();
330 const auto c = column(2).toVec3();
331 const auto d = column(3).toVec3();
332
333 const T x = m(3, 0);
334 const T y = m(3, 1);
335 const T z = m(3, 2);
336 const T w = m(3, 3);
337
338 auto s = helios::math::cross(a, b);
339 auto t = helios::math::cross(c, d);
340 auto u = a*y - b*x;
341 auto v = c*w - d*z;
342
343 T invDet = static_cast<T>(1) / (helios::math::dot(s, v) + helios::math::dot(t, u));
344
345 s = s * invDet;
346 t = t * invDet;
347 u = u * invDet;
348 v = v * invDet;
349
350 auto r0 = (helios::math::cross(b, v)) + t*y;
351 auto r1 = (helios::math::cross(v, a)) - t*x;
352 auto r2 = (helios::math::cross(d, u)) + s*w;
353 auto r3 = (helios::math::cross(u, c)) - s*z;
354
356 r0[0], r0[1], r0[2], -helios::math::dot(b, t),
357 r1[0], r1[1], r1[2], helios::math::dot(a, t),
358 r2[0], r2[1], r2[2], -helios::math::dot(d, s),
359 r3[0], r3[1], r3[2], helios::math::dot(c, s)
360 };
361 }
362
372 const auto m = *this;
374 m(0, 3), m(1, 3), m(2, 3)
375 };
376 }
377
389 const auto m = *this;
391 m(0, 0), m(1, 0), m(2, 0), m(3, 0),
392 m(0, 1), m(1, 1), m(2, 1), m(3, 1),
393 m(0, 2), m(1, 2), m(2, 2), m(3, 2),
394 v[0], v[1], v[2], static_cast<T>(1)
395 };
396 }
397
410 const auto m = *this;
412 m(0, 0) * v[0], m(1, 0) * v[0], m(2, 0) * v[0], m(3, 0) * v[0],
413 m(0, 1) * v[1], m(1, 1) * v[1], m(2, 1) * v[1], m(3, 1) * v[1],
414 m(0, 2) * v[2], m(1, 2) * v[2], m(2, 2) * v[2], m(3, 2) * v[2],
415 m(0, 3), m(1, 3), m(2, 3), m(3, 3),
416 };
417 }
418
419
431 const auto m = *this;
433 m(0, 0), m(1, 0), m(2, 0), m(3, 0),
434 m(0, 1), m(1, 1), m(2, 1), m(3, 1),
435 m(0, 2), m(1, 2), m(2, 2), m(3, 2),
436 v[0], v[1], v[2], static_cast<T>(1)
437 };
438 }
439
467 const auto m = *this;
469 return m;
470 }
471
472 auto id = identity();
474 id(0, 3) = m(0, 3);
475 id(1, 3) = m(1, 3);
476 id(2, 3) = m(2, 3);
477 }
478
481 id(0, 0) = m(0, 0); id(0, 1) = m(0, 1); id(0, 2) = m(0, 2);
482 id(1, 0) = m(1, 0); id(1, 1) = m(1, 1); id(1, 2) = m(1, 2);
483 id(2, 0) = m(2, 0); id(2, 1) = m(2, 1); id(2, 2) = m(2, 2);
484 } else {
485
486 const auto bx = vec3<T>(m(0, 0), m(1, 0), m(2, 0));
487 const auto by = vec3<T>(m(0, 1), m(1, 1), m(2, 1));
488 const auto bz = vec3<T>(m(0, 2), m(1, 2), m(2, 2));
489
490 const auto sx = bx.length();
491 const auto sy = by.length();
492 const auto sz = bz.length();
493
495 vec3<T> rx = sx != 0 ? bx/sx : vec3<T>{1, 0, 0};
496 vec3<T> ry = sy != 0 ? by/sy : vec3<T>{0, 1, 0};
497 vec3<T> rz = sz != 0 ? bz/sz : vec3<T>{0, 0, 1};
498
499 id(0, 0) = rx[0]; id(0, 1) = ry[0]; id(0, 2) = rz[0];
500 id(1, 0) = rx[1]; id(1, 1) = ry[1]; id(1, 2) = rz[1];
501 id(2, 0) = rx[2]; id(2, 1) = ry[2]; id(2, 2) = rz[2];
503 id(0, 0) = sx;
504 id(1, 1) = sy;
505 id(2, 2) = sz;
506 }
507 }
508
509 return id;
510 }
511
512 };
513
514
526 template<helios::math::concepts::IsNumeric T>
527 const T* value_ptr(const mat4<T>& m) noexcept {
528 return &m(0, 0);
529 }
530
531
543 template<helios::math::concepts::IsNumeric T>
544 T* value_ptr(mat4<T>& m) noexcept {
545 return &m(0, 0);
546 }
547
552
557
562
563} // namespace helios::math

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.