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
18namespace hi { inline namespace v1 {
19
20class matrix3;
21[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, scale3 const& rhs) noexcept;
22[[nodiscard]] constexpr matrix3 operator*(translate3 const& lhs, rotate3 const& rhs) noexcept;
23
30class matrix3 {
31public:
32 constexpr matrix3(matrix3 const&) noexcept = default;
33 constexpr matrix3(matrix3&&) noexcept = default;
34 constexpr matrix3& operator=(matrix3 const&) noexcept = default;
35 constexpr matrix3& operator=(matrix3&&) noexcept = default;
36
39 constexpr matrix3() noexcept
40 {
41 hilet a = f32x4::broadcast(1.0f);
42 _col0 = a.x000();
43 _col1 = a._0y00();
44 _col2 = a._00z0();
45 _col3 = a._000w();
46 };
47
55 constexpr matrix3(f32x4 col0, f32x4 col1, f32x4 col2, f32x4 col3 = f32x4{0.0f, 0.0f, 0.0f, 1.0f}) noexcept :
56 _col0(col0), _col1(col1), _col2(col2), _col3(col3)
57 {
58 }
59
68 _col0(static_cast<f32x4>(col0)),
69 _col1(static_cast<f32x4>(col1)),
70 _col2(static_cast<f32x4>(col2)),
71 _col3(static_cast<f32x4>(col3).xyz1())
72 {
73 }
74
80 // constexpr matrix3(vector2 col0, vector2 col1) noexcept
81 // :
82 // _col0(static_cast<f32x4>(col0)),
83 // _col1(static_cast<f32x4>(col1)),
84 // _col2(f32x4{0.0f, 0.0f, 1.0f, 0.0f}),
85 // _col3(f32x4{0.0f, 0.0f, 0.0f, 1.0f})
86 //{
87 // }
88
104 constexpr matrix3(
105 float c0r0,
106 float c1r0,
107 float c2r0,
108 float c0r1,
109 float c1r1,
110 float c2r1,
111 float c0r2,
112 float c1r2,
113 float c2r2) noexcept :
114 _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)
115 {
116 }
117
140 constexpr matrix3(
141 float c0r0,
142 float c1r0,
143 float c2r0,
144 float c3r0,
145 float c0r1,
146 float c1r1,
147 float c2r1,
148 float c3r1,
149 float c0r2,
150 float c1r2,
151 float c2r2,
152 float c3r2,
153 float c0r3,
154 float c1r3,
155 float c2r3,
156 float c3r3) noexcept :
157 _col0(c0r0, c0r1, c0r2, c0r3), _col1(c1r0, c1r1, c1r2, c1r3), _col2(c2r0, c2r1, c2r2, c2r3), _col3(c3r0, c3r1, c3r2, c3r3)
158 {
159 }
160
163 [[nodiscard]] constexpr matrix3(matrix2 const& other) noexcept :
164 _col0(get<0>(other)), _col1(get<1>(other)), _col2(get<2>(other)), _col3(get<3>(other))
165 {
166 }
167
168 [[nodiscard]] constexpr explicit operator matrix2() const noexcept
169 {
170 auto tmp0 = _col0;
171 auto tmp1 = _col1;
172 auto tmp2 = _col2;
173 auto tmp3 = _col3;
174 tmp0.z() = 0.0f;
175 tmp0.w() = 0.0f;
176 tmp1.z() = 0.0f;
177 tmp1.w() = 0.0f;
178 tmp2.x() = 0.0f;
179 tmp2.y() = 0.0f;
180 tmp2.z() = 1.0f;
181 tmp2.w() = 0.0f;
182 tmp3.z() = 0.0f;
183 tmp3.w() = 1.0f;
184 return matrix2{tmp0, tmp1, tmp2, tmp3};
185 }
186
187 [[nodiscard]] constexpr matrix3(scale3 const& rhs) noexcept
188 {
189 _col0 = f32x4{rhs}.x000();
190 _col1 = f32x4{rhs}._0y00();
191 _col2 = f32x4{rhs}._00z0();
192 _col3 = f32x4{rhs}._000w();
193 }
194
195 [[nodiscard]] constexpr matrix3(translate3 const& rhs) noexcept
196 {
197 hilet ones = f32x4::broadcast(1.0f);
198 _col0 = ones.x000();
199 _col1 = ones._0y00();
200 _col2 = ones._00z0();
201 _col3 = ones._000w() + f32x4{rhs};
202 }
203
207 [[nodiscard]] constexpr matrix3(rotate3 const& rhs) noexcept
208 {
209 // Original from https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
210 // 1 - 2(yy + zz) | 2(xy - zw) | 2(xz + yw)
211 // 2(xy + zw) | 1 - 2(xx + zz) | 2(yz - xw)
212 // 2(xz - yw) | 2(yz + xw) | 1 - 2(xx + yy)
213
214 // Flipping adds and multiplies:
215 // 1 - 2(zz + yy) | 2(xy - zw) | 2(yw + xz)
216 // 2(zw + yx) | 1 - 2(xx + zz) | 2(yz - xw)
217 // 2(zx - yw) | 2(xw + zy) | 1 - 2(yy + xx)
218
219 // All multiplies.
220 hilet x_mul = f32x4{rhs}.xxxx() * f32x4{rhs};
221 hilet y_mul = f32x4{rhs}.yyyy() * f32x4{rhs};
222 hilet z_mul = f32x4{rhs}.zzzz() * f32x4{rhs};
223
224 auto twos = f32x4{-2.0f, 2.0f, 2.0f, 0.0f};
225 auto one = f32x4{1.0f, 0.0f, 0.0f, 0.0f};
226 _col0 = one + addsub<0b0011>(z_mul.zwxy(), y_mul.yxwz()) * twos;
227 one = one.yxzw();
228 twos = twos.yxzw();
229 _col1 = one + addsub<0b0110>(x_mul.yxwz(), z_mul.wzyx()) * twos;
230 one = one.xzyw();
231 twos = twos.xzyw();
232 _col2 = one + addsub<0b0101>(y_mul.wzyx(), x_mul.zwxy()) * twos;
233 _col3 = one.xywz();
234 }
235
238 [[nodiscard]] constexpr explicit operator std::array<f32x4, 4>() const noexcept
239 {
240 hi_axiom(holds_invariant());
241 return {_col0, _col1, _col2, _col3};
242 }
243
253 [[nodiscard]] constexpr static matrix3
258
264 template<int I>
265 [[nodiscard]] friend constexpr f32x4 const& get(matrix3 const& rhs) noexcept
266 {
267 if constexpr (I == 0) {
268 return rhs._col0;
269 } else if constexpr (I == 1) {
270 return rhs._col1;
271 } else if constexpr (I == 2) {
272 return rhs._col2;
273 } else if constexpr (I == 3) {
274 return rhs._col3;
275 } else {
276 hi_static_no_default();
277 }
278 }
279
285 template<int I>
286 [[nodiscard]] friend constexpr f32x4& get(matrix3& rhs) noexcept
287 {
288 if constexpr (I == 0) {
289 return rhs._col0;
290 } else if constexpr (I == 1) {
291 return rhs._col1;
292 } else if constexpr (I == 2) {
293 return rhs._col2;
294 } else if constexpr (I == 3) {
295 return rhs._col3;
296 } else {
297 hi_static_no_default();
298 }
299 }
300
301 [[nodiscard]] constexpr bool holds_invariant() const noexcept
302 {
303 return true;
304 }
305
311 [[nodiscard]] constexpr f32x4 operator*(f32x4 const& rhs) const noexcept
312 {
313 return {_col0 * rhs.xxxx() + _col1 * rhs.yyyy() + _col2 * rhs.zzzz() + _col3 * rhs.wwww()};
314 }
315
316
319 [[nodiscard]] friend constexpr matrix3 transpose(matrix3 const& rhs) noexcept
320 {
321 auto tmp = transpose(rhs._col0, rhs._col1, rhs._col2, rhs._col3);
322 return matrix3{std::get<0>(tmp), std::get<1>(tmp), std::get<2>(tmp), std::get<3>(tmp)};
323 }
324
358 template<char DstX, char DstY, char DstZ, char DstW = 'w'>
359 [[nodiscard]] friend constexpr matrix3 reflect(matrix3 const& rhs) noexcept
360 {
362 }
363
369 [[nodiscard]] constexpr friend bool operator==(matrix3 const& lhs, matrix3 const& rhs) noexcept
370 {
371 return equal(lhs._col0, rhs._col0) and equal(lhs._col1, rhs._col1) and equal(lhs._col2, rhs._col2) and
372 equal(lhs._col3, rhs._col3);
373 }
374
377 [[nodiscard]] constexpr matrix3 operator~() const
378 {
379 // rc
380 // var s0 : Number = i00 * i11 -
381 // i10 * i01;
382 // var c0 : Number = i20 * i31 -
383 // i30 * i21;
384 hilet s0c0 = _col0 * _col1.yxwz();
385
386 // var s1 : Number = i00 * i12 -
387 // i10 * i02;
388 // var c1 : Number = i20 * i32 -
389 // i30 * i22;
390 hilet s1c1 = _col0 * _col2.yxwz();
391 hilet s0c0s1c1 = hsub(s0c0, s1c1);
392
393 // var s2 : Number = i00 * i13 -
394 // i10 * i03;
395 // var c2 : Number = i20 * i33 -
396 // i30 * i23;
397 hilet s2c2 = _col0 * _col3.yxwz();
398
399 // var s3 : Number = i01 * i12 -
400 // i11 * i02;
401 // var c3 : Number = i21 * i32 -
402 // i31 * i22;
403 hilet s3c3 = _col1 * _col2.yxwz();
404 hilet s2c2s3c3 = hsub(s2c2, s3c3);
405
406 // var s4 : Number = i01 * i13 -
407 // i11 * i03;
408 // var c4 : Number = i21 * i33 -
409 // i31 * i23;
410 hilet s4c4 = _col1 * _col3.yxwz();
411
412 // var s5 : Number = i02 * i13 -
413 // i12 * i03;
414 // var c5 : Number = i22 * i33 -
415 // i32 * i23;
416 hilet s5c5 = _col2 * _col3.yxwz();
417 hilet s4c4s5c5 = hsub(s4c4, s5c5);
418
419 // det = (s0 * c5 +
420 // -s1 * c4 +
421 // s2 * c3 +
422 // s3 * c2 +
423 // -s4 * c1 +
424 // s5 * c0)
425 hilet s0123 = s0c0s1c1.xz00() + s2c2s3c3._00xz();
426 hilet s45__ = s4c4s5c5.xz00();
427
428 hilet c5432 = s4c4s5c5.wy00() + s2c2s3c3._00wy();
429 hilet c10__ = s0c0s1c1.wy00();
430
433
435 hilet det_sum1 = hadd(det_sum0, det_sum0);
436 hilet det = hadd(det_sum1, det_sum1).xxxx();
437
438 if (det.x() == 0.0f) {
439 throw std::domain_error("Divide by zero");
440 }
441
442 hilet invdet = rcp(det);
443
444 hilet t = transpose(*this);
445
446 // rc rc rc rc
447 // m.i00 := (i11 * c5 + i12 * -c4 + i13 * c3) * invdet;
448 // m.i10 := (i10 * -c5 + i12 * c2 + i13 * -c1) * invdet;
449 // m.i20 := (i10 * c4 + i11 * -c2 + i13 * c0) * invdet;
450 // m.i30 := (i10 * -c3 + i11 * c1 + i12 * -c0) * invdet;
451 auto tmp_c5543 = neg<0b1010>(c5432.xxyz());
452 auto tmp_c4221 = neg<0b0101>(c5432.yww0() + c10__._000x());
453 auto tmp_c3100 = neg<0b1010>(c5432.z000() + c10__._0xyy());
454 hilet inv_col0 = ((t._col1.yxxx() * tmp_c5543) + (t._col1.zzyy() * tmp_c4221) + (t._col1.wwwz() * tmp_c3100)) * invdet;
455
456 // m.i01 := (i01 * -c5 + i02 * c4 + i03 * -c3) * invdet;
457 // m.i11 := (i00 * c5 + i02 * -c2 + i03 * c1) * invdet;
458 // m.i21 := (i00 * -c4 + i01 * c2 + i03 * -c0) * invdet;
459 // m.i31 := (i00 * c3 + i01 * -c1 + i02 * c0) * invdet;
463 hilet inv_col1 = ((t._col0.yxxx() * tmp_c5543) + (t._col0.zzyy() * tmp_c4221) + (t._col0.wwwz() * tmp_c3100)) * invdet;
464
465 // m.i02 := (i31 * s5 + i32 * -s4 + i33 * s3) * invdet;
466 // m.i12 := (i30 * -s5 + i32 * s2 + i33 * -s1) * invdet;
467 // m.i22 := (i30 * s4 + i31 * -s2 + i33 * s0) * invdet;
468 // m.i32 := (i30 * -s3 + i31 * s1 + i32 * -s0) * invdet;
469 auto tmp_s5543 = neg<0b1010>(s45__.yyx0() + s0123._000w());
470 auto tmp_s4221 = neg<0b0101>(s45__.x000() + s0123._0zzy());
471 auto tmp_s3100 = neg<0b1010>(s0123.wyxx());
472 hilet inv_col2 = ((t._col3.yxxx() * tmp_s5543) + (t._col3.zzyy() * tmp_s4221) + (t._col3.wwwz() * tmp_s3100)) * invdet;
473
474 // m.i03 := (i21 * -s5 + i22 * s4 + i23 * -s3) * invdet;
475 // m.i13 := (i20 * s5 + i22 * -s2 + i23 * s1) * invdet;
476 // m.i23 := (i20 * -s4 + i21 * s2 + i23 * -s0) * invdet;
477 // m.i33 := (i20 * s3 + i21 * -s1 + i22 * s0) * invdet;
481 hilet inv_col3 = ((t._col2.yxxx() * tmp_s5543) + (t._col2.zzyy() * tmp_s4221) + (t._col2.wwwz() * tmp_s3100)) * invdet;
482
484 }
485
486private:
487 f32x4 _col0;
488 f32x4 _col1;
489 f32x4 _col2;
490 f32x4 _col3;
491
492 template<char Axis>
493 [[nodiscard]] constexpr static f32x4 reflect_column() noexcept
494 {
495 if constexpr (Axis == 'x') {
496 return f32x4{1.0f, 0.0f, 0.0f, 0.0f};
497 } else if constexpr (Axis == 'X') {
498 return f32x4{-1.0f, 0.0f, 0.0f, 0.0f};
499 } else if constexpr (Axis == 'y') {
500 return f32x4{0.0f, 1.0f, 0.0f, 0.0f};
501 } else if constexpr (Axis == 'Y') {
502 return f32x4{0.0f, -1.0f, 0.0f, 0.0f};
503 } else if constexpr (Axis == 'z') {
504 return f32x4{0.0f, 0.0f, 1.0f, 0.0f};
505 } else if constexpr (Axis == 'Z') {
506 return f32x4{0.0f, 0.0f, -1.0f, 0.0f};
507 } else if constexpr (Axis == 'w') {
508 return f32x4{0.0f, 0.0f, 0.0f, 1.0f};
509 } else if constexpr (Axis == 'W') {
510 return f32x4{0.0f, 0.0f, 0.0f, -1.0f};
511 } else {
512 hi_static_no_default();
513 }
514 }
515};
516
517
518
519}} // namespace hi::v1
@ other
The gui_event does not have associated data.
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
@ one
The number was one, and this means something in the current language.
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:29
Horizontal/Vertical alignment combination.
Definition alignment.hpp:242
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix2.hpp:27
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:229
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:30
friend constexpr matrix3 transpose(matrix3 const &rhs) noexcept
Matrix transpose.
Definition matrix3.hpp:319
constexpr f32x4 operator*(f32x4 const &rhs) const noexcept
Transform a f32x4 numeric array by the matrix.
Definition matrix3.hpp:311
friend constexpr matrix3 reflect(matrix3 const &rhs) noexcept
Reflect axis of a matrix.
Definition matrix3.hpp:359
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:55
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:140
constexpr matrix3(matrix2 const &other) noexcept
Copy-construct a matrix from a smaller matrix.
Definition matrix3.hpp:163
constexpr matrix3(rotate3 const &rhs) noexcept
Convert quaternion to matrix.
Definition matrix3.hpp:207
constexpr friend bool operator==(matrix3 const &lhs, matrix3 const &rhs) noexcept
Compare two matrices potentially of different dimensions.
Definition matrix3.hpp:369
constexpr matrix3() noexcept
Constructs an identity matrix.
Definition matrix3.hpp:39
friend constexpr f32x4 & get(matrix3 &rhs) noexcept
Get a column.
Definition matrix3.hpp:286
constexpr matrix3 operator~() const
Invert matrix.
Definition matrix3.hpp:377
friend constexpr f32x4 const & get(matrix3 const &rhs) noexcept
Get a column.
Definition matrix3.hpp:265
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:104
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:254
constexpr matrix3(vector3 col0, vector3 col1, vector3 col2, vector3 col3=vector3{}) noexcept
Construct a matrix from four vectors.
Definition matrix3.hpp:67
Definition rotate3.hpp:12
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector3.hpp:20