HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
matrix2.hpp
1// Copyright Take Vos 2021-2022.
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
9#pragma once
10
11#include "translate2.hpp"
12#include "scale2.hpp"
13#include "rotate2.hpp"
14#include "aarectangle.hpp"
15#include "../macros.hpp"
16#include <array>
17#include <exception>
18#include <compare>
19#include <stdexcept>
20
21hi_export_module(hikogui.geometry : matrix2);
22
23hi_export namespace hi { inline namespace v1 {
24class aarectangle;
25class scale2;
26class translate2;
27class matrix2;
28
29[[nodiscard]] constexpr matrix2 operator*(matrix2 const& lhs, matrix2 const& rhs) noexcept;
30[[nodiscard]] constexpr aarectangle operator*(scale2 const& lhs, aarectangle const& rhs) noexcept;
31[[nodiscard]] constexpr matrix2 operator*(translate2 const& lhs, scale2 const& rhs) noexcept;
32
39class matrix2 {
40public:
41 constexpr matrix2(matrix2 const&) noexcept = default;
42 constexpr matrix2(matrix2&&) noexcept = default;
43 constexpr matrix2& operator=(matrix2 const&) noexcept = default;
44 constexpr matrix2& operator=(matrix2&&) noexcept = default;
45
48 constexpr matrix2() noexcept
49 {
50 auto const a = f32x4::broadcast(1.0f);
51 _col0 = a.x000();
52 _col1 = a._0y00();
53 _col2 = a._00z0();
54 _col3 = a._000w();
55 };
56
64 constexpr matrix2(f32x4 col0, f32x4 col1, f32x4 col2, f32x4 col3 = f32x4{0.0f, 0.0f, 0.0f, 1.0f}) noexcept :
65 _col0(col0), _col1(col1), _col2(col2), _col3(col3)
66 {
67 hi_axiom(holds_invariant());
68 }
69
78 _col0(static_cast<f32x4>(col0)),
79 _col1(static_cast<f32x4>(col1)),
80 _col2(static_cast<f32x4>(col2)),
81 _col3(static_cast<f32x4>(col3).xyz1())
82 {
83 hi_axiom(holds_invariant());
84 }
85
92 _col0(static_cast<f32x4>(col0)),
93 _col1(static_cast<f32x4>(col1)),
94 _col2(f32x4{0.0f, 0.0f, 1.0f, 0.0f}),
95 _col3(f32x4{0.0f, 0.0f, 0.0f, 1.0f})
96 {
97 hi_axiom(holds_invariant());
98 }
99
115 constexpr matrix2(
116 float c0r0,
117 float c1r0,
118 float c2r0,
119 float c0r1,
120 float c1r1,
121 float c2r1,
122 float c0r2,
123 float c1r2,
124 float c2r2) noexcept :
125 _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)
126 {
127 hi_axiom(holds_invariant());
128 }
129
152 constexpr matrix2(
153 float c0r0,
154 float c1r0,
155 float c2r0,
156 float c3r0,
157 float c0r1,
158 float c1r1,
159 float c2r1,
160 float c3r1,
161 float c0r2,
162 float c1r2,
163 float c2r2,
164 float c3r2,
165 float c0r3,
166 float c1r3,
167 float c2r3,
168 float c3r3) noexcept :
169 _col0(c0r0, c0r1, c0r2, c0r3), _col1(c1r0, c1r1, c1r2, c1r3), _col2(c2r0, c2r1, c2r2, c2r3), _col3(c3r0, c3r1, c3r2, c3r3)
170 {
171 hi_axiom(holds_invariant());
172 }
173
174 [[nodiscard]] constexpr matrix2(translate2 const& rhs) noexcept
175 {
176 auto const ones = f32x4::broadcast(1.0f);
177 _col0 = ones.x000();
178 _col1 = ones._0y00();
179 _col2 = ones._00z0();
180 _col3 = ones._000w() + f32x4{rhs};
181 }
182
183 [[nodiscard]] constexpr matrix2(scale2 const& rhs) noexcept
184 {
185 _col0 = f32x4{rhs}.x000();
186 _col1 = f32x4{rhs}._0y00();
187 _col2 = f32x4{rhs}._00z0();
188 _col3 = f32x4{rhs}._000w();
189 }
190
194 [[nodiscard]] constexpr matrix2(rotate2 const& rhs) noexcept
195 {
196 // Original from https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
197 // 1 - 2(yy + zz) | 2(xy - zw) | 2(xz + yw)
198 // 2(xy + zw) | 1 - 2(xx + zz) | 2(yz - xw)
199 // 2(xz - yw) | 2(yz + xw) | 1 - 2(xx + yy)
200
201 // Flipping adds and multiplies:
202 // 1 - 2(zz + yy) | 2(xy - zw) | 2(yw + xz)
203 // 2(zw + yx) | 1 - 2(xx + zz) | 2(yz - xw)
204 // 2(zx - yw) | 2(xw + zy) | 1 - 2(yy + xx)
205
206 // All multiplies.
207 auto const x_mul = f32x4{rhs}.xxxx() * f32x4{rhs};
208 auto const y_mul = f32x4{rhs}.yyyy() * f32x4{rhs};
209 auto const z_mul = f32x4{rhs}.zzzz() * f32x4{rhs};
210
211 auto twos = f32x4{-2.0f, 2.0f, 2.0f, 0.0f};
212 auto one = f32x4{1.0f, 0.0f, 0.0f, 0.0f};
213 _col0 = one + addsub_mask<0b0011>(z_mul.zwxy(), y_mul.yxwz()) * twos;
214 one = one.yxzw();
215 twos = twos.yxzw();
216 _col1 = one + addsub_mask<0b0110>(x_mul.yxwz(), z_mul.wzyx()) * twos;
217 one = one.xzyw();
218 twos = twos.xzyw();
219 _col2 = one + addsub_mask<0b0101>(y_mul.wzyx(), x_mul.zwxy()) * twos;
220 _col3 = one.xywz();
221 }
222
225 [[nodiscard]] constexpr explicit operator std::array<f32x4, 4>() const noexcept
226 {
227 hi_axiom(holds_invariant());
228 return {_col0, _col1, _col2, _col3};
229 }
230
240 [[nodiscard]] constexpr static matrix2
248
254 template<int I>
255 [[nodiscard]] friend constexpr f32x4 const& get(matrix2 const& rhs) noexcept
256 {
257 if constexpr (I == 0) {
258 return rhs._col0;
259 } else if constexpr (I == 1) {
260 return rhs._col1;
261 } else if constexpr (I == 2) {
262 return rhs._col2;
263 } else if constexpr (I == 3) {
264 return rhs._col3;
265 } else {
266 hi_static_no_default();
267 }
268 }
269
275 template<int I>
276 [[nodiscard]] friend constexpr f32x4& get(matrix2& rhs) noexcept
277 {
278 if constexpr (I == 0) {
279 return rhs._col0;
280 } else if constexpr (I == 1) {
281 return rhs._col1;
282 } else if constexpr (I == 2) {
283 return rhs._col2;
284 } else if constexpr (I == 3) {
285 return rhs._col3;
286 } else {
287 hi_static_no_default();
288 }
289 }
290
291 [[nodiscard]] constexpr bool holds_invariant() const noexcept
292 {
293 return _col0.z() == 0.0f and _col0.w() == 0.0f and _col1.z() == 0.0f and _col1.w() == 0.0f and _col2.x() == 0.0f and
294 _col2.y() == 0.0f and _col2.z() == 1.0f and _col2.w() == 0.0f and _col3.z() == 0.0f and _col3.w() == 1.0f;
295 }
296
302 [[nodiscard]] constexpr f32x4 operator*(f32x4 const& rhs) const noexcept
303 {
304 return {_col0 * rhs.xxxx() + _col1 * rhs.yyyy() + _col2 * rhs.zzzz() + _col3 * rhs.wwww()};
305 }
306
309 [[nodiscard]] friend constexpr matrix2 transpose(matrix2 const& rhs) noexcept
310 {
311 auto tmp = transpose(rhs._col0, rhs._col1, rhs._col2, rhs._col3);
312 return matrix2{std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
313 }
314
348 template<char DstX, char DstY, char DstZ, char DstW = 'w'>
349 [[nodiscard]] friend constexpr matrix2 reflect(matrix2 const& rhs) noexcept
350 {
352 }
353
359 [[nodiscard]] constexpr friend bool operator==(matrix2 const& lhs, matrix2 const& rhs) noexcept
360 {
361 return equal(lhs._col0, rhs._col0) and equal(lhs._col1, rhs._col1) and equal(lhs._col3, rhs._col3);
362 }
363
366 [[nodiscard]] constexpr matrix2 operator~() const
367 {
368 // rc
369 // var s0 : Number = i00 * i11 -
370 // i10 * i01;
371 // var c0 : Number = i20 * i31 -
372 // i30 * i21;
373 auto const s0c0 = _col0 * _col1.yxwz();
374
375 // var s1 : Number = i00 * i12 -
376 // i10 * i02;
377 // var c1 : Number = i20 * i32 -
378 // i30 * i22;
379 auto const s1c1 = _col0 * _col2.yxwz();
380 auto const s0c0s1c1 = hsub(s0c0, s1c1);
381
382 // var s2 : Number = i00 * i13 -
383 // i10 * i03;
384 // var c2 : Number = i20 * i33 -
385 // i30 * i23;
386 auto const s2c2 = _col0 * _col3.yxwz();
387
388 // var s3 : Number = i01 * i12 -
389 // i11 * i02;
390 // var c3 : Number = i21 * i32 -
391 // i31 * i22;
392 auto const s3c3 = _col1 * _col2.yxwz();
393 auto const s2c2s3c3 = hsub(s2c2, s3c3);
394
395 // var s4 : Number = i01 * i13 -
396 // i11 * i03;
397 // var c4 : Number = i21 * i33 -
398 // i31 * i23;
399 auto const s4c4 = _col1 * _col3.yxwz();
400
401 // var s5 : Number = i02 * i13 -
402 // i12 * i03;
403 // var c5 : Number = i22 * i33 -
404 // i32 * i23;
405 auto const s5c5 = _col2 * _col3.yxwz();
406 auto const s4c4s5c5 = hsub(s4c4, s5c5);
407
408 // det = (s0 * c5 +
409 // -s1 * c4 +
410 // s2 * c3 +
411 // s3 * c2 +
412 // -s4 * c1 +
413 // s5 * c0)
414 auto const s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
415 auto const s45__ = s4c4s5c5.xz00();
416
417 auto const c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
418 auto const c10__ = s0c0s1c1.wy00();
419
422
423 auto const det_sum0 = hadd(det_prod_half0, det_prod_half1);
424 auto const det_sum1 = hadd(det_sum0, det_sum0);
425 auto const det = hadd(det_sum1, det_sum1).xxxx();
426
427 if (det.x() == 0.0f) {
428 throw std::domain_error("Divide by zero");
429 }
430
431 auto const invdet = rcp(det);
432
433 auto const t = transpose(*this);
434
435 // rc rc rc rc
436 // m.i00 := (i11 * c5 + i12 * -c4 + i13 * c3) * invdet;
437 // m.i10 := (i10 * -c5 + i12 * c2 + i13 * -c1) * invdet;
438 // m.i20 := (i10 * c4 + i11 * -c2 + i13 * c0) * invdet;
439 // m.i30 := (i10 * -c3 + i11 * c1 + i12 * -c0) * invdet;
440 auto tmp_c5543 = neg_mask<0b1010>(c5432.xxyz());
441 auto tmp_c4221 = neg_mask<0b0101>(c5432.yww0() + c10__._000x());
442 auto tmp_c3100 = neg_mask<0b1010>(c5432.z000() + c10__._0xyy());
443 auto const inv_col0 = ((t._col1.yxxx() * tmp_c5543) + (t._col1.zzyy() * tmp_c4221) + (t._col1.wwwz() * tmp_c3100)) * invdet;
444
445 // m.i01 := (i01 * -c5 + i02 * c4 + i03 * -c3) * invdet;
446 // m.i11 := (i00 * c5 + i02 * -c2 + i03 * c1) * invdet;
447 // m.i21 := (i00 * -c4 + i01 * c2 + i03 * -c0) * invdet;
448 // m.i31 := (i00 * c3 + i01 * -c1 + i02 * c0) * invdet;
452 auto const inv_col1 = ((t._col0.yxxx() * tmp_c5543) + (t._col0.zzyy() * tmp_c4221) + (t._col0.wwwz() * tmp_c3100)) * invdet;
453
454 // m.i02 := (i31 * s5 + i32 * -s4 + i33 * s3) * invdet;
455 // m.i12 := (i30 * -s5 + i32 * s2 + i33 * -s1) * invdet;
456 // m.i22 := (i30 * s4 + i31 * -s2 + i33 * s0) * invdet;
457 // m.i32 := (i30 * -s3 + i31 * s1 + i32 * -s0) * invdet;
458 auto tmp_s5543 = neg_mask<0b1010>(s45__.yyx0() + s0123._000w());
459 auto tmp_s4221 = neg_mask<0b0101>(s45__.x000() + s0123._0zzy());
460 auto tmp_s3100 = neg_mask<0b1010>(s0123.wyxx());
461 auto const inv_col2 = ((t._col3.yxxx() * tmp_s5543) + (t._col3.zzyy() * tmp_s4221) + (t._col3.wwwz() * tmp_s3100)) * invdet;
462
463 // m.i03 := (i21 * -s5 + i22 * s4 + i23 * -s3) * invdet;
464 // m.i13 := (i20 * s5 + i22 * -s2 + i23 * s1) * invdet;
465 // m.i23 := (i20 * -s4 + i21 * s2 + i23 * -s0) * invdet;
466 // m.i33 := (i20 * s3 + i21 * -s1 + i22 * s0) * invdet;
470 auto const inv_col3 = ((t._col2.yxxx() * tmp_s5543) + (t._col2.zzyy() * tmp_s4221) + (t._col2.wwwz() * tmp_s3100)) * invdet;
471
473 }
474
475private:
476 f32x4 _col0;
477 f32x4 _col1;
478 f32x4 _col2;
479 f32x4 _col3;
480
481 template<char Axis>
482 [[nodiscard]] constexpr static f32x4 reflect_column() noexcept
483 {
484 if constexpr (Axis == 'x') {
485 return f32x4{1.0f, 0.0f, 0.0f, 0.0f};
486 } else if constexpr (Axis == 'X') {
487 return f32x4{-1.0f, 0.0f, 0.0f, 0.0f};
488 } else if constexpr (Axis == 'y') {
489 return f32x4{0.0f, 1.0f, 0.0f, 0.0f};
490 } else if constexpr (Axis == 'Y') {
491 return f32x4{0.0f, -1.0f, 0.0f, 0.0f};
492 } else if constexpr (Axis == 'z') {
493 return f32x4{0.0f, 0.0f, 1.0f, 0.0f};
494 } else if constexpr (Axis == 'Z') {
495 return f32x4{0.0f, 0.0f, -1.0f, 0.0f};
496 } else if constexpr (Axis == 'w') {
497 return f32x4{0.0f, 0.0f, 0.0f, 1.0f};
498 } else if constexpr (Axis == 'W') {
499 return f32x4{0.0f, 0.0f, 0.0f, -1.0f};
500 } else {
501 hi_static_no_default();
502 }
503 }
504};
505
506}} // namespace hi::v1
The HikoGUI namespace.
Definition array_generic.hpp:20
@ one
The number was one, and this means something in the current language.
constexpr matrix2 operator*(matrix2 const &lhs, matrix2 const &rhs) noexcept
Matrix/Matrix multiplication.
Definition transform.hpp:69
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
Horizontal/Vertical alignment combination.
Definition alignment.hpp:244
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix2.hpp:39
constexpr matrix2(rotate2 const &rhs) noexcept
Convert quaternion to matrix.
Definition matrix2.hpp:194
constexpr matrix2(float c0r0, float c1r0, float c2r0, float c0r1, float c1r1, float c2r1, float c0r2, float c1r2, float c2r2) noexcept
Construct a 3x3 matrix from scalar values.
Definition matrix2.hpp:115
constexpr friend bool operator==(matrix2 const &lhs, matrix2 const &rhs) noexcept
Compare two matrices potentially of different dimensions.
Definition matrix2.hpp:359
constexpr matrix2(vector3 col0, vector3 col1, vector3 col2, vector3 col3=vector3{}) noexcept
Construct a matrix from four vectors.
Definition matrix2.hpp:77
friend constexpr f32x4 & get(matrix2 &rhs) noexcept
Get a column.
Definition matrix2.hpp:276
constexpr matrix2(float c0r0, float c1r0, float c2r0, float c3r0, float c0r1, float c1r1, float c2r1, float c3r1, float c0r2, float c1r2, float c2r2, float c3r2, float c0r3, float c1r3, float c2r3, float c3r3) noexcept
Construct a 4x4 matrix from scalar values.
Definition matrix2.hpp:152
constexpr f32x4 operator*(f32x4 const &rhs) const noexcept
Transform a f32x4 numeric array by the matrix.
Definition matrix2.hpp:302
static constexpr matrix2 uniform(aarectangle src_rectangle, aarectangle dst_rectangle, alignment alignment) noexcept
Create a transformation matrix to translate and uniformly-scale a src_rectangle to a dst_rectangle.
Definition matrix2.hpp:241
friend constexpr matrix2 transpose(matrix2 const &rhs) noexcept
Matrix transpose.
Definition matrix2.hpp:309
constexpr matrix2 operator~() const
Invert matrix.
Definition matrix2.hpp:366
constexpr matrix2(f32x4 col0, f32x4 col1, f32x4 col2, f32x4 col3=f32x4{0.0f, 0.0f, 0.0f, 1.0f}) noexcept
Construct a matrix from four columns.
Definition matrix2.hpp:64
constexpr matrix2(vector2 col0, vector2 col1) noexcept
Construct a matrix from two vectors.
Definition matrix2.hpp:91
constexpr matrix2() noexcept
Constructs an identity matrix.
Definition matrix2.hpp:48
friend constexpr matrix2 reflect(matrix2 const &rhs) noexcept
Reflect axis of a matrix.
Definition matrix2.hpp:349
friend constexpr f32x4 const & get(matrix2 const &rhs) noexcept
Get a column.
Definition matrix2.hpp:255
Definition rotate2.hpp:17
static constexpr scale2 uniform(extent2 src_extent, extent2 dst_extent) noexcept
Get a uniform-scale-transform to scale an extent to another extent.
Definition scale2.hpp:51
Definition translate2.hpp:18
static constexpr translate2 align(aarectangle src_rectangle, aarectangle dst_rectangle, alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition translate2.hpp:84
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:27
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector3.hpp:26
T size(T... args)