32#include <glm/matrix.hpp>
34#include <glm/ext/matrix_clip_space.hpp>
35#include <glm/ext/matrix_transform.hpp>
37#include <glm/mat2x2.hpp>
38#include <glm/mat2x3.hpp>
39#include <glm/mat2x4.hpp>
40#include <glm/mat3x2.hpp>
41#include <glm/mat3x3.hpp>
42#include <glm/mat3x4.hpp>
43#include <glm/mat4x2.hpp>
44#include <glm/mat4x3.hpp>
45#include <glm/mat4x4.hpp>
47namespace utility::math
50 using glm::determinant;
52 using glm::matrixCompMult;
53 using glm::outerProduct;
57 using glm::infinitePerspective;
59 using glm::perspective;
60 using glm::perspectiveFov;
61 using glm::perspectiveLH;
62 using glm::perspectiveRH;
63 using glm::tweakedInfinitePerspective;
77 template<
typename Type>
89 typename = std::enable_if_t<(Cols >= 2) && (Cols <= 4)
90 && (Rows >= 2) && (Rows <= 4)>>
91 class Matrix:
public glm::mat<Cols, Rows, MatrixComponentType>
99 : glm::mat<Cols, Rows, MatrixComponentType>(
100 MatrixComponentType { 0 })
102 if constexpr (Cols == Rows) {
103 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
105 glm::mat<Cols, Rows, MatrixComponentType>(
106 MatrixComponentType { 1 });
116 Matrix(std::initializer_list<MatrixComponentType> values)
118 if (values.size() != Cols * Rows) {
119 throw std::invalid_argument(
"Matrix requires exactly "
120 + std::to_string(Cols * Rows)
123 const auto it = values.begin();
124 for (std::size_t row = 0; row < Rows; ++row) {
125 for (std::size_t col = 0; col < Cols; ++col) {
126 (*this)[col][row] = *(it + row * Cols + col);
135 explicit Matrix(MatrixComponentType value)
136 : glm::mat<Cols, Rows, MatrixComponentType>(value)
144 explicit Matrix(
const glm::mat<Cols, Rows, MatrixComponentType> &value)
145 : glm::mat<Cols, Rows, MatrixComponentType>(value)
188 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
191 const glm::mat<Cols, Rows, MatrixComponentType> &
>(rhs));
201 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
this) +=
202 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
215 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
218 const glm::mat<Cols, Rows, MatrixComponentType> &
>(rhs));
228 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
this) -=
229 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
242 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
254 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
this) *=
267 if (scalar == MatrixComponentType { 0 }) {
268 throw std::invalid_argument(
"Matrix division by zero");
271 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
284 if (scalar == MatrixComponentType { 0 }) {
285 throw std::invalid_argument(
"Matrix division by zero");
287 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
this) /=
301 template<std::
size_t RhsCols, std::
size_t RhsRows>
302 requires(Cols == RhsRows)
307 using LhsGlm = glm::mat<Cols, Rows, MatrixComponentType>;
308 using RhsGlm = glm::mat<RhsCols, RhsRows, MatrixComponentType>;
310 static_cast<const LhsGlm &
>(*
this)
311 *
static_cast<const RhsGlm &
>(rhs));
320 requires(Cols == Rows)
322 *
static_cast<glm::mat<Cols, Rows, MatrixComponentType> *
>(
this) =
323 static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
326 const glm::mat<Cols, Rows, MatrixComponentType> &
>(rhs);
341 const glm::mat<Cols, Rows, MatrixComponentType> &
>(*this)
343 const glm::mat<Cols, Rows, MatrixComponentType> &
>(rhs);
356 MatrixComponentType epsilon = MatrixComponentType {
359 for (std::size_t col = 0; col < Cols; ++col) {
360 for (std::size_t row = 0; row < Rows; ++row) {
361 if (std::abs((*
this)[col][row] - rhs[col][row]) > epsilon) {
376 return !(*
this == rhs);
386 -
static_cast<const glm::mat<Cols, Rows, MatrixComponentType> &
>(
406 using Matrix2x2F = Matrix<float, 2, 2>;
411 using Matrix2x2D = Matrix<double, 2, 2>;
416 using Matrix2x3F = Matrix<float, 2, 3>;
421 using Matrix2x3D = Matrix<double, 2, 3>;
426 using Matrix2x4F = Matrix<float, 2, 4>;
431 using Matrix2x4D = Matrix<double, 2, 4>;
436 using Matrix3x2F = Matrix<float, 3, 2>;
441 using Matrix3x2D = Matrix<double, 3, 2>;
446 using Matrix3x3F = Matrix<float, 3, 3>;
451 using Matrix3x3D = Matrix<double, 3, 3>;
456 using Matrix3x4F = Matrix<float, 3, 4>;
461 using Matrix3x4D = Matrix<double, 3, 4>;
466 using Matrix4x2F = Matrix<float, 4, 2>;
471 using Matrix4x2D = Matrix<double, 4, 2>;
476 using Matrix4x3F = Matrix<float, 4, 3>;
481 using Matrix4x3D = Matrix<double, 4, 3>;
486 using Matrix4x4F = Matrix<float, 4, 4>;
491 using Matrix4x4D = Matrix<double, 4, 4>;
499 std::ostream &operator<<(std::ostream &stream,
const Matrix2x2F &matrix);
507 std::ostream &operator<<(std::ostream &stream,
const Matrix2x2D &matrix);
515 std::ostream &operator<<(std::ostream &stream,
const Matrix4x4F &matrix);
523 std::ostream &operator<<(std::ostream &stream,
const Matrix4x4D &matrix);
531 std::ostream &operator<<(std::ostream &stream,
const Matrix3x3F &matrix);
539 std::ostream &operator<<(std::ostream &stream,
const Matrix3x3D &matrix);
547 std::ostream &operator<<(std::ostream &stream,
const Matrix3x4F &matrix);
555 std::ostream &operator<<(std::ostream &stream,
const Matrix3x4D &matrix);
563 std::ostream &operator<<(std::ostream &stream,
const Matrix4x3F &matrix);
571 std::ostream &operator<<(std::ostream &stream,
const Matrix4x3D &matrix);
579 std::ostream &operator<<(std::ostream &stream,
const Matrix2x3F &matrix);
587 std::ostream &operator<<(std::ostream &stream,
const Matrix2x3D &matrix);
595 std::ostream &operator<<(std::ostream &stream,
const Matrix2x4F &matrix);
603 std::ostream &operator<<(std::ostream &stream,
const Matrix2x4D &matrix);
611 std::ostream &operator<<(std::ostream &stream,
const Matrix3x2F &matrix);
619 std::ostream &operator<<(std::ostream &stream,
const Matrix3x2D &matrix);
627 std::ostream &operator<<(std::ostream &stream,
const Matrix4x2F &matrix);
635 std::ostream &operator<<(std::ostream &stream,
const Matrix4x2D &matrix);
643 std::ostream &operator<<(std::ostream &stream,
const Matrix4x4F &matrix);
651 std::ostream &operator<<(std::ostream &stream,
const Matrix4x4D &matrix);
M x N matrix class inheriting from glm::mat<Cols, Rows, Type>.
bool equalsEpsilon(const Matrix &rhs, MatrixComponentType epsilon=MatrixComponentType { 1e-5 }) const
Approximate equality using an epsilon threshold.
Matrix & operator*=(const Matrix &rhs) noexcept
Matrix multiplication assignment (square matrices only).
~Matrix(void)=default
Default destructor for Matrix.
Matrix & operator=(const Matrix &other)=default
Copy assignment operator.
Matrix & operator-=(const Matrix &rhs) noexcept
Matrix subtraction assignment.
Matrix & operator*=(MatrixComponentType scalar) noexcept
Scalar multiplication assignment.
Matrix(const glm::mat< Cols, Rows, MatrixComponentType > &value)
Construct from a GLM matrix.
Matrix operator-(void) const noexcept
Unary negation.
bool operator!=(const Matrix &rhs) const noexcept
Inequality comparison.
friend Matrix operator*(MatrixComponentType scalar, const Matrix &mat)
Friend function for scalar multiplication with scalar on the left.
Matrix & operator+=(const Matrix &rhs) noexcept
Matrix addition assignment.
bool operator==(const Matrix &rhs) const noexcept
Equality comparison.
Matrix(MatrixComponentType value)
Construct by filling all components with the same value.
Matrix(void)
Default constructor initializing square matrices to identity and non-square matrices to zero.
Matrix operator*(MatrixComponentType scalar) const noexcept
Scalar multiplication.
Matrix & operator=(Matrix &&other) noexcept=default
Move assignment operator.
Matrix(const Matrix &other)=default
Copy constructor.
Matrix operator+(const Matrix &rhs) const noexcept
Matrix addition.
Matrix & operator/=(MatrixComponentType scalar)
Scalar division assignment.
Matrix operator-(const Matrix &rhs) const noexcept
Matrix subtraction.
Matrix operator/(MatrixComponentType scalar) const
Scalar division.
Matrix(std::initializer_list< MatrixComponentType > values)
Construct from initializer list of Cols*Rows values (row-major order).
Matrix(Matrix &&other) noexcept=default
Move constructor.
Concept to constrain matrix component type.