HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
matrix.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "vector.hpp"
8#include "extent.hpp"
9#include "point.hpp"
10#include "../rect.hpp"
11#include "../aarect.hpp"
12#include "../color/color.hpp"
13
14namespace tt {
15namespace geo {
16
17template<int D>
18class matrix {
19public:
20 static_assert(D == 2 || D == 3, "Only 2D or 3D rotation-matrices are supported");
21
22 constexpr matrix(matrix const &) noexcept = default;
23 constexpr matrix(matrix &&) noexcept = default;
24 constexpr matrix &operator=(matrix const &) noexcept = default;
25 constexpr matrix &operator=(matrix &&) noexcept = default;
26
27 constexpr matrix() noexcept :
28 _col0(1.0f, 0.0f, 0.0f, 0.0f),
29 _col1(0.0f, 1.0f, 0.0f, 0.0f),
30 _col2(0.0f, 0.0f, 1.0f, 0.0f),
31 _col3(0.0f, 0.0f, 0.0f, 1.0f){};
32
33 constexpr matrix(f32x4 col0, f32x4 col1, f32x4 col2, f32x4 col3 = f32x4{0.0f, 0.0f, 0.0f, 1.0f}) noexcept :
34 _col0(col0), _col1(col1), _col2(col2), _col3(col3)
35 {
36 }
37
38 constexpr matrix(
39 float c0r0,
40 float c1r0,
41 float c2r0,
42 float c0r1,
43 float c1r1,
44 float c2r1,
45 float c0r2,
46 float c1r2,
47 float c2r2) noexcept requires(D == 3) :
48 _col0(c0r0, c0r1, c0r2, 0.0f), _col1(c1r0, c1r1, c1r2, 0.0f), _col2(c2r0, c2r1, c2r2, 0.0f), _col3(0.0f, 0.0f, 0.0f, 1.0f)
49 {
50 }
51
52 constexpr matrix(
53 float c0r0,
54 float c1r0,
55 float c2r0,
56 float c3r0,
57 float c0r1,
58 float c1r1,
59 float c2r1,
60 float c3r1,
61 float c0r2,
62 float c1r2,
63 float c2r2,
64 float c3r2,
65 float c0r3,
66 float c1r3,
67 float c2r3,
68 float c3r3) noexcept requires(D == 3) :
69 _col0(c0r0, c0r1, c0r2, c0r3), _col1(c1r0, c1r1, c1r2, c1r3), _col2(c2r0, c2r1, c2r2, c2r3), _col3(c3r0, c3r1, c3r2, c3r3)
70 {
71 }
72
73 template<int E>
74 requires(E < D) [[nodiscard]] constexpr matrix(matrix<E> const &other) noexcept :
75 _col0(get<0>(other)), _col1(get<1>(other)), _col2(get<2>(other)), _col3(get<3>(other))
76 {
77 }
78
79 template<int E>
80 requires(E < D) constexpr matrix &operator=(matrix<E> const &rhs) noexcept
81 {
82 _col0 = get<0>(rhs);
83 _col1 = get<1>(rhs);
84 _col2 = get<2>(rhs);
85 _col3 = get<3>(rhs);
86 return *this;
87 }
88
98 [[nodiscard]] constexpr static matrix uniform(aarect src_rectangle, aarect dst_rectangle, alignment alignment) noexcept;
99
100 template<int I>
101 [[nodiscard]] friend constexpr f32x4 get(matrix const &rhs) noexcept
102 {
103 if constexpr (I == 0) {
104 return rhs._col0;
105 } else if constexpr (I == 1) {
106 return rhs._col1;
107 } else if constexpr (I == 2) {
108 return rhs._col2;
109 } else if constexpr (I == 3) {
110 return rhs._col3;
111 } else {
112 tt_static_no_default();
113 }
114 }
115
116 [[nodiscard]] constexpr bool is_valid() const noexcept
117 {
118 return true;
119 }
120
121 [[nodiscard]] constexpr auto operator*(f32x4 const &rhs) const noexcept
122 {
123 return f32x4{_col0 * rhs.xxxx() + _col1 * rhs.yyyy() + _col2 * rhs.zzzz() + _col3 * rhs.wwww()};
124 }
125
126 template<int E>
127 [[nodiscard]] constexpr auto operator*(vector<E> const &rhs) const noexcept
128 {
129 tt_axiom(rhs.is_valid());
130 return vector<std::max(D, E)>{
131 _col0 * static_cast<f32x4>(rhs).xxxx() + _col1 * static_cast<f32x4>(rhs).yyyy() +
132 _col2 * static_cast<f32x4>(rhs).zzzz()};
133 }
134
135 template<int E>
136 [[nodiscard]] constexpr auto operator*(extent<E> const &rhs) const noexcept
137 {
138 tt_axiom(rhs.is_valid());
139 return extent<std::max(D, E)>{
140 _col0 * static_cast<f32x4>(rhs).xxxx() + _col1 * static_cast<f32x4>(rhs).yyyy() +
141 _col2 * static_cast<f32x4>(rhs).zzzz()};
142 }
143
144 template<int E>
145 [[nodiscard]] constexpr auto operator*(point<E> const &rhs) const noexcept
146 {
147 tt_axiom(rhs.is_valid());
148 return point<std::max(D, E)>{
149 _col0 * static_cast<f32x4>(rhs).xxxx() + _col1 * static_cast<f32x4>(rhs).yyyy() +
150 _col2 * static_cast<f32x4>(rhs).zzzz() + _col3 * static_cast<f32x4>(rhs).wwww()};
151 }
152
153 [[nodiscard]] constexpr auto operator*(rect const &rhs) const noexcept
154 {
155 return rect{*this * rhs.corner<0>(), *this * rhs.corner<1>(), *this * rhs.corner<2>(), *this * rhs.corner<3>()};
156 }
157
162 [[nodiscard]] constexpr auto operator*(color const &rhs) const noexcept
163 {
164 tt_axiom(rhs.is_valid());
165 auto r = color{
166 _col0 * static_cast<f32x4>(rhs).xxxx() + _col1 * static_cast<f32x4>(rhs).yyyy() +
167 _col2 * static_cast<f32x4>(rhs).zzzz() + _col3};
168
169 r.a() = rhs.a();
170 return r;
171 }
172
175 [[nodiscard]] constexpr auto operator*(matrix<2> const &rhs) const noexcept
176 {
177 return matrix<D>{*this * get<0>(rhs), *this * get<1>(rhs), *this * get<2>(rhs), *this * get<3>(rhs)};
178 }
179
182 [[nodiscard]] constexpr auto operator*(matrix<3> const &rhs) const noexcept
183 {
184 return matrix<3>{*this * get<0>(rhs), *this * get<1>(rhs), *this * get<2>(rhs), *this * get<3>(rhs)};
185 }
186
189 [[nodiscard]] friend constexpr matrix transpose(matrix rhs) noexcept
190 {
191 auto tmp = transpose(rhs._col0, rhs._col1, rhs._col2, rhs._col3);
192 return {std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
193 }
194
195 template<int E>
196 [[nodiscard]] constexpr bool operator==(matrix<E> const &rhs) const noexcept
197 {
198 return _col0 == rhs._col0 && _col1 == rhs._col1 && _col2 == rhs._col2 && _col3 == rhs._col3;
199 }
200
203 [[nodiscard]] constexpr matrix operator~() const
204 {
205 // rc
206 // var s0 : Number = i00 * i11 -
207 // i10 * i01;
208 // var c0 : Number = i20 * i31 -
209 // i30 * i21;
210 ttlet s0c0 = _col0 * _col1.yxwz();
211
212 // var s1 : Number = i00 * i12 -
213 // i10 * i02;
214 // var c1 : Number = i20 * i32 -
215 // i30 * i22;
216 ttlet s1c1 = _col0 * _col2.yxwz();
217 ttlet s0c0s1c1 = hsub(s0c0, s1c1);
218
219 // var s2 : Number = i00 * i13 -
220 // i10 * i03;
221 // var c2 : Number = i20 * i33 -
222 // i30 * i23;
223 ttlet s2c2 = _col0 * _col3.yxwz();
224
225 // var s3 : Number = i01 * i12 -
226 // i11 * i02;
227 // var c3 : Number = i21 * i32 -
228 // i31 * i22;
229 ttlet s3c3 = _col1 * _col2.yxwz();
230 ttlet s2c2s3c3 = hsub(s2c2, s3c3);
231
232 // var s4 : Number = i01 * i13 -
233 // i11 * i03;
234 // var c4 : Number = i21 * i33 -
235 // i31 * i23;
236 ttlet s4c4 = _col1 * _col3.yxwz();
237
238 // var s5 : Number = i02 * i13 -
239 // i12 * i03;
240 // var c5 : Number = i22 * i33 -
241 // i32 * i23;
242 ttlet s5c5 = _col2 * _col3.yxwz();
243 ttlet s4c4s5c5 = hsub(s4c4, s5c5);
244
245 // det = (s0 * c5 +
246 // -s1 * c4 +
247 // s2 * c3 +
248 // s3 * c2 +
249 // -s4 * c1 +
250 // s5 * c0)
251 ttlet s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
252 ttlet s45__ = s4c4s5c5.xz00();
253
254 ttlet c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
255 ttlet c10__ = s0c0s1c1.wy00();
256
257 ttlet det_prod_half0 = neg<0b0010>(s0123 * c5432);
258 ttlet det_prod_half1 = neg<0b0001>(s45__ * c10__);
259
260 ttlet det_sum0 = hadd(det_prod_half0, det_prod_half1);
261 ttlet det_sum1 = hadd(det_sum0, det_sum0);
262 ttlet det = hadd(det_sum1, det_sum1).xxxx();
263
264 if (det.x() == 0.0f) {
265 throw std::domain_error("Divide by zero");
266 }
267
268 ttlet invdet = rcp(det);
269
270 ttlet t = transpose(*this);
271
272 // rc rc rc rc
273 // m.i00 = (i11 * c5 + i12 * -c4 + i13 * c3) * invdet;
274 // m.i10 = (i10 * -c5 + i12 * c2 + i13 * -c1) * invdet;
275 // m.i20 = (i10 * c4 + i11 * -c2 + i13 * c0) * invdet;
276 // m.i30 = (i10 * -c3 + i11 * c1 + i12 * -c0) * invdet;
277 auto tmp_c5543 = neg<0b1010>(c5432.xxyz());
278 auto tmp_c4221 = neg<0b0101>(c5432.yww0() + c10__._000x());
279 auto tmp_c3100 = neg<0b1010>(c5432.z000() + c10__._0xyy());
280 ttlet inv_col0 = ((t._col1.yxxx() * tmp_c5543) + (t._col1.zzyy() * tmp_c4221) + (t._col1.wwwz() * tmp_c3100)) * invdet;
281
282 // m.i01 = (i01 * -c5 + i02 * c4 + i03 * -c3) * invdet;
283 // m.i11 = (i00 * c5 + i02 * -c2 + i03 * c1) * invdet;
284 // m.i21 = (i00 * -c4 + i01 * c2 + i03 * -c0) * invdet;
285 // m.i31 = (i00 * c3 + i01 * -c1 + i02 * c0) * invdet;
286 tmp_c5543 = -tmp_c5543;
287 tmp_c4221 = -tmp_c4221;
288 tmp_c3100 = -tmp_c3100;
289 ttlet inv_col1 = ((t._col0.yxxx() * tmp_c5543) + (t._col0.zzyy() * tmp_c4221) + (t._col0.wwwz() * tmp_c3100)) * invdet;
290
291 // m.i02 = (i31 * s5 + i32 * -s4 + i33 * s3) * invdet;
292 // m.i12 = (i30 * -s5 + i32 * s2 + i33 * -s1) * invdet;
293 // m.i22 = (i30 * s4 + i31 * -s2 + i33 * s0) * invdet;
294 // m.i32 = (i30 * -s3 + i31 * s1 + i32 * -s0) * invdet;
295 auto tmp_s5543 = neg<0b1010>(s45__.yyx0() + s0123._000w());
296 auto tmp_s4221 = neg<0b0101>(s45__.x000() + s0123._0zzy());
297 auto tmp_s3100 = neg<0b1010>(s0123.wyxx());
298 ttlet inv_col2 = ((t._col3.yxxx() * tmp_s5543) + (t._col3.zzyy() * tmp_s4221) + (t._col3.wwwz() * tmp_s3100)) * invdet;
299
300 // m.i03 = (i21 * -s5 + i22 * s4 + i23 * -s3) * invdet;
301 // m.i13 = (i20 * s5 + i22 * -s2 + i23 * s1) * invdet;
302 // m.i23 = (i20 * -s4 + i21 * s2 + i23 * -s0) * invdet;
303 // m.i33 = (i20 * s3 + i21 * -s1 + i22 * s0) * invdet;
304 tmp_s5543 = -tmp_s5543;
305 tmp_s4221 = -tmp_s4221;
306 tmp_s3100 = -tmp_s3100;
307 ttlet inv_col3 = ((t._col2.yxxx() * tmp_s5543) + (t._col2.zzyy() * tmp_s4221) + (t._col2.wwwz() * tmp_s3100)) * invdet;
308
309 return {inv_col0, inv_col1, inv_col2, inv_col3};
310 }
311
312private:
313 f32x4 _col0;
314 f32x4 _col1;
315 f32x4 _col2;
316 f32x4 _col3;
317};
318
319} // namespace geo
320
321using matrix2 = geo::matrix<2>;
322using matrix3 = geo::matrix<3>;
323
324} // namespace tt
This is a RGBA floating point color.
Definition color.hpp:39
A high-level geometric extent.
Definition extent.hpp:20
Definition matrix.hpp:18
constexpr auto operator*(color const &rhs) const noexcept
Transform a color by a color matrix.
Definition matrix.hpp:162
static constexpr matrix uniform(aarect src_rectangle, aarect dst_rectangle, alignment alignment) noexcept
Create a transformation matrix to translate and uniformly-scale a src_rectangle to a dst_rectangle.
Definition scale.hpp:140
constexpr auto operator*(matrix< 3 > const &rhs) const noexcept
Matrix/Matrix multiplication.
Definition matrix.hpp:182
constexpr matrix operator~() const
Invert matrix.
Definition matrix.hpp:203
friend constexpr matrix transpose(matrix rhs) noexcept
Matrix transpose.
Definition matrix.hpp:189
constexpr auto operator*(matrix< 2 > const &rhs) const noexcept
Matrix/Matrix multiplication.
Definition matrix.hpp:175
A high-level geometric point Part of the high-level vec, point, mat and color types.
Definition point.hpp:21
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
Class which represents an rectangle.
Definition rect.hpp:16
T max(T... args)