6#include "TTauri/Foundation/vec.hpp"
7#include "TTauri/Foundation/aarect.hpp"
8#include "TTauri/Foundation/rect.hpp"
10#include <fmt/ostream.h>
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;
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) {}
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
49 col0(i00, i01, i02, i03),
50 col1(i10, i11, i12, i13),
51 col2(i20, i21, i22, i23),
52 col3(i30, i31, i32, i33) {}
59 explicit S(
vec rhs) noexcept :
62 tt_assume(rhs.is_point());
65 S(
float x,
float y,
float z=1.0f) noexcept :
71 tt_assume(haystack.x() != 0.0f && haystack.y() != 0.0f);
72 tt_assume(needle.x() != 0.0f && needle.y() != 0.0f);
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}};
81 operator mat () const noexcept {
82 tt_assume(s.is_point());
83 return { s.x000(), s._0y00(), s._00z0(), s._000w() };
86 [[nodiscard]]
friend S operator*(
S const &lhs,
S const &rhs)
noexcept {
87 return S{lhs.s * rhs.s};
90 [[nodiscard]]
friend vec operator*(S
const &lhs, vec
const &rhs)
noexcept {
91 return vec{lhs.s * rhs};
101 [[nodiscard]]
friend rect operator*(
S const &lhs,
rect const &rhs)
noexcept {
103 lhs.s * rhs.corner<0>(),
104 lhs.s * rhs.corner<1>(),
105 lhs.s * rhs.corner<2>(),
106 lhs.s * rhs.corner<3>()
113 return S{reciprocal(rhs.s)};
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;
128 explicit T(
vec rhs) noexcept :
129 t(rhs) { tt_assume(rhs.is_vector()); }
131 T(
float x,
float y,
float z=0.0f) noexcept :
134 operator mat ()
const noexcept {
135 tt_assume(t.is_vector());
136 return { t._1000(), t._0100(), t._0010(), t.xyz1() };
139 [[nodiscard]]
friend T operator*(
T const &lhs,
T const &rhs)
noexcept {
140 return T{lhs.t + rhs.t};
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() };
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() };
151 [[nodiscard]]
friend vec operator*(
T const &lhs,
vec const &rhs)
noexcept {
152 return vec{lhs.t + rhs};
159 lhs.t + rhs.corner<0>(),
160 lhs.t + rhs.corner<1>(),
161 lhs.t + rhs.corner<2>(),
162 lhs.t + rhs.corner<3>()
166 [[nodiscard]]
friend rect operator*(
T const &lhs,
rect const &rhs)
noexcept {
168 lhs.t + rhs.corner<0>(),
169 lhs.t + rhs.corner<1>(),
170 lhs.t + rhs.corner<2>(),
171 lhs.t + rhs.corner<3>()
187 T2() noexcept : t() {}
189 explicit T2(
vec rhs) noexcept : t(rhs) {
190 tt_assume(rhs.is_vector());
191 tt_assume(rhs.z() == 0.0f);
194 T2(
float x,
float y) noexcept :
197 operator mat::T ()
const noexcept {
201 operator mat ()
const noexcept {
202 tt_assume(t.is_vector());
203 return { t._1000(), t._0100(), t._0010(), t.xyz1() };
206 [[nodiscard]]
friend T2 operator*(
T2 const &lhs,
T2 const &rhs)
noexcept {
207 return T2{lhs.t + rhs.t};
210 [[nodiscard]]
friend mat::T operator*(
mat::T const &lhs,
T2 const &rhs)
noexcept {
211 return mat::T{lhs.t + rhs.t};
214 [[nodiscard]]
friend mat::T operator*(
T2 const &lhs,
mat::T const &rhs)
noexcept {
215 return mat::T{lhs.t + rhs.t};
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() };
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() };
226 [[nodiscard]]
friend vec operator*(
T2 const &lhs,
vec const &rhs)
noexcept {
227 return vec{lhs.t + rhs};
230 [[nodiscard]]
friend aarect operator*(
T2 const &lhs,
aarect const &rhs)
noexcept {
231 return aarect::p0p3(lhs.t + rhs.p0(), lhs.t + rhs.p3());
234 [[nodiscard]]
friend rect operator*(
T2 const &lhs,
rect const &rhs)
noexcept {
236 lhs.t + rhs.corner<0>(),
237 lhs.t + rhs.corner<1>(),
238 lhs.t + rhs.corner<2>(),
239 lhs.t + rhs.corner<3>()
252 constexpr size_t size() noexcept {
return 4; }
255 [[nodiscard]] tt_force_inline vec &get() noexcept {
256 static_assert(
I <= 3);
257 if constexpr (
I == 0) {
259 }
else if constexpr (
I == 1) {
261 }
else if constexpr (
I == 2) {
269 [[nodiscard]] tt_force_inline vec get() const noexcept {
270 static_assert(
I <= 3);
271 if constexpr (
I == 0) {
273 }
else if constexpr (
I == 1) {
275 }
else if constexpr (
I == 2) {
285 ttlet xyxy = col0.xy00() + col1._00xy();
286 ttlet result = eq(xyxy,
vec{});
287 return (result == 0b1001) || (result == 0b0110);
295 (lhs.col0 * rhs.xxxx() + lhs.col1 * rhs.yyyy()) +
296 (lhs.col2 * rhs.zzzz() + lhs.col3 * rhs.wwww());
304 lhs * rhs.corner<1>(),
305 lhs * rhs.corner<2>(),
306 lhs * rhs.corner<3>()
315 lhs * rhs.corner<1>(),
316 lhs * rhs.corner<2>(),
317 lhs * rhs.corner<3>()
324 return {lhs * rhs.col0, lhs * rhs.col1, lhs * rhs.col2, lhs * rhs.col3};
330 return {lhs.s * rhs.col0, lhs.s * rhs.col1, lhs.s * rhs.col2, lhs.s * rhs.col3};
336 return {rhs.col0, rhs.col1, rhs.col2, lhs.t + rhs.col3};
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)};
354 ttlet s0c0 = rhs.col0 * rhs.col1.yxwz();
360 ttlet s1c1 = rhs.col0 * rhs.col2.yxwz();
361 ttlet s0c0s1c1 = hsub(s0c0, s1c1);
367 ttlet s2c2 = rhs.col0 * rhs.col3.yxwz();
373 ttlet s3c3 = rhs.col1 * rhs.col2.yxwz();
374 ttlet s2c2s3c3 = hsub(s2c2, s3c3);
380 ttlet s4c4 = rhs.col1 * rhs.col3.yxwz();
386 ttlet s5c5 = rhs.col2 * rhs.col3.yxwz();
387 ttlet s4c4s5c5 = hsub(s4c4, s5c5);
395 ttlet s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
396 ttlet s45__ = s4c4s5c5.xz00();
398 ttlet c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
399 ttlet c10__ = s0c0s1c1.wy00();
401 ttlet det_prod_half0 = neg<0,1,0,0>(s0123 * c5432);
402 ttlet det_prod_half1 = neg<1,0,0,0>(s45__ * c10__);
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();
408 if (det.x() == 0.0f) {
412 ttlet invdet = reciprocal(det);
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());
425 (t.col1.yxxx() * tmp_c5543) +
426 (t.col1.zzyy() * tmp_c4221) +
427 (t.col1.wwwz() * tmp_c3100)
434 tmp_c5543 = -tmp_c5543;
435 tmp_c4221 = -tmp_c4221;
436 tmp_c3100 = -tmp_c3100;
438 (t.col0.yxxx() * tmp_c5543) +
439 (t.col0.zzyy() * tmp_c4221) +
440 (t.col0.wwwz() * tmp_c3100)
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());
451 (t.col3.yxxx() * tmp_s5543) +
452 (t.col3.zzyy() * tmp_s4221) +
453 (t.col3.wwwz() * tmp_s3100)
460 tmp_s5543 = -tmp_s5543;
461 tmp_s4221 = -tmp_s4221;
462 tmp_s3100 = -tmp_s3100;
464 (t.col2.yxxx() * tmp_s5543) +
465 (t.col2.zzyy() * tmp_s4221) +
466 (t.col2.wwwz() * tmp_s3100)
469 return {inv_col0, inv_col1, inv_col2, inv_col3};
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;
476 [[nodiscard]]
friend bool operator!=(
mat const &lhs,
mat const &rhs)
noexcept {
477 return !(lhs == rhs);
482 [[nodiscard]]
static mat I() noexcept {
484 return { tmp._1000(), tmp._0100(), tmp._0010(), tmp._0001() };
487 [[nodiscard]]
static mat RGBtoXYZ(
491 float bx,
float by)
noexcept
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};
500 1.0f * (w.x() / w.y()),
502 1.0f * (w.z() / w.y())
506 ttlet C =
mat{r, g, b};
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() };
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};
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() };
542 return { tmp.xy00(), tmp.zx00(), tmp._0010(), tmp._0001() };
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;
566 [[nodiscard]]
friend std::string to_string(
mat const &rhs)
noexcept {
567 return fmt::format(
"[{}, {}, {}, {}]", rhs.col0, rhs.col1, rhs.col2, rhs.col3);
571 return lhs << to_string(rhs);
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
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