HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
matrix3.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 "matrix2.hpp"
12#include "translate3.hpp"
13#include "scale3.hpp"
14#include "rotate3.hpp"
15#include "../macros.hpp"
16#include <array>
17#include <exception>
18#include <compare>
19#include <stdexcept>
20
21hi_export_module(hikogui.geometry : matrix3);
22
23hi_export namespace hi { inline namespace v1 {
24
25class matrix3;
26[[nodiscard]] constexpr matrix3 operator*(matrix3 const& lhs, matrix3 const& rhs) noexcept;
27[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, scale3 const& rhs) noexcept;
28[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, rotate3 const& rhs) noexcept;
29
36class matrix3 {
37public:
38 constexpr matrix3(matrix3 const&) noexcept = default;
39 constexpr matrix3(matrix3&&) noexcept = default;
40 constexpr matrix3& operator=(matrix3 const&) noexcept = default;
41 constexpr matrix3& operator=(matrix3&&) noexcept = default;
42
45 constexpr matrix3() noexcept
46 {
47 auto const a = f32x4::broadcast(1.0f);
48 _col0 = a.x000();
49 _col1 = a._0y00();
50 _col2 = a._00z0();
51 _col3 = a._000w();
52 };
53
61 constexpr matrix3(f32x4 col0, f32x4 col1, f32x4 col2, f32x4 col3 = f32x4{0.0f, 0.0f, 0.0f, 1.0f}) noexcept :
62 _col0(col0), _col1(col1), _col2(col2), _col3(col3)
63 {
64 }
65
74 _col0(static_cast<f32x4>(col0)),
75 _col1(static_cast<f32x4>(col1)),
76 _col2(static_cast<f32x4>(col2)),
77 _col3(static_cast<f32x4>(col3).xyz1())
78 {
79 }
80
86 // constexpr matrix3(vector2 col0, vector2 col1) noexcept
87 // :
88 // _col0(static_cast<f32x4>(col0)),
89 // _col1(static_cast<f32x4>(col1)),
90 // _col2(f32x4{0.0f, 0.0f, 1.0f, 0.0f}),
91 // _col3(f32x4{0.0f, 0.0f, 0.0f, 1.0f})
92 //{
93 // }
94
110 constexpr matrix3(
111 float c0r0,
112 float c1r0,
113 float c2r0,
114 float c0r1,
115 float c1r1,
116 float c2r1,
117 float c0r2,
118 float c1r2,
119 float c2r2) noexcept :
120 _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)
121 {
122 }
123
146 constexpr matrix3(
147 float c0r0,
148 float c1r0,
149 float c2r0,
150 float c3r0,
151 float c0r1,
152 float c1r1,
153 float c2r1,
154 float c3r1,
155 float c0r2,
156 float c1r2,
157 float c2r2,
158 float c3r2,
159 float c0r3,
160 float c1r3,
161 float c2r3,
162 float c3r3) noexcept :
163 _col0(c0r0, c0r1, c0r2, c0r3), _col1(c1r0, c1r1, c1r2, c1r3), _col2(c2r0, c2r1, c2r2, c2r3), _col3(c3r0, c3r1, c3r2, c3r3)
164 {
165 }
166
169 [[nodiscard]] constexpr matrix3(matrix2 const& other) noexcept :
170 _col0(get<0>(other)), _col1(get<1>(other)), _col2(get<2>(other)), _col3(get<3>(other))
171 {
172 }
173
174 [[nodiscard]] constexpr explicit operator matrix2() const noexcept
175 {
176 auto tmp0 = _col0;
177 auto tmp1 = _col1;
178 auto tmp2 = _col2;
179 auto tmp3 = _col3;
180 tmp0.z() = 0.0f;
181 tmp0.w() = 0.0f;
182 tmp1.z() = 0.0f;
183 tmp1.w() = 0.0f;
184 tmp2.x() = 0.0f;
185 tmp2.y() = 0.0f;
186 tmp2.z() = 1.0f;
187 tmp2.w() = 0.0f;
188 tmp3.z() = 0.0f;
189 tmp3.w() = 1.0f;
190 return matrix2{tmp0, tmp1, tmp2, tmp3};
191 }
192
193 [[nodiscard]] constexpr matrix3(scale3 const& rhs) noexcept
194 {
195 _col0 = f32x4{rhs}.x000();
196 _col1 = f32x4{rhs}._0y00();
197 _col2 = f32x4{rhs}._00z0();
198 _col3 = f32x4{rhs}._000w();
199 }
200
201 [[nodiscard]] constexpr matrix3(translate3 const& rhs) noexcept
202 {
203 auto const ones = f32x4::broadcast(1.0f);
204 _col0 = ones.x000();
205 _col1 = ones._0y00();
206 _col2 = ones._00z0();
207 _col3 = ones._000w() + f32x4{rhs};
208 }
209
213 [[nodiscard]] constexpr matrix3(rotate3 const& rhs) noexcept
214 {
215 // Original from https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
216 // 1 - 2(yy + zz) | 2(xy - zw) | 2(xz + yw)
217 // 2(xy + zw) | 1 - 2(xx + zz) | 2(yz - xw)
218 // 2(xz - yw) | 2(yz + xw) | 1 - 2(xx + yy)
219
220 // Flipping adds and multiplies:
221 // 1 - 2(zz + yy) | 2(xy - zw) | 2(yw + xz)
222 // 2(zw + yx) | 1 - 2(xx + zz) | 2(yz - xw)
223 // 2(zx - yw) | 2(xw + zy) | 1 - 2(yy + xx)
224
225 // All multiplies.
226 auto const x_mul = f32x4{rhs}.xxxx() * f32x4{rhs};
227 auto const y_mul = f32x4{rhs}.yyyy() * f32x4{rhs};
228 auto const z_mul = f32x4{rhs}.zzzz() * f32x4{rhs};
229
230 auto twos = f32x4{-2.0f, 2.0f, 2.0f, 0.0f};
231 auto one = f32x4{1.0f, 0.0f, 0.0f, 0.0f};
232 _col0 = one + addsub_mask<0b0011>(z_mul.zwxy(), y_mul.yxwz()) * twos;
233 one = one.yxzw();
234 twos = twos.yxzw();
235 _col1 = one + addsub_mask<0b0110>(x_mul.yxwz(), z_mul.wzyx()) * twos;
236 one = one.xzyw();
237 twos = twos.xzyw();
238 _col2 = one + addsub_mask<0b0101>(y_mul.wzyx(), x_mul.zwxy()) * twos;
239 _col3 = one.xywz();
240 }
241
244 [[nodiscard]] constexpr explicit operator std::array<f32x4, 4>() const noexcept
245 {
246 hi_axiom(holds_invariant());
247 return {_col0, _col1, _col2, _col3};
248 }
249
259 [[nodiscard]] constexpr static matrix3
264
270 template<int I>
271 [[nodiscard]] friend constexpr f32x4 const& get(matrix3 const& rhs) noexcept
272 {
273 if constexpr (I == 0) {
274 return rhs._col0;
275 } else if constexpr (I == 1) {
276 return rhs._col1;
277 } else if constexpr (I == 2) {
278 return rhs._col2;
279 } else if constexpr (I == 3) {
280 return rhs._col3;
281 } else {
282 hi_static_no_default();
283 }
284 }
285
291 template<int I>
292 [[nodiscard]] friend constexpr f32x4& get(matrix3& rhs) noexcept
293 {
294 if constexpr (I == 0) {
295 return rhs._col0;
296 } else if constexpr (I == 1) {
297 return rhs._col1;
298 } else if constexpr (I == 2) {
299 return rhs._col2;
300 } else if constexpr (I == 3) {
301 return rhs._col3;
302 } else {
303 hi_static_no_default();
304 }
305 }
306
307 [[nodiscard]] constexpr bool holds_invariant() const noexcept
308 {
309 return true;
310 }
311
317 [[nodiscard]] constexpr f32x4 operator*(f32x4 const& rhs) const noexcept
318 {
319 return {_col0 * rhs.xxxx() + _col1 * rhs.yyyy() + _col2 * rhs.zzzz() + _col3 * rhs.wwww()};
320 }
321
322
325 [[nodiscard]] friend constexpr matrix3 transpose(matrix3 const& rhs) noexcept
326 {
327 auto tmp = transpose(rhs._col0, rhs._col1, rhs._col2, rhs._col3);
328 return matrix3{std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
329 }
330
364 template<char DstX, char DstY, char DstZ, char DstW = 'w'>
365 [[nodiscard]] friend constexpr matrix3 reflect(matrix3 const& rhs) noexcept
366 {
368 }
369
375 [[nodiscard]] constexpr friend bool operator==(matrix3 const& lhs, matrix3 const& rhs) noexcept
376 {
377 return equal(lhs._col0, rhs._col0) and equal(lhs._col1, rhs._col1) and equal(lhs._col2, rhs._col2) and
378 equal(lhs._col3, rhs._col3);
379 }
380
383 [[nodiscard]] constexpr matrix3 operator~() const
384 {
385 // rc
386 // var s0 : Number = i00 * i11 -
387 // i10 * i01;
388 // var c0 : Number = i20 * i31 -
389 // i30 * i21;
390 auto const s0c0 = _col0 * _col1.yxwz();
391
392 // var s1 : Number = i00 * i12 -
393 // i10 * i02;
394 // var c1 : Number = i20 * i32 -
395 // i30 * i22;
396 auto const s1c1 = _col0 * _col2.yxwz();
397 auto const s0c0s1c1 = hsub(s0c0, s1c1);
398
399 // var s2 : Number = i00 * i13 -
400 // i10 * i03;
401 // var c2 : Number = i20 * i33 -
402 // i30 * i23;
403 auto const s2c2 = _col0 * _col3.yxwz();
404
405 // var s3 : Number = i01 * i12 -
406 // i11 * i02;
407 // var c3 : Number = i21 * i32 -
408 // i31 * i22;
409 auto const s3c3 = _col1 * _col2.yxwz();
410 auto const s2c2s3c3 = hsub(s2c2, s3c3);
411
412 // var s4 : Number = i01 * i13 -
413 // i11 * i03;
414 // var c4 : Number = i21 * i33 -
415 // i31 * i23;
416 auto const s4c4 = _col1 * _col3.yxwz();
417
418 // var s5 : Number = i02 * i13 -
419 // i12 * i03;
420 // var c5 : Number = i22 * i33 -
421 // i32 * i23;
422 auto const s5c5 = _col2 * _col3.yxwz();
423 auto const s4c4s5c5 = hsub(s4c4, s5c5);
424
425 // det = (s0 * c5 +
426 // -s1 * c4 +
427 // s2 * c3 +
428 // s3 * c2 +
429 // -s4 * c1 +
430 // s5 * c0)
431 auto const s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
432 auto const s45__ = s4c4s5c5.xz00();
433
434 auto const c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
435 auto const c10__ = s0c0s1c1.wy00();
436
439
440 auto const det_sum0 = hadd(det_prod_half0, det_prod_half1);
441 auto const det_sum1 = hadd(det_sum0, det_sum0);
442 auto const det = hadd(det_sum1, det_sum1).xxxx();
443
444 if (det.x() == 0.0f) {
445 throw std::domain_error("Divide by zero");
446 }
447
448 auto const invdet = rcp(det);
449
450 auto const t = transpose(*this);
451
452 // rc rc rc rc
453 // m.i00 := (i11 * c5 + i12 * -c4 + i13 * c3) * invdet;
454 // m.i10 := (i10 * -c5 + i12 * c2 + i13 * -c1) * invdet;
455 // m.i20 := (i10 * c4 + i11 * -c2 + i13 * c0) * invdet;
456 // m.i30 := (i10 * -c3 + i11 * c1 + i12 * -c0) * invdet;
457 auto tmp_c5543 = neg_mask<0b1010>(c5432.xxyz());
458 auto tmp_c4221 = neg_mask<0b0101>(c5432.yww0() + c10__._000x());
459 auto tmp_c3100 = neg_mask<0b1010>(c5432.z000() + c10__._0xyy());
460 auto const inv_col0 = ((t._col1.yxxx() * tmp_c5543) + (t._col1.zzyy() * tmp_c4221) + (t._col1.wwwz() * tmp_c3100)) * invdet;
461
462 // m.i01 := (i01 * -c5 + i02 * c4 + i03 * -c3) * invdet;
463 // m.i11 := (i00 * c5 + i02 * -c2 + i03 * c1) * invdet;
464 // m.i21 := (i00 * -c4 + i01 * c2 + i03 * -c0) * invdet;
465 // m.i31 := (i00 * c3 + i01 * -c1 + i02 * c0) * invdet;
469 auto const inv_col1 = ((t._col0.yxxx() * tmp_c5543) + (t._col0.zzyy() * tmp_c4221) + (t._col0.wwwz() * tmp_c3100)) * invdet;
470
471 // m.i02 := (i31 * s5 + i32 * -s4 + i33 * s3) * invdet;
472 // m.i12 := (i30 * -s5 + i32 * s2 + i33 * -s1) * invdet;
473 // m.i22 := (i30 * s4 + i31 * -s2 + i33 * s0) * invdet;
474 // m.i32 := (i30 * -s3 + i31 * s1 + i32 * -s0) * invdet;
475 auto tmp_s5543 = neg_mask<0b1010>(s45__.yyx0() + s0123._000w());
476 auto tmp_s4221 = neg_mask<0b0101>(s45__.x000() + s0123._0zzy());
477 auto tmp_s3100 = neg_mask<0b1010>(s0123.wyxx());
478 auto const inv_col2 = ((t._col3.yxxx() * tmp_s5543) + (t._col3.zzyy() * tmp_s4221) + (t._col3.wwwz() * tmp_s3100)) * invdet;
479
480 // m.i03 := (i21 * -s5 + i22 * s4 + i23 * -s3) * invdet;
481 // m.i13 := (i20 * s5 + i22 * -s2 + i23 * s1) * invdet;
482 // m.i23 := (i20 * -s4 + i21 * s2 + i23 * -s0) * invdet;
483 // m.i33 := (i20 * s3 + i21 * -s1 + i22 * s0) * invdet;
487 auto const inv_col3 = ((t._col2.yxxx() * tmp_s5543) + (t._col2.zzyy() * tmp_s4221) + (t._col2.wwwz() * tmp_s3100)) * invdet;
488
490 }
491
492private:
493 f32x4 _col0;
494 f32x4 _col1;
495 f32x4 _col2;
496 f32x4 _col3;
497
498 template<char Axis>
499 [[nodiscard]] constexpr static f32x4 reflect_column() noexcept
500 {
501 if constexpr (Axis == 'x') {
502 return f32x4{1.0f, 0.0f, 0.0f, 0.0f};
503 } else if constexpr (Axis == 'X') {
504 return f32x4{-1.0f, 0.0f, 0.0f, 0.0f};
505 } else if constexpr (Axis == 'y') {
506 return f32x4{0.0f, 1.0f, 0.0f, 0.0f};
507 } else if constexpr (Axis == 'Y') {
508 return f32x4{0.0f, -1.0f, 0.0f, 0.0f};
509 } else if constexpr (Axis == 'z') {
510 return f32x4{0.0f, 0.0f, 1.0f, 0.0f};
511 } else if constexpr (Axis == 'Z') {
512 return f32x4{0.0f, 0.0f, -1.0f, 0.0f};
513 } else if constexpr (Axis == 'w') {
514 return f32x4{0.0f, 0.0f, 0.0f, 1.0f};
515 } else if constexpr (Axis == 'W') {
516 return f32x4{0.0f, 0.0f, 0.0f, -1.0f};
517 } else {
518 hi_static_no_default();
519 }
520 }
521};
522
523
524
525}} // namespace hi::v1
@ other
The gui_event does not have associated data.
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
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
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:36
friend constexpr matrix3 transpose(matrix3 const &rhs) noexcept
Matrix transpose.
Definition matrix3.hpp:325
constexpr f32x4 operator*(f32x4 const &rhs) const noexcept
Transform a f32x4 numeric array by the matrix.
Definition matrix3.hpp:317
friend constexpr matrix3 reflect(matrix3 const &rhs) noexcept
Reflect axis of a matrix.
Definition matrix3.hpp:365
constexpr matrix3(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 matrix3.hpp:61
constexpr matrix3(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 matrix3.hpp:146
constexpr matrix3(matrix2 const &other) noexcept
Copy-construct a matrix from a smaller matrix.
Definition matrix3.hpp:169
constexpr matrix3(rotate3 const &rhs) noexcept
Convert quaternion to matrix.
Definition matrix3.hpp:213
constexpr friend bool operator==(matrix3 const &lhs, matrix3 const &rhs) noexcept
Compare two matrices potentially of different dimensions.
Definition matrix3.hpp:375
constexpr matrix3() noexcept
Constructs an identity matrix.
Definition matrix3.hpp:45
friend constexpr f32x4 & get(matrix3 &rhs) noexcept
Get a column.
Definition matrix3.hpp:292
constexpr matrix3 operator~() const
Invert matrix.
Definition matrix3.hpp:383
friend constexpr f32x4 const & get(matrix3 const &rhs) noexcept
Get a column.
Definition matrix3.hpp:271
constexpr matrix3(float c0r0, float c1r0, float c2r0, float c0r1, float c1r1, float c2r1, float c0r2, float c1r2, float c2r2) noexcept
Construct a matrix from two vectors.
Definition matrix3.hpp:110
static constexpr matrix3 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 matrix3.hpp:260
constexpr matrix3(vector3 col0, vector3 col1, vector3 col2, vector3 col3=vector3{}) noexcept
Construct a matrix from four vectors.
Definition matrix3.hpp:73
Definition rotate3.hpp:17
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector3.hpp:26