181 class Matrix :
public Vector<t_row_dims, Vector<t_col_dims, t_type>>
185 : Vector<t_row_dims, Vector<t_col_dims, t_type>>()
187 constexpr explicit Matrix(
const t_type diagonal)
188 : Vector<t_row_dims, Vector<t_col_dims, t_type>>(Vector<t_col_dims, t_type>(0))
190 for (
uint01 i = 0; i <
getMin(t_row_dims, t_col_dims); i++)
192 (*this)[i][i] = diagonal;
197 const t_type n00,
const t_type n10,
198 const t_type n01,
const t_type n11)
199 : Vector<2, Vector<2, t_type>>(
200 Vector<2, t_type>(n00, n10)
201 , Vector<2, t_type>(n01, n11))
203 static_assert(t_row_dims == 2 && t_col_dims == 2,
"Bad Transform Constructor, should be 2x2");
206 const t_type n00,
const t_type n10,
const t_type n20,
207 const t_type n01,
const t_type n11,
const t_type n21,
208 const t_type n02,
const t_type n12,
const t_type n22)
209 : Vector<3, Vector<3, t_type>>(
210 Vector<3, t_type>(n00, n10, n20)
211 , Vector<3, t_type>(n01, n11, n21)
212 , Vector<3, t_type>(n02, n12, n22))
214 static_assert(t_row_dims == 3 && t_col_dims == 3,
"Bad Transform Constructor, should be 3x3");
217 const t_type n00,
const t_type n10,
const t_type n20,
const t_type n30,
218 const t_type n01,
const t_type n11,
const t_type n21,
const t_type n31,
219 const t_type n02,
const t_type n12,
const t_type n22,
const t_type n32,
220 const t_type n03,
const t_type n13,
const t_type n23,
const t_type n33)
221 : Vector<4, Vector<4, t_type>>(
222 Vector<4, t_type>(n00, n10, n20, n30)
223 , Vector<4, t_type>(n01, n11, n21, n31)
224 , Vector<4, t_type>(n02, n12, n22, n32)
225 , Vector<4, t_type>(n03, n13, n23, n33))
227 static_assert(t_row_dims == 4 && t_col_dims == 4,
"Bad Transform Constructor, should be 4x4");
229 template<
class t_angle_type>
230 constexpr Matrix(
const Vector<t_row_dims - 1, t_type>& offset,
const Vector<3,
Angle<t_angle_type>>& orientation,
const Vector<t_row_dims - 1, t_type>& scale)
231 : Vector<t_row_dims, Vector<t_col_dims, t_type>>(Vector<t_col_dims, t_type>(0))
234 *
this = RotationMatrix(orientation);
236 (*this)[t_row_dims - 1][0] = offset[X];
237 if constexpr (t_col_dims >= 2)
238 (*
this)[t_row_dims - 1][1] = offset[Y];
239 if constexpr (t_col_dims >= 3)
240 (*
this)[t_row_dims - 1][2] = offset[Z];
242 *
this = this->scale(scale);
244 constexpr Matrix(
const Vector<t_row_dims* t_col_dims, t_type>& vector)
246 memcpy(
this, &vector,
sizeof(Vector<t_row_dims* t_col_dims, t_type>));
248 constexpr Matrix(
const Vector<t_row_dims, Vector<t_col_dims, t_type>>& vector)
249 : Vector<t_row_dims, Vector<t_col_dims, t_type>>(vector)
251 constexpr Matrix(
const Matrix& mat) =
default;
253 template<
class t_new_type>
254 [[nodiscard]]
constexpr decltype(
auto)
as()
const
256 if constexpr (std::is_same_v<t_new_type, t_type>)
258 return static_cast<const Matrix<t_type>&
>(*this);
262 Matrix<t_new_type> mat;
263 for (
uint01 row = 0; row < t_row_dims; ++row)
265 for (
uint01 col = 0; col < t_col_dims; ++col)
273 template<
class t_new_type, u
int01 t_new_row_dims, u
int01 t_new_col_dims>
274 [[nodiscard]]
constexpr decltype(
auto)
as()
const
276 if constexpr (t_new_row_dims == t_row_dims && t_new_col_dims == t_col_dims && std::is_same_v<t_new_type, t_type>)
278 return static_cast<const Matrix<t_type>&
>(*this);
282 Matrix<t_new_type, t_new_row_dims, t_new_col_dims> mat;
283 for (
uint01 row = 0; row <
getMin(t_row_dims, t_new_row_dims); ++row)
285 for (
uint01 col = 0; col <
getMin(t_col_dims, t_new_col_dims); ++col)
293 template<u
int01 t_i0, u
int01 t_i1, u
int01 t_j0, u
int01 t_j1>
294 [[nodiscard]]
constexpr Matrix<t_type, t_i1 - t_i0 + 1, t_j1 - t_j0 + 1> subMatrix()
const
296 Matrix<t_type, t_i1 - t_i0 + 1, t_j1 - t_j0 + 1> mat;
297 for (
uint01 i = t_i0; i <= t_i1; i++)
299 for (
uint01 j = t_j0; j <= t_j1; j++)
300 mat[i - t_i0][j - t_j0] = (*
this)[i][j];
304 template<u
int01 t_j0, u
int01 t_j1, u
int01 t_i_size>
305 [[nodiscard]]
constexpr Matrix<t_type, t_i_size, t_j1 - t_j0 + 1> subMatrix(
const Vector<t_i_size, uint01>& r)
const
307 Matrix<t_type, t_i_size, t_j1 - t_j0 + 1> mat;
308 for (
uint01 i = 0; i < t_i_size; i++)
310 for (
uint01 j = t_j0; j <= t_j1; j++)
312 mat[i][j - t_j0] = (*this)[r[i]][j];
318 [[nodiscard]]
static constexpr Matrix<t_type> OffsetMatrix(
const Vector<3, t_type>& translation)
320 Matrix<t_type> mat(1);
321 mat[t_row_dims - 1][0] = translation[X];
322 if constexpr (t_col_dims >= 2)
323 mat[t_row_dims - 1][1] = translation[Y];
324 if constexpr (t_col_dims >= 3)
325 mat[t_row_dims - 1][2] = translation[Z];
328 [[nodiscard]]
static constexpr Matrix<t_type> ScalerMatrix(t_type scale)
330 Matrix<t_type> mat(1);
332 if constexpr (t_col_dims >= 2 && t_row_dims >= 2)
334 if constexpr (t_col_dims >= 3 && t_row_dims >= 3)
338 [[nodiscard]]
static constexpr Matrix<t_type> ScalerMatrix(
const Vector<2, t_type>& scale)
341 mat[0][0] = scale[X];
342 if constexpr (t_col_dims >= 2 && t_row_dims >= 2)
343 mat[1][1] = scale[Y];
346 [[nodiscard]]
static constexpr Matrix<t_type> ScalerMatrix(
const Vector<3, t_type>& scale)
348 Matrix<t_type> mat(1);
349 mat[0][0] = scale[X];
350 if constexpr (t_col_dims >= 2 && t_row_dims >= 2)
351 mat[1][1] = scale[Y];
352 if constexpr (t_col_dims >= 3 && t_row_dims >= 3)
353 mat[2][2] = scale[Z];
357 static constexpr Matrix<t_type> SwapAxes(
uint01 a,
uint01 b)
360 static_assert(t_row_dims == t_col_dims,
"needs to be same size");
361 lib_assert(a < t_row_dims && b < t_col_dims,
"dims too high for matrix");
370 template<
class t_angle_type>
371 static constexpr Matrix<t_type> RotationMatrix(
const Vector<3,
Angle<t_angle_type>>& orientation)
373 t_type ch = t_type(1);
374 t_type sh = t_type(0);
375 t_type ca = t_type(1);
376 t_type sa = t_type(0);
377 t_type cb = t_type(1);
378 t_type sb = t_type(0);
381 ch =
cos(orientation[
YAW]);
382 sh =
sin(orientation[
YAW]);
395 t_type m00 = ch * ca;
396 t_type m01 = ch * sa * sb - sh * cb;
397 t_type m02 = ch * sa * cb + sh * sb;
398 t_type m10 = sh * ca;
399 t_type m11 = sh * sa * sb + ch * cb;
400 t_type m12 = sh * sa * cb - ch * sb;
402 t_type m21 = ca * sb;
403 t_type m22 = ca * cb;
404 return Matrix<t_type>(
410 template<
class t_angle_type>
411 static constexpr Matrix<t_type> RotationMatrix(
const Angle<t_angle_type>& phi,
const Vector<3, t_type>& axis)
415 const t_type x = axis[X];
416 const t_type y = axis[Y];
417 const t_type z = axis[Z];
418 return Matrix<t_type>(
419 (cos_val + x * x * (1 - cos_val)), (z * sin_val + y * x * (1 - cos_val)), (-y * sin_val + z * x * (1 - cos_val)), 0
420 , (-z * sin_val + x * y * (1 - cos_val)), (cos_val + y * y * (1 - cos_val)), (x * sin_val + z * y * (1 - cos_val)), 0
421 , (y * sin_val + x * z * (1 - cos_val)), (-x * sin_val + y * z * (1 - cos_val)), (cos_val + z * z * (1 - cos_val)), 0
424 [[nodiscard]]
constexpr t_type determinant()
const
426 static_assert(t_col_dims == t_row_dims,
"Rows and columns must be equal for determinate");
430 return (*
this)[0][0];
432 return (*
this)[0][0] * (*this)[1][1] - (*this)[1][0] * (*this)[0][1];
435 +(*this)[0][0] * ((*this)[1][1] * (*this)[2][2] - (*this)[2][1] * (*this)[1][2])
436 - (*
this)[1][0] * ((*this)[0][1] * (*this)[2][2] - (*this)[2][1] * (*this)[0][2])
437 + (*
this)[2][0] * ((*this)[0][1] * (*this)[1][2] - (*this)[1][1] * (*this)[0][2]);
440 t_type SubFactor00 = (*this)[2][2] * (*this)[3][3] - (*this)[3][2] * (*this)[2][3];
441 t_type SubFactor01 = (*this)[2][1] * (*this)[3][3] - (*this)[3][1] * (*this)[2][3];
442 t_type SubFactor02 = (*this)[2][1] * (*this)[3][2] - (*this)[3][1] * (*this)[2][2];
443 t_type SubFactor03 = (*this)[2][0] * (*this)[3][3] - (*this)[3][0] * (*this)[2][3];
444 t_type SubFactor04 = (*this)[2][0] * (*this)[3][2] - (*this)[3][0] * (*this)[2][2];
445 t_type SubFactor05 = (*this)[2][0] * (*this)[3][1] - (*this)[3][0] * (*this)[2][1];
446 Vector<4, t_type> DetCof(
447 +((*
this)[1][1] * SubFactor00 - (*
this)[1][2] * SubFactor01 + (*
this)[1][3] * SubFactor02),
448 -((*
this)[1][0] * SubFactor00 - (*
this)[1][2] * SubFactor03 + (*
this)[1][3] * SubFactor04),
449 +((*
this)[1][0] * SubFactor01 - (*
this)[1][1] * SubFactor03 + (*
this)[1][3] * SubFactor05),
450 -((*
this)[1][0] * SubFactor02 - (*
this)[1][1] * SubFactor04 + (*
this)[1][2] * SubFactor05));
452 (*
this)[0][0] * DetCof[0] + (*this)[0][1] * DetCof[1] +
453 (*this)[0][2] * DetCof[2] + (*this)[0][3] * DetCof[3];
456 return Constant<t_type>::Invalid;
459 [[nodiscard]]
constexpr Vector<3, t_type> decomposeScale()
const
461 static_assert(t_col_dims >= 4 && t_row_dims >= 4,
"Cannot decompose lower dimension matrix");
462 Vector<3, t_type> scaling;
463 Vector<3, t_type> rows[3];
464 for (
uint01 i = 0; i < 3; i++)
469 scaling =
quantize(scaling, Vector<3, t_type>(.000001));
470 const Vector<3, t_type> temp_z =
cross(rows[0], rows[1]);
471 if (
dot(temp_z, rows[2]) < 0)
473 scaling[X] = -scaling[X];
478 [[nodiscard]]
constexpr Vector<3, t_type> decomposeOffset()
const
480 static_assert(t_col_dims >= 3 && t_row_dims >= 3,
"Cannot decompose lower dimension matrix");
481 Vector<3, t_type> offset;
482 offset[X] = (*this)[3][0];
483 offset[Y] = (*this)[3][1];
484 offset[Z] = (*this)[3][2];
491 template<
class t_angle_type>
492 [[nodiscard]]
constexpr Vector<3, Angle<t_angle_type>> decomposeRotation()
const
494 static_assert(t_col_dims >= 3 && t_row_dims >= 3,
"Cannot decompose lower dimension matrix");
495 Vector<3, Angle<t_angle_type>> rotation;
496 Vector<3, t_type> rows[3];
497 for (
uint01 i = 0; i < 3; i++)
501 const Vector<3, t_type> temp_z =
cross(rows[0], rows[1]);
502 if (
dot(temp_z, rows[2]) < 0)
506 for (
uint04 i = 0; i < 3; i++)
510 t_type sy =
sqrt(rows[0][0] * rows[0][0] + rows[0][1] * rows[0][1]);
525 template<
class t_angle_type>
529 const t_type sin_phi =
530 ((R[2][1] - R[1][2]) * axis_unit[0] +
531 (R[0][2] - R[2][0]) * axis_unit[1] +
532 (R[1][0] - R[0][1]) * axis_unit[2]) *
static_cast<t_type
>(0.5);
535 Vector<3, t_type> Ra{
536 R[0][0] * axis_unit[0] + R[0][1] * axis_unit[1] + R[0][2] * axis_unit[2],
537 R[1][0] * axis_unit[0] + R[1][1] * axis_unit[1] + R[1][2] * axis_unit[2],
538 R[2][0] * axis_unit[0] + R[2][1] * axis_unit[1] + R[2][2] * axis_unit[2]
541 const t_type cos_phi =
dot(axis_unit, Ra);
545 [[nodiscard]]
constexpr Vector<4, t_type> decomposeRotationQuaternion()
const
547 t_type trace = (*this)[0][0] + (*this)[1][1] + (*this)[2][2];
548 Vector<4, t_type> temp;
550 if (trace > t_type(0.0))
552 t_type s =
sqrt(trace + t_type(1.0));
553 temp[3] = (s * t_type(0.5));
556 temp[0] = (((*this)[2][1] - (*this)[1][2]) * s);
557 temp[1] = (((*this)[0][2] - (*this)[2][0]) * s);
558 temp[2] = (((*this)[1][0] - (*this)[0][1]) * s);
562 uint01 i = (*this)[0][0] < (*this)[1][1] ?
563 ((*this)[1][1] < (*this)[2][2] ? 2U : 1U) :
564 ((*this)[0][0] < (*this)[2][2] ? 2U : 0U);
568 t_type s = t_type((*
this)[i][i] - (*
this)[j][j] - (*
this)[k][k] + t_type(1.0));
569 temp[i] = s * t_type(0.5);
572 temp[3] = ((*this)[k][j] - (*this)[j][k]) * s;
573 temp[j] = ((*this)[j][i] + (*this)[i][j]) * s;
574 temp[k] = ((*this)[k][i] + (*this)[i][k]) * s;
578 template<
class t_angle_type>
579 constexpr void decompose(Vector<3, t_type>& scaling, Vector<3,
Angle<t_angle_type>>& rotation, Vector<3, t_type>& position)
const
581 static_assert(t_col_dims >= 4 && t_row_dims >= 4,
"Cannot decompose lower dimension matrix");
583 position[X] = (*this)[3][0];
584 position[Y] = (*this)[3][1];
585 position[Z] = (*this)[3][2];
587 Vector<3, t_type> rows[3];
588 for (
uint01 i = 0; i < 3; i++)
593 scaling =
quantize(scaling, Vector<3, t_type>(.000001));
594 const Vector<3, t_type> temp_z =
cross(rows[0], rows[1]);
595 if (
dot(temp_z, rows[2]) < 0)
597 scaling[X] = -scaling[X];
600 for (
uint04 i = 0; i < 3; i++)
604 t_type sy =
sqrt(rows[0][0] * rows[0][0] + rows[0][1] * rows[0][1]);
618 [[nodiscard]]
constexpr Matrix offset(
const Vector<2, t_type>& translation)
const
621 mat[t_row_dims - 1][0] = translation[X];
622 if constexpr (t_col_dims >= 2)
623 mat[t_row_dims - 1][1] = translation[Y];
624 if constexpr (t_col_dims >= 3)
625 mat[t_row_dims - 1][2] = 0;
626 return (*
this) * mat;
631 [[nodiscard]]
constexpr Matrix offset(
const Vector<3, t_type>& translation)
const
633 return (*
this) * Matrix::OffsetMatrix(translation);
636 [[nodiscard]]
constexpr inline Matrix scale(t_type scale)
const
638 return (*
this) * Matrix::ScalerMatrix(scale);
642 [[nodiscard]]
constexpr Matrix scale(
const Vector<2, t_type>& scale)
const
644 return (*
this) * Matrix::ScalerMatrix(scale);
648 [[nodiscard]]
constexpr Matrix scale(
const Vector<3, t_type>& scale)
const
650 return (*
this) * Matrix::ScalerMatrix(scale);
653 Matrix& correctZeroScale(t_type new_value = 1e-6, t_type epsilon = 1e-9)
655 for (
uint01 i = 0; i <
getMin(t_row_dims, t_col_dims); i++)
657 if (std::abs((*
this)[i][i]) < epsilon)
658 (*this)[i][i] = new_value;
663 [[nodiscard]]
constexpr Matrix scale(
const Vector<3, t_type>& direction, t_type scale)
const
666 mat[0][0] += (scale - 1) * direction[X] * direction[X];
667 mat[0][1] = (scale - 1) * direction[Y] * direction[X];
668 mat[0][2] = (scale - 1) * direction[Z] * direction[X];
670 mat[1][0] = (scale - 1) * direction[X] * direction[Y];
671 mat[1][1] += (scale - 1) * direction[Y] * direction[Y];
672 mat[1][2] = (scale - 1) * direction[Z] * direction[Y];
674 mat[2][0] = (scale - 1) * direction[X] * direction[Z];
675 mat[2][1] = (scale - 1) * direction[Y] * direction[Z];
676 mat[2][2] += (scale - 1) * direction[Z] * direction[Z];
678 return (*
this) * mat;
680 template<
class t_angle_type>
681 [[nodiscard]]
constexpr Matrix rotate(
const Vector<3,
Angle<t_angle_type>>& orientation)
const
683 return *
this * Matrix<t_type>::RotationMatrix(orientation);
685 template<
class t_angle_type>
686 [[nodiscard]]
constexpr Matrix<t_type> rotate(
const Angle<t_angle_type>& phi,
const Vector<3, t_type>& axis)
const
688 return *
this * RotationMatrix(phi, axis);
690 [[nodiscard]]
constexpr Matrix shear(t_type dx, t_type dy)
const
695 return (*
this) * mat;
697 [[nodiscard]]
constexpr Matrix<t_type, t_col_dims, t_row_dims> transpose()
const
699 Matrix<t_type, t_col_dims, t_row_dims> mat;
700 for (
uint01 row = 0; row < t_row_dims; row++)
701 for (
uint01 col = 0; col < t_col_dims; col++)
702 mat[col][row] = (*
this)[row][col];
706 template<u
int01 t_cols = t_col_dims, u
int01 t_rows = t_row_dims>
707 [[nodiscard]]
inline Matrix<t_type, t_cols, t_rows> invert()
const
712 [[nodiscard]]
inline t_type* begin()
714 return &(*this)[0][0];
717 [[nodiscard]]
inline const t_type* begin()
const
719 return &(*this)[0][0];
721 [[nodiscard]]
inline const t_type& inlineGet(
uint01 val)
const
723 return (&(*
this)[0][0])[val];
725 [[nodiscard]]
inline t_type& inlineGet(
uint01 val)
727 return (&(*
this)[0][0])[val];
730 [[nodiscard]] Matrix operator*(
const Matrix& right)
const
732 Matrix<t_type, t_row_dims, t_col_dims>
product;
733 for(
uint01 col = 0; col < t_col_dims; ++col)
735 for(
uint01 row = 0; row < t_row_dims; ++row)
737 for(
uint01 i = 0; i < t_row_dims; ++i)
739 product[row][col] += ((*this)[i][col] * right[row][i]);
745 inline Matrix& operator=(
const Matrix& right)
747 for(
uint01 col = 0; col < t_col_dims; ++col)
749 for(
uint01 row = 0; row < t_row_dims; ++row)
751 (*this)[row][col] = right[row][col];
756 inline Matrix& operator*=(
const Matrix& right)
758 *
this = *
this * right;