HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
mat.hpp
1// Copyright 2020 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/vec.hpp"
7#include "TTauri/Foundation/aarect.hpp"
8#include "TTauri/Foundation/rect.hpp"
9#include <fmt/format.h>
10#include <fmt/ostream.h>
11#include <ostream>
12
13namespace tt {
14
18class mat {
19 vec col0;
20 vec col1;
21 vec col2;
22 vec col3;
23
24public:
27 tt_force_inline mat() noexcept {}
28 tt_force_inline mat(mat const &rhs) noexcept = default;
29 tt_force_inline mat &operator=(mat const &rhs) noexcept = default;
30 tt_force_inline mat(mat &&rhs) noexcept = default;
31 tt_force_inline mat &operator=(mat &&rhs) noexcept = default;
32
35 tt_force_inline mat(vec col0, vec col1, vec col2, vec col3=vec{0.0f, 0.0f, 0.0f, 1.0f}) noexcept :
36 col0(col0), col1(col1), col2(col2), col3(col3) {}
37
43 tt_force_inline mat(
44 float i00, float i10, float i20, float i30,
45 float i01, float i11, float i21, float i31,
46 float i02, float i12, float i22, float i32,
47 float i03, float i13, float i23, float i33
48 ) :
49 col0(i00, i01, i02, i03),
50 col1(i10, i11, i12, i13),
51 col2(i20, i21, i22, i23),
52 col3(i30, i31, i32, i33) {}
53
56 struct S {
57 vec s;
58
59 explicit S(vec rhs) noexcept :
60 s(rhs)
61 {
62 tt_assume(rhs.is_point());
63 }
64
65 S(float x, float y, float z=1.0f) noexcept :
66 s(x, y, z, 1.0f) {}
67
70 static S uniform2D(vec haystack, vec needle) noexcept {
71 tt_assume(haystack.x() != 0.0f && haystack.y() != 0.0f);
72 tt_assume(needle.x() != 0.0f && needle.y() != 0.0f);
73
74 ttlet non_uniform_scale = haystack.xyxy() / needle.xyxy();
75 ttlet uniform_scale = std::min(non_uniform_scale.x(), non_uniform_scale.y());
76 return S{vec{uniform_scale, uniform_scale, 1.0f, 1.0f}};
77 }
78
81 operator mat () const noexcept {
82 tt_assume(s.is_point());
83 return { s.x000(), s._0y00(), s._00z0(), s._000w() };
84 }
85
86 [[nodiscard]] friend S operator*(S const &lhs, S const &rhs) noexcept {
87 return S{lhs.s * rhs.s};
88 }
89
90 [[nodiscard]] friend vec operator*(S const &lhs, vec const &rhs) noexcept {
91 return vec{lhs.s * rhs};
92 }
93
97 [[nodiscard]] tt_force_inline friend aarect operator*(S const &lhs, aarect const &rhs) noexcept {
98 return aarect::p0p3(lhs.s * rhs.p0(), lhs.s * rhs.p3());
99 }
100
101 [[nodiscard]] friend rect operator*(S const &lhs, rect const &rhs) noexcept {
102 return rect{
103 lhs.s * rhs.corner<0>(),
104 lhs.s * rhs.corner<1>(),
105 lhs.s * rhs.corner<2>(),
106 lhs.s * rhs.corner<3>()
107 };
108 }
109
112 [[nodiscard]] friend S operator~(S const &rhs) noexcept {
113 return S{reciprocal(rhs.s)};
114 }
115 };
116
119 struct T {
120 vec t;
121
122 T() noexcept : t() {}
123 T(T const &rhs) noexcept = default;
124 T(T &&rhs) noexcept = default;
125 T &operator=(T const &rhs) noexcept = default;
126 T &operator=(T &&rhs) noexcept = default;
127
128 explicit T(vec rhs) noexcept :
129 t(rhs) { tt_assume(rhs.is_vector()); }
130
131 T(float x, float y, float z=0.0f) noexcept :
132 t(x, y, z) {}
133
134 operator mat () const noexcept {
135 tt_assume(t.is_vector());
136 return { t._1000(), t._0100(), t._0010(), t.xyz1() };
137 }
138
139 [[nodiscard]] friend T operator*(T const &lhs, T const &rhs) noexcept {
140 return T{lhs.t + rhs.t};
141 }
142
143 [[nodiscard]] friend mat operator*(T const &lhs, mat::S const &rhs) noexcept {
144 return { rhs.s.x000(), rhs.s._0y00(), rhs.s._00z0(), lhs.t.xyz1() };
145 }
146
147 [[nodiscard]] friend mat operator*(mat::S const &lhs, T const &rhs) noexcept {
148 return { lhs.s.x000(), lhs.s._0y00(), lhs.s._00z0(), lhs.s * rhs.t.xyz1() };
149 }
150
151 [[nodiscard]] friend vec operator*(T const &lhs, vec const &rhs) noexcept {
152 return vec{lhs.t + rhs};
153 }
154
157 [[nodiscard]] tt_force_inline friend rect operator*(T const &lhs, aarect const &rhs) noexcept {
158 return rect{
159 lhs.t + rhs.corner<0>(),
160 lhs.t + rhs.corner<1>(),
161 lhs.t + rhs.corner<2>(),
162 lhs.t + rhs.corner<3>()
163 };
164 }
165
166 [[nodiscard]] friend rect operator*(T const &lhs, rect const &rhs) noexcept {
167 return rect{
168 lhs.t + rhs.corner<0>(),
169 lhs.t + rhs.corner<1>(),
170 lhs.t + rhs.corner<2>(),
171 lhs.t + rhs.corner<3>()
172 };
173 }
174
177 [[nodiscard]] friend T operator~(T const &rhs) noexcept {
178 return T{-rhs.t};
179 }
180 };
181
184 struct T2 {
185 vec t;
186
187 T2() noexcept : t() {}
188
189 explicit T2(vec rhs) noexcept : t(rhs) {
190 tt_assume(rhs.is_vector());
191 tt_assume(rhs.z() == 0.0f);
192 }
193
194 T2(float x, float y) noexcept :
195 t(x, y, 0.0f) {}
196
197 operator mat::T () const noexcept {
198 return mat::T{t};
199 }
200
201 operator mat () const noexcept {
202 tt_assume(t.is_vector());
203 return { t._1000(), t._0100(), t._0010(), t.xyz1() };
204 }
205
206 [[nodiscard]] friend T2 operator*(T2 const &lhs, T2 const &rhs) noexcept {
207 return T2{lhs.t + rhs.t};
208 }
209
210 [[nodiscard]] friend mat::T operator*(mat::T const &lhs, T2 const &rhs) noexcept {
211 return mat::T{lhs.t + rhs.t};
212 }
213
214 [[nodiscard]] friend mat::T operator*(T2 const &lhs, mat::T const &rhs) noexcept {
215 return mat::T{lhs.t + rhs.t};
216 }
217
218 [[nodiscard]] friend mat operator*(T2 const &lhs, mat::S const &rhs) noexcept {
219 return { rhs.s.x000(), rhs.s._0y00(), rhs.s._00z0(), lhs.t.xyz1() };
220 }
221
222 [[nodiscard]] friend mat operator*(mat::S const &lhs, T2 const &rhs) noexcept {
223 return { lhs.s.x000(), lhs.s._0y00(), lhs.s._00z0(), lhs.s * rhs.t.xyz1() };
224 }
225
226 [[nodiscard]] friend vec operator*(T2 const &lhs, vec const &rhs) noexcept {
227 return vec{lhs.t + rhs};
228 }
229
230 [[nodiscard]] friend aarect operator*(T2 const &lhs, aarect const &rhs) noexcept {
231 return aarect::p0p3(lhs.t + rhs.p0(), lhs.t + rhs.p3());
232 }
233
234 [[nodiscard]] friend rect operator*(T2 const &lhs, rect const &rhs) noexcept {
235 return rect{
236 lhs.t + rhs.corner<0>(),
237 lhs.t + rhs.corner<1>(),
238 lhs.t + rhs.corner<2>(),
239 lhs.t + rhs.corner<3>()
240 };
241 }
242
245 [[nodiscard]] friend T2 operator~(T2 const &rhs) noexcept {
246 return T2{-rhs.t};
247 }
248 };
249
250
251
252 constexpr size_t size() noexcept { return 4; }
253
254 template<size_t I>
255 [[nodiscard]] tt_force_inline vec &get() noexcept {
256 static_assert(I <= 3);
257 if constexpr (I == 0) {
258 return col0;
259 } else if constexpr (I == 1) {
260 return col1;
261 } else if constexpr (I == 2) {
262 return col2;
263 } else {
264 return col3;
265 }
266 }
267
268 template<size_t I>
269 [[nodiscard]] tt_force_inline vec get() const noexcept {
270 static_assert(I <= 3);
271 if constexpr (I == 0) {
272 return col0;
273 } else if constexpr (I == 1) {
274 return col1;
275 } else if constexpr (I == 2) {
276 return col2;
277 } else {
278 return col3;
279 }
280 }
281
284 [[nodiscard]] bool is_z_rot90() const noexcept {
285 ttlet xyxy = col0.xy00() + col1._00xy();
286 ttlet result = eq(xyxy, vec{});
287 return (result == 0b1001) || (result == 0b0110);
288 }
289
293 [[nodiscard]] tt_force_inline friend vec operator*(mat const &lhs, vec const &rhs) noexcept {
294 return
295 (lhs.col0 * rhs.xxxx() + lhs.col1 * rhs.yyyy()) +
296 (lhs.col2 * rhs.zzzz() + lhs.col3 * rhs.wwww());
297 }
298
301 [[nodiscard]] tt_force_inline friend rect operator*(mat const &lhs, aarect const &rhs) noexcept {
302 return rect{
303 lhs * rhs.corner<0>(),
304 lhs * rhs.corner<1>(),
305 lhs * rhs.corner<2>(),
306 lhs * rhs.corner<3>()
307 };
308 }
309
312 [[nodiscard]] tt_force_inline friend rect operator*(mat const &lhs, rect const &rhs) noexcept {
313 return rect{
314 lhs * rhs.corner<0>(),
315 lhs * rhs.corner<1>(),
316 lhs * rhs.corner<2>(),
317 lhs * rhs.corner<3>()
318 };
319 }
320
323 [[nodiscard]] friend mat operator*(mat const &lhs, mat const &rhs) noexcept {
324 return {lhs * rhs.col0, lhs * rhs.col1, lhs * rhs.col2, lhs * rhs.col3};
325 }
326
329 [[nodiscard]] friend mat operator*(S const &lhs, mat const &rhs) noexcept {
330 return {lhs.s * rhs.col0, lhs.s * rhs.col1, lhs.s * rhs.col2, lhs.s * rhs.col3};
331 }
332
335 [[nodiscard]] friend mat operator*(T const &lhs, mat const &rhs) noexcept {
336 return {rhs.col0, rhs.col1, rhs.col2, lhs.t + rhs.col3};
337 }
338
341 [[nodiscard]] friend mat transpose(mat rhs) noexcept {
342 auto tmp = transpose(rhs.col0, rhs.col1, rhs.col2, rhs.col3);
343 return {std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
344 }
345
348 [[nodiscard]] friend mat operator~(mat const &rhs) {
349 // rc
350 //var s0 : Number = i00 * i11 -
351 // i10 * i01;
352 //var c0 : Number = i20 * i31 -
353 // i30 * i21;
354 ttlet s0c0 = rhs.col0 * rhs.col1.yxwz();
355
356 //var s1 : Number = i00 * i12 -
357 // i10 * i02;
358 //var c1 : Number = i20 * i32 -
359 // i30 * i22;
360 ttlet s1c1 = rhs.col0 * rhs.col2.yxwz();
361 ttlet s0c0s1c1 = hsub(s0c0, s1c1);
362
363 //var s2 : Number = i00 * i13 -
364 // i10 * i03;
365 //var c2 : Number = i20 * i33 -
366 // i30 * i23;
367 ttlet s2c2 = rhs.col0 * rhs.col3.yxwz();
368
369 //var s3 : Number = i01 * i12 -
370 // i11 * i02;
371 //var c3 : Number = i21 * i32 -
372 // i31 * i22;
373 ttlet s3c3 = rhs.col1 * rhs.col2.yxwz();
374 ttlet s2c2s3c3 = hsub(s2c2, s3c3);
375
376 //var s4 : Number = i01 * i13 -
377 // i11 * i03;
378 //var c4 : Number = i21 * i33 -
379 // i31 * i23;
380 ttlet s4c4 = rhs.col1 * rhs.col3.yxwz();
381
382 //var s5 : Number = i02 * i13 -
383 // i12 * i03;
384 //var c5 : Number = i22 * i33 -
385 // i32 * i23;
386 ttlet s5c5 = rhs.col2 * rhs.col3.yxwz();
387 ttlet s4c4s5c5 = hsub(s4c4, s5c5);
388
389 // det = (s0 * c5 +
390 // -s1 * c4 +
391 // s2 * c3 +
392 // s3 * c2 +
393 // -s4 * c1 +
394 // s5 * c0)
395 ttlet s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
396 ttlet s45__ = s4c4s5c5.xz00();
397
398 ttlet c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
399 ttlet c10__ = s0c0s1c1.wy00();
400
401 ttlet det_prod_half0 = neg<0,1,0,0>(s0123 * c5432);
402 ttlet det_prod_half1 = neg<1,0,0,0>(s45__ * c10__);
403
404 ttlet det_sum0 = hadd(det_prod_half0, det_prod_half1);
405 ttlet det_sum1 = hadd(det_sum0, det_sum0);
406 ttlet det = hadd(det_sum1, det_sum1).xxxx();
407
408 if (det.x() == 0.0f) {
409 TTAURI_THROW(math_error("Divide by zero"));
410 }
411
412 ttlet invdet = reciprocal(det);
413
414 ttlet t = transpose(rhs);
415
416 // rc rc rc rc
417 //m.i00 = (i11 * c5 + i12 * -c4 + i13 * c3) * invdet;
418 //m.i10 = (i10 * -c5 + i12 * c2 + i13 * -c1) * invdet;
419 //m.i20 = (i10 * c4 + i11 * -c2 + i13 * c0) * invdet;
420 //m.i30 = (i10 * -c3 + i11 * c1 + i12 * -c0) * invdet;
421 auto tmp_c5543 = neg<0,1,0,1>(c5432.xxyz());
422 auto tmp_c4221 = neg<1,0,1,0>(c5432.yww0() + c10__._000x());
423 auto tmp_c3100 = neg<0,1,0,1>(c5432.z000() + c10__._0xyy());
424 ttlet inv_col0 = (
425 (t.col1.yxxx() * tmp_c5543) +
426 (t.col1.zzyy() * tmp_c4221) +
427 (t.col1.wwwz() * tmp_c3100)
428 ) * invdet;
429
430 //m.i01 = (i01 * -c5 + i02 * c4 + i03 * -c3) * invdet;
431 //m.i11 = (i00 * c5 + i02 * -c2 + i03 * c1) * invdet;
432 //m.i21 = (i00 * -c4 + i01 * c2 + i03 * -c0) * invdet;
433 //m.i31 = (i00 * c3 + i01 * -c1 + i02 * c0) * invdet;
434 tmp_c5543 = -tmp_c5543;
435 tmp_c4221 = -tmp_c4221;
436 tmp_c3100 = -tmp_c3100;
437 ttlet inv_col1 = (
438 (t.col0.yxxx() * tmp_c5543) +
439 (t.col0.zzyy() * tmp_c4221) +
440 (t.col0.wwwz() * tmp_c3100)
441 ) * invdet;
442
443 //m.i02 = (i31 * s5 + i32 * -s4 + i33 * s3) * invdet;
444 //m.i12 = (i30 * -s5 + i32 * s2 + i33 * -s1) * invdet;
445 //m.i22 = (i30 * s4 + i31 * -s2 + i33 * s0) * invdet;
446 //m.i32 = (i30 * -s3 + i31 * s1 + i32 * -s0) * invdet;
447 auto tmp_s5543 = neg<0,1,0,1>(s45__.yyx0() + s0123._000w());
448 auto tmp_s4221 = neg<1,0,1,0>(s45__.x000() + s0123._0zzy());
449 auto tmp_s3100 = neg<0,1,0,1>(s0123.wyxx());
450 ttlet inv_col2 = (
451 (t.col3.yxxx() * tmp_s5543) +
452 (t.col3.zzyy() * tmp_s4221) +
453 (t.col3.wwwz() * tmp_s3100)
454 ) * invdet;
455
456 //m.i03 = (i21 * -s5 + i22 * s4 + i23 * -s3) * invdet;
457 //m.i13 = (i20 * s5 + i22 * -s2 + i23 * s1) * invdet;
458 //m.i23 = (i20 * -s4 + i21 * s2 + i23 * -s0) * invdet;
459 //m.i33 = (i20 * s3 + i21 * -s1 + i22 * s0) * invdet;
460 tmp_s5543 = -tmp_s5543;
461 tmp_s4221 = -tmp_s4221;
462 tmp_s3100 = -tmp_s3100;
463 ttlet inv_col3 = (
464 (t.col2.yxxx() * tmp_s5543) +
465 (t.col2.zzyy() * tmp_s4221) +
466 (t.col2.wwwz() * tmp_s3100)
467 ) * invdet;
468
469 return {inv_col0, inv_col1, inv_col2, inv_col3};
470 }
471
472 [[nodiscard]] friend bool operator==(mat const &lhs, mat const &rhs) noexcept {
473 return lhs.col0 == rhs.col0 && lhs.col1 == rhs.col1 && lhs.col2 == rhs.col2 && lhs.col3 == rhs.col3;
474 }
475
476 [[nodiscard]] friend bool operator!=(mat const &lhs, mat const &rhs) noexcept {
477 return !(lhs == rhs);
478 }
479
482 [[nodiscard]] static mat I() noexcept {
483 vec tmp;
484 return { tmp._1000(), tmp._0100(), tmp._0010(), tmp._0001() };
485 }
486
487 [[nodiscard]] static mat RGBtoXYZ(
488 float wx, float wy,
489 float rx, float ry,
490 float gx, float gy,
491 float bx, float by) noexcept
492 {
493 ttlet w = vec{wx, wy, 1.0f - wx - wy};
494 ttlet r = vec{rx, ry, 1.0f - rx - ry};
495 ttlet g = vec{gx, gy, 1.0f - gx - gy};
496 ttlet b = vec{bx, by, 1.0f - bx - by};
497
498 // Calculate whitepoint's tristimulus values from coordinates
499 ttlet W = vec{
500 1.0f * (w.x() / w.y()),
501 1.0f,
502 1.0f * (w.z() / w.y())
503 };
504
505 // C is the chromaticity matrix.
506 ttlet C = mat{r, g, b};
507
508 // solve tristimulus sums.
509 ttlet S = mat::S{vec::point(~C * W)};
510
511 return C * S;
512 }
513
521 [[nodiscard]] static mat shear(float _00, float _01, float _10, float _11) noexcept {
522 ttlet c0 = vec{_00, _10};
523 ttlet c1 = vec{_01, _11};
524 return { c0, c1, c0._0010(), c0._0001() };
525 }
526
531 template<int N=2, typename T, std::enable_if_t<std::is_arithmetic_v<T>,int> = 0>
532 [[nodiscard]] static mat R(T rhs) noexcept {
533 ttlet s = sin(numeric_cast<float>(rhs));
534 ttlet c = cos(numeric_cast<float>(rhs));
535 ttlet tmp = vec{c, s, -s};
536
537 if constexpr (N == 0) {
538 return { tmp._1000(), tmp._0xy0(), tmp._0zx0(), tmp._0001() };
539 } else if constexpr (N == 1) {
540 return { tmp.x0z0(), tmp._0100(), tmp.x0y0(), tmp._0001() };
541 } else {
542 return { tmp.xy00(), tmp.zx00(), tmp._0010(), tmp._0001() };
543 }
544 }
545
552 [[nodiscard]] static mat::T align(aarect haystack, aarect needle, Alignment alignment) noexcept {
553 return mat::T{
554 aarect::_align(haystack, needle, alignment).offset() -
555 needle.offset()
556 };
557 }
558
559 [[nodiscard]] static mat uniform2D_scale_and_translate(aarect haystack, aarect needle, Alignment alignment) noexcept {
560 ttlet scale = S::uniform2D(haystack.extent(), needle.extent());
561 ttlet scaled_needle = scale * needle;
562 ttlet translation = align(haystack, scaled_needle, alignment);
563 return translation * scale;
564 }
565
566 [[nodiscard]] friend std::string to_string(mat const &rhs) noexcept {
567 return fmt::format("[{}, {}, {}, {}]", rhs.col0, rhs.col1, rhs.col2, rhs.col3);
568 }
569
570 friend std::ostream &operator<<(std::ostream &lhs, mat const &rhs) noexcept {
571 return lhs << to_string(rhs);
572 }
573};
574
575
576template<typename M> struct is_mat : std::false_type {};
577template<> struct is_mat<mat> : std::true_type {};
578template<> struct is_mat<mat::T> : std::true_type {};
579template<> struct is_mat<mat::T2> : std::true_type {};
580template<> struct is_mat<mat::S> : std::true_type {};
581
582template<typename M>
583inline constexpr bool is_mat_v = is_mat<M>::value;
584
585}
Class which represents an axis-aligned rectangle.
Definition aarect.hpp:13
tt_force_inline vec offset() const noexcept
Get vector from origin to the bottom-left corner.
Definition aarect.hpp:177
static aarect _align(aarect outside, aarect inside, Alignment alignment) noexcept
Need to call the hiden friend function from within another class.
Definition aarect.hpp:265
static tt_force_inline aarect p0p3(vec const &v) noexcept
Create aarect from packed p0p3 coordinates.
Definition aarect.hpp:75
Definition exceptions.hpp:154
A 4x4 matrix.
Definition mat.hpp:18
tt_force_inline friend rect operator*(mat const &lhs, aarect const &rhs) noexcept
Matrix/aarect multiplication.
Definition mat.hpp:301
friend mat operator*(T const &lhs, mat const &rhs) noexcept
Translate/Matrix multiplication.
Definition mat.hpp:335
tt_force_inline mat(float i00, float i10, float i20, float i30, float i01, float i11, float i21, float i31, float i02, float i12, float i22, float i32, float i03, float i13, float i23, float i33)
Construct a matrix from the individual values.
Definition mat.hpp:43
friend mat operator*(mat const &lhs, mat const &rhs) noexcept
Matrix/Matrix multiplication.
Definition mat.hpp:323
static mat I() noexcept
Create an identity matrix.
Definition mat.hpp:482
friend mat operator~(mat const &rhs)
Invert matrix.
Definition mat.hpp:348
static mat shear(float _00, float _01, float _10, float _11) noexcept
Create a 2D shearing matrix.
Definition mat.hpp:521
static mat R(T rhs) noexcept
Create a rotation matrix.
Definition mat.hpp:532
tt_force_inline mat(vec col0, vec col1, vec col2, vec col3=vec{0.0f, 0.0f, 0.0f, 1.0f}) noexcept
Create a matrix for 4 vector-columns.
Definition mat.hpp:35
tt_force_inline mat() noexcept
Create an identity matrix.
Definition mat.hpp:27
bool is_z_rot90() const noexcept
Rotation around z axis is a multiple of 90 degree.
Definition mat.hpp:284
tt_force_inline friend vec operator*(mat const &lhs, vec const &rhs) noexcept
Matrix/Vector multiplication.
Definition mat.hpp:293
static mat::T align(aarect haystack, aarect needle, Alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition mat.hpp:552
tt_force_inline friend rect operator*(mat const &lhs, rect const &rhs) noexcept
Matrix/rect multiplication.
Definition mat.hpp:312
friend mat transpose(mat rhs) noexcept
Matrix transpose.
Definition mat.hpp:341
friend mat operator*(S const &lhs, mat const &rhs) noexcept
Scale/Matrix multiplication.
Definition mat.hpp:329
Optimized scale matrix.
Definition mat.hpp:56
tt_force_inline friend aarect operator*(S const &lhs, aarect const &rhs) noexcept
Matrix/Vector multiplication.
Definition mat.hpp:97
friend S operator~(S const &rhs) noexcept
Invert matrix.
Definition mat.hpp:112
static S uniform2D(vec haystack, vec needle) noexcept
Get a scaling matrix to uniformly scale a needle to fit in the haystack.
Definition mat.hpp:70
Optimized translate matrix.
Definition mat.hpp:119
tt_force_inline friend rect operator*(T const &lhs, aarect const &rhs) noexcept
Matrix/aarect multiplication.
Definition mat.hpp:157
friend T operator~(T const &rhs) noexcept
Invert matrix.
Definition mat.hpp:177
Optimized 2D translate matrix.
Definition mat.hpp:184
friend T2 operator~(T2 const &rhs) noexcept
Invert matrix.
Definition mat.hpp:245
Definition mat.hpp:576
Class which represents an axis-aligned rectangle.
Definition rect.hpp:15
tt_force_inline vec corner() const noexcept
Get coordinate of a corner.
Definition rect.hpp:84
A 4D vector.
Definition vec.hpp:37
static tt_force_inline vec point(float x=0.0f, float y=0.0f, float z=0.0f) noexcept
Create a point out of 2 to 4 values.
Definition vec.hpp:180
T min(T... args)