27 using sequence_size = sequence_size_t < t_iSize >;
28 using BASE_COORDINATE = COORDINATE;
29 using UNIT_TYPE = COORDINATE;
32 COORDINATE m_coordinatea[t_iSize];
35 static constexpr bool IS_MATRIX =
false;
36 static constexpr ::collection::count SIZE = t_iSize;
39 constexpr sequence_type()
53 constexpr sequence_type(UNIT_TYPE n)
70 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 2,
int> = 0 >
71 constexpr sequence_type(
const sequence_type < NUMBER1, 2 > & sequence)
73 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
74 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
78 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 3,
int> = 0 >
79 constexpr sequence_type(
const sequence_type < NUMBER1, 3 > & sequence)
81 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
82 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
83 m_coordinatea[2] = (UNIT_TYPE) sequence.m_coordinatea[2];
87 template < primitive_number NUMBER1, ::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0 >
88 constexpr sequence_type(
const sequence_type < NUMBER1, 4 > & sequence)
90 m_coordinatea[0] = (UNIT_TYPE) sequence.m_coordinatea[0];
91 m_coordinatea[1] = (UNIT_TYPE) sequence.m_coordinatea[1];
92 m_coordinatea[2] = (UNIT_TYPE) sequence.m_coordinatea[2];
93 m_coordinatea[3] = (UNIT_TYPE) sequence.m_coordinatea[3];
101 template < ::collection::count S = SIZE, std::enable_if_t<S == 2,
int> = 0 >
102 constexpr sequence_type(COORDINATE coordinate0, COORDINATE coordinate1)
104 m_coordinatea[0] = coordinate0;
105 m_coordinatea[1] = coordinate1;
109 template <::collection::count S = SIZE, std::enable_if_t<S == 3,
int> = 0>
110 constexpr sequence_type(COORDINATE coordinate0, COORDINATE coordinate1,
111 COORDINATE coordinate2)
113 m_coordinatea[0] = coordinate0;
114 m_coordinatea[1] = coordinate1;
115 m_coordinatea[2] = coordinate2;
119 template <::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0>
120 constexpr sequence_type(
121 COORDINATE coordinate0, COORDINATE coordinate1,
122 COORDINATE coordinate2, COORDINATE coordinate3)
124 m_coordinatea[0] = coordinate0;
125 m_coordinatea[1] = coordinate1;
126 m_coordinatea[2] = coordinate2;
127 m_coordinatea[3] = coordinate3;
131 constexpr ::collection::count get_size()
const {
return SIZE; }
132 constexpr ::collection::count get_count()
const {
return this->get_size(); }
135 constexpr COORDINATE & set_coordinate(::collection::index i, COORDINATE coordinate)
138 return m_coordinatea[i] = coordinate;
143 constexpr COORDINATE coordinate(::collection::index i)
const
146 return m_coordinatea[i];
151 constexpr COORDINATE & coordinate(::collection::index i)
154 return m_coordinatea[i];
159 void set_all(COORDINATE coordinate)
162 for (::collection::count i = 0; i < SIZE; ++i)
165 m_coordinatea[i] = coordinate;
171 bool is_all(COORDINATE coordinate)
const
174 for (::collection::count i = 0; i < SIZE; ++i)
177 if(m_coordinatea[i] != coordinate)
193 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2,
int> = 0 >
194 inline
void add2(const sequence_type & a)
199 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2,
int> = 0 >
200 inline
void sub2(const sequence_type & a)
205 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2,
int> = 0 >
206 inline
void mul2(UNIT_TYPE n)
211 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2,
int> = 0 >
212 inline
void set2(UNIT_TYPE a, UNIT_TYPE b)
218 template < ::collection::count S = SIZE, std::enable_if_t<S <= 2,
int> = 0 >
219 static inline
void mix2(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
221 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
222 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
226 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3,
int> = 0 >
227 inline
void add3(const sequence_type & a)
233 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3,
int> = 0 >
234 inline
void sub3(const sequence_type & a)
240 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3,
int> = 0 >
241 inline
void mul3(UNIT_TYPE n)
247 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3,
int> = 0 >
248 inline
void set3(UNIT_TYPE a, UNIT_TYPE b, UNIT_TYPE c)
255 template < ::collection::count S = SIZE, std::enable_if_t<S <= 3,
int> = 0 >
256 static inline
void mix3(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
258 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
259 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
260 c.c() = a.c()*((UNIT_TYPE)1.0 - t) + b.c()*t;
264 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4,
int> = 0 >
265 inline
void add4(const sequence_type & q)
272 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4,
int> = 0 >
273 inline
void sub4(const sequence_type & q)
280 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4,
int> = 0 >
281 inline
void mul4(UNIT_TYPE n)
288 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4,
int> = 0 >
289 inline
void set4(UNIT_TYPE a, UNIT_TYPE b, UNIT_TYPE c, UNIT_TYPE d)
297 template < ::collection::count S = SIZE, std::enable_if_t<S <= 4,
int> = 0 >
298 static inline
void mix4(const sequence_type &a, const sequence_type &b, UNIT_TYPE t, sequence_type &c)
300 c.a() = a.a()*((UNIT_TYPE)1.0 - t) + b.a()*t;
301 c.b() = a.b()*((UNIT_TYPE)1.0 - t) + b.b()*t;
302 c.c() = a.c()*((UNIT_TYPE)1.0 - t) + b.c()*t;
303 c.d() = a.d()*((UNIT_TYPE)1.0 - t) + b.d()*t;
307 sequence_type operator-() const
309 sequence_type result;
310 for (::collection::count i = 0; i < SIZE; ++i)
311 result[i] = -m_coordinatea[i];
316 friend sequence_type operator+(const sequence_type& a, const sequence_type& b)
318 sequence_type result;
319 for (::collection::count i = 0; i < SIZE; ++i)
320 result[i] = a.m_coordinatea[i] + b.m_coordinatea[i];
324 sequence_type& operator+=(const sequence_type& a) {
325 for (::collection::count i = 0; i < SIZE; ++i)
326 m_coordinatea[i] += a.m_coordinatea[i];
330 friend sequence_type operator-(const sequence_type& a, const sequence_type& b) {
331 sequence_type result;
332 for (::collection::count i = 0; i < SIZE; ++i)
333 result[i] = a.m_coordinatea[i] - b.m_coordinatea[i];
337 sequence_type& operator-=(const sequence_type& a) {
338 for (::collection::count i = 0; i < SIZE; ++i)
339 m_coordinatea[i] -= a.m_coordinatea[i];
343 friend sequence_type operator *(const sequence_type& a, const sequence_type& b) {
344 sequence_type result;
345 for (::collection::count i = 0; i < SIZE; ++i)
346 result[i] = a.m_coordinatea[i] * b.m_coordinatea[i];
350 template < primitive_number NUMBER1 >
351 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > operator *(NUMBER1 n)
const
353 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > result;
354 for (::collection::count i = 0; i < SIZE; ++i)
355 result[i] = (largest_number < UNIT_TYPE, NUMBER1 >) (this->m_coordinatea[i] * n);
361 for (::collection::count i = 0; i < SIZE; ++i)
362 m_coordinatea[i] *= a.m_coordinatea[i];
369 for (::collection::count i = 0; i < SIZE; ++i)
370 result[i] = a.m_coordinatea[i] / b.m_coordinatea[i];
375 template < primitive_number NUMBER1 >
376 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > operator /(NUMBER1 n)
const
378 sequence_type < largest_number < UNIT_TYPE, NUMBER1 >, SIZE > result;
379 for (::collection::count i = 0; i < SIZE; ++i)
380 result[i] = (largest_number < UNIT_TYPE, NUMBER1 >) (this->m_coordinatea[i] / n);
386 for (::collection::count i = 0; i < SIZE; ++i)
387 m_coordinatea[i] /= a.m_coordinatea[i];
392 for (::collection::count i = 0; i < SIZE; ++i) {
393 if (m_coordinatea[i] != a.m_coordinatea[i])
400 template <
typename PREDICATE >
401 bool is_every(PREDICATE predicate)
const
404 for (::collection::count i = 0; i < SIZE; ++i)
407 if (!predicate(m_coordinatea[i]))
421 bool is_empty()
const
424 return is_every([](
auto coordinate) {
return coordinate == COORDINATE{}; });
437 bool is_all_set()
const
440 return is_every([](
auto coordinate) {
return coordinate != COORDINATE{}; });
445 bool is_all_positive()
const
448 return is_every([](
auto coordinate) {
return coordinate > COORDINATE{}; });
453 template <
typename PREDICATE >
459 for (::collection::count i = 0; i < SIZE; ++i)
462 if (predicate(m_coordinatea[i]))
465 vector[i] = m_coordinatea[i];
471 vector[i] = vectorOther.m_coordinatea[i];
485 return prefer_self_coordinate_if(vectorOther, [](
auto coordinate) {
return coordinate != 0; });
493 return prefer_self_coordinate_if(vectorOther, [](
auto coordinate) {
return coordinate > COORDINATE{}; });
498 template <
typename PREDICATE,
typename SOURCE_PREDICATE >
499 sequence_type pred_prefer_self_coordinate_if(PREDICATE predicate, SOURCE_PREDICATE sourcepredicate)
const
502 if (is_every(predicate))
509 auto vectorOther = sourcepredicate();
511 return prefer_self_coordinate_if(vectorOther, predicate);
516 template <
typename SOURCE_PREDICATE >
517 sequence_type pred_prefer_self_coordinate_if_set(SOURCE_PREDICATE sourcepredicate)
const
520 return pred_prefer_self_coordinate_if([](
auto coordinate) {
return coordinate != COORDINATE{}; }, sourcepredicate);
525 template <
typename SOURCE_PREDICATE >
526 sequence_type pred_prefer_self_coordinate_if_positive(SOURCE_PREDICATE sourcepredicate)
const
529 return pred_prefer_self_coordinate_if([](
auto coordinate) {
return coordinate > COORDINATE{}; }, sourcepredicate);
535 constexpr bool operator!=(
const sequence_type& a)
const {
return !operator==(a); }
537 constexpr const COORDINATE& operator[](::collection::count i)
const {
return m_coordinatea[i]; }
539 constexpr COORDINATE& operator[](::collection::count i) {
return m_coordinatea[i]; }
541 template <::collection::count S = SIZE, std::enable_if_t<(S >= 1),
int> = 0>
542 constexpr const COORDINATE& a()
const {
return m_coordinatea[0]; }
543 template <::collection::count S = SIZE, std::enable_if_t<(S >= 1),
int> = 0>
544 COORDINATE& a() {
return m_coordinatea[0]; }
546 template <::collection::count S = SIZE, std::enable_if_t<(S >= 2),
int> = 0>
547 constexpr const COORDINATE& b()
const {
return m_coordinatea[1]; }
548 template <::collection::count S = SIZE, std::enable_if_t<(S >= 2),
int> = 0>
549 COORDINATE& b() {
return m_coordinatea[1]; }
551 template <::collection::count S = SIZE, std::enable_if_t<(S >= 3),
int> = 0>
552 constexpr const COORDINATE& c()
const {
return m_coordinatea[2]; }
553 template <::collection::count S = SIZE, std::enable_if_t<(S >= 3),
int> = 0>
554 COORDINATE& c() {
return m_coordinatea[2]; }
556 template <::collection::count S = SIZE, std::enable_if_t<(S >= 4),
int> = 0>
557 constexpr const COORDINATE& d()
const {
return m_coordinatea[3]; }
558 template <::collection::count S = SIZE, std::enable_if_t<(S >= 4),
int> = 0>
559 COORDINATE& d() {
return m_coordinatea[3]; }
562 template <::collection::count S = SIZE, std::enable_if_t<(S == 2),
int> = 0>
563 COORDINATE dot_with_left_perpendicular_of(
const sequence_type & b)
566 return (this->b() * b.a()) - (this->a() * b.b());
571 template <::collection::count S = SIZE, std::enable_if_t<(S == 2),
int> = 0>
575 return ::std::atan2(this->dot_with_left_perpendicular_of(b), this->dot(b));
585 for (::collection::count i = 0; i < SIZE; ++i)
588 result.m_coordinatea[i] = ::maximum(m_coordinatea[i], vector.m_coordinatea[i]);
601 for (::collection::count i = 0; i < SIZE; ++i)
604 result.m_coordinatea[i] = ::minimum(m_coordinatea[i], vector.m_coordinatea[i]);
613 UNIT_TYPE minimum()
const
616 UNIT_TYPE nMinimum = this->m_coordinatea[0];
618 for (::collection::count i = 1; i < SIZE; ++i)
621 nMinimum = ::minimum(nMinimum, this->m_coordinatea[i]);
630 UNIT_TYPE maximum()
const
633 UNIT_TYPE nMaximum = this->m_coordinatea[0];
635 for (::collection::count i = 1; i < SIZE; ++i)
638 nMaximum = ::maximum(nMaximum, this->m_coordinatea[i]);
650 COORDINATE result = m_coordinatea[0] * vector.m_coordinatea[0];
652 for (::collection::count i = 1; i < SIZE; ++i)
655 result += m_coordinatea[i] * vector.m_coordinatea[i];
664 COORDINATE squared_modulus()
const
672 COORDINATE modulus()
const
675 return ::sqrt(squared_modulus());
683 return *
this / modulus();
688 const UNIT_TYPE & get_dimension(enum_orientation eorientation)
const
691 return this->m_coordinatea[eorientation];
695 UNIT_TYPE & get_dimension(enum_orientation eorientation)
698 return this->m_coordinatea[eorientation];
703 template < ::collection::count S = SIZE, std::enable_if_t<S == 2,
int> = 0 >
704 const UNIT_TYPE & get_normal_dimension(enum_orientation eorientation)
const
707 return this->m_coordinatea[orthogonal2_index_of(eorientation)];
712 template < ::collection::count S = SIZE, std::enable_if_t<S == 2,
int> = 0 >
713 UNIT_TYPE & get_normal_dimension(enum_orientation eorientation)
716 return this->m_coordinatea[orthogonal2_index_of(eorientation)];
721 inline UNIT_TYPE & set_dimension(enum_orientation eorientation, UNIT_TYPE l)
noexcept
724 return this->m_coordinatea[eorientation] = l;
729 inline UNIT_TYPE & set_orthogonal_dimension(enum_orientation eorientation, UNIT_TYPE l)
noexcept
732 return this->m_coordinatea[orthogonal2_index_of(eorientation)] = l;
993template <
typename Value_, ::collection::count Size_>
struct Matrix {
994 static constexpr bool IsNanoGUI =
true;
995 static constexpr bool IsMatrix =
true;
997 using COORDINATE = Value_;
998 static constexpr ::collection::count SIZE = Size_;
1002 explicit Matrix(COORDINATE s) {
1003 ::memory_set(m, 0,
sizeof(COORDINATE) * SIZE * SIZE);
1004 for (::collection::count i = 0; i < SIZE; ++i)
1008 friend Matrix operator*(
const Matrix& a,
const Matrix& b) {
1010 for (::collection::count i = 0; i < SIZE; ++i) {
1011 for (::collection::count j = 0; j < SIZE; ++j) {
1012 COORDINATE accum = 0;
1013 for (::collection::count k = 0; k < SIZE; ++k)
1014 accum += a.m[k][i] * b.m[j][k];
1023 ::memory_set(result.m, 0,
sizeof(COORDINATE) * SIZE * SIZE);
1024 for (::collection::count i = 0; i < SIZE; ++i)
1025 result.m[i][i] = i < SIZE - 1 ? m_coordinatea[i] : 1;
1031 ::memory_set(result.m, 0,
sizeof(COORDINATE) * SIZE * SIZE);
1032 for (::collection::count i = 0; i < SIZE; ++i)
1033 result.m[i][i] = m_coordinatea[i];
1039 ::memory_set(result.m, 0,
sizeof(COORDINATE) * SIZE * SIZE);
1040 for (::collection::count i = 0; i < SIZE; ++i) {
1041 result.m[i][i] = 1.f;
1043 result.m[SIZE - 1][i] = m_coordinatea[i];
1049 template <::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0>
1053 COORDINATE s = ::sin(angle);
1054 COORDINATE c = ::cos(angle);
1055 COORDINATE t = 1 - c;
1059 result.m[0][0] = c + axis.a() * axis.a() * t;
1060 result.m[1][1] = c + axis.b() * axis.b() * t;
1061 result.m[2][2] = c + axis.c() * axis.c() * t;
1063 COORDINATE tmp1 = axis.a() * axis.b() * t;
1064 COORDINATE tmp2 = axis.c() * s;
1066 result.m[0][1] = tmp1 + tmp2;
1067 result.m[1][0] = tmp1 - tmp2;
1069 tmp1 = axis.a() * axis.c() * t;
1070 tmp2 = axis.b() * s;
1071 result.m[0][2] = tmp1 - tmp2;
1072 result.m[2][0] = tmp1 + tmp2;
1074 tmp1 = axis.b() * axis.c() * t;
1075 tmp2 = axis.a() * s;
1076 result.m[1][2] = tmp1 + tmp2;
1077 result.m[2][1] = tmp1 - tmp2;
1084 template <::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0>
1085 static Matrix perspective(COORDINATE fov, COORDINATE near_, COORDINATE far_, COORDINATE aspect = 1.f)
1088 COORDINATE recip = 1 / (near_ - far_);
1089 COORDINATE c = 1 / ::tan(.5f * fov);
1093 trafo.m[3][2] = 2.f * near_ * far_ * recip;
1094 trafo.m[2][3] = -1.f;
1099 template <::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0>
1100 static Matrix ortho(COORDINATE left, COORDINATE right,
1101 COORDINATE bottom, COORDINATE top,
1102 COORDINATE near_, COORDINATE far_)
1105 COORDINATE rl = 1 / (right - left);
1106 COORDINATE tb = 1 / (top - bottom);
1107 COORDINATE fn = 1 / (far_ - near_);
1111 result.m[0][0] = 2 * rl;
1112 result.m[1][1] = 2 * tb;
1113 result.m[2][2] = -2 * fn;
1115 result.m[3][0] = -(right + left) * rl;
1116 result.m[3][1] = -(top + bottom) * tb;
1117 result.m[3][2] = -(far_ + near_) * fn;
1122 template <::collection::count S = SIZE, std::enable_if_t<S == 4,
int> = 0>
1128 auto dir = normalize(target - origin);
1129 auto left = normalize(cross(dir, up));
1130 auto new_up = cross(left, dir);
1134 result.m[0][0] = left.a();
1135 result.m[0][1] = left.b();
1136 result.m[0][2] = left.c();
1137 result.m[1][0] = new_up.a();
1138 result.m[1][1] = new_up.b();
1139 result.m[1][2] = new_up.c();
1140 result.m[2][0] = dir.a();
1141 result.m[2][1] = dir.b();
1142 result.m[2][2] = dir.c();
1143 result.m[3][0] = -dot(left, origin);
1144 result.m[3][1] = -dot(new_up, origin);
1145 result.m[3][2] = -dot(dir, origin);
1146 result.m[3][3] = 1.f;
1150 COORDINATE m[SIZE][SIZE];