From 4fb06d70fca79e361f98ab826b1659f3afb3c139 Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 30 Sep 2024 10:58:54 -0700 Subject: [PATCH 1/4] refactored some unit tests --- include/omath/Mat.h | 304 ++++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/UnitTestMat.cpp | 245 ++++++++++++++++++++++++++++++++++ 3 files changed, 550 insertions(+) create mode 100644 include/omath/Mat.h create mode 100644 tests/UnitTestMat.cpp diff --git a/include/omath/Mat.h b/include/omath/Mat.h new file mode 100644 index 0000000..36789cf --- /dev/null +++ b/include/omath/Mat.h @@ -0,0 +1,304 @@ +// +// Created by vlad on 9/29/2024. +// +#pragma once +#include +#include +#include +#include "Vector3.h" +#include +#include "Angles.h" + + +namespace omath +{ + template + class Mat final + { + public: + + constexpr Mat() + { + Clear(); + } + + + constexpr Mat(const std::initializer_list>& rows) + { + if (rows.size() != Rows) + throw std::invalid_argument("Initializer list rows size does not match template parameter Rows"); + + auto rowIt = rows.begin(); + for (size_t i = 0; i < Rows; ++i, ++rowIt) + { + if (rowIt->size() != Columns) + throw std::invalid_argument("All rows must have the same number of columns as template parameter Columns"); + + auto colIt = rowIt->begin(); + for (size_t j = 0; j < Columns; ++j, ++colIt) + { + At(i, j) = *colIt; + } + } + } + + + constexpr Mat(const Mat& other) + { + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) = other.At(i, j); + } + + + constexpr Mat(Mat&& other) noexcept + { + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) = other.At(i, j) ; + } + + [[nodiscard]] + static constexpr size_t RowCount() noexcept { return Rows; } + + [[nodiscard]] + static constexpr size_t ColumnsCount() noexcept { return Columns; } + + [[nodiscard]] + constexpr std::pair Size() const noexcept { return { Rows, Columns }; } + + + [[nodiscard]] constexpr const float& At(const size_t rowIndex, const size_t columnIndex) const + { + if (rowIndex >= Rows || columnIndex >= Columns) + throw std::out_of_range("Index out of range"); + + return m_data[rowIndex * Columns + columnIndex]; + } + [[nodiscard]] constexpr float& At(const size_t rowIndex, const size_t columnIndex) + { + return const_cast(std::as_const(*this).At(rowIndex, columnIndex)); + } + [[nodiscard]] + constexpr float Sum() const + { + float sum = 0.f; + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + sum += At(i, j); + + return sum; + } + + constexpr void Clear() + { + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) = 0.f; + } + + // Operator overloading for multiplication with another Mat + template + constexpr Mat operator*(const Mat& other) const + { + Mat result; + + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < OtherColumns; ++j) + { + float sum = 0.f; + for (size_t k = 0; k < Columns; ++k) + sum += At(i, k) * other.At(k, j); + result.At(i, j) = sum; + } + return result; + } + + constexpr Mat& operator*=(float f) + { + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) *= f; + return *this; + } + + constexpr Mat operator*(float f) const + { + Mat result(*this); + result *= f; + return result; + } + + constexpr Mat& operator/=(float f) + { + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) /= f; + return *this; + } + + constexpr Mat operator/(float f) const + { + Mat result(*this); + result /= f; + return result; + } + + constexpr Mat& operator=(const Mat& other) + { + if (this == &other) + return *this; + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) = other.At(i, j); + return *this; + } + + constexpr Mat& operator=(Mat&& other) noexcept + { + if (this == &other) + return *this; + + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + At(i, j) = other.At(i, j); + + return *this; + } + + [[nodiscard]] + constexpr Mat Transpose() const + { + Mat transposed; + for (size_t i = 0; i < Rows; ++i) + for (size_t j = 0; j < Columns; ++j) + transposed.At(j, i) = At(i, j); + + return transposed; + } + + [[nodiscard]] + constexpr float Determinant() const + { + static_assert(Rows == Columns, "Determinant is only defined for square matrices."); + + if constexpr (Rows == 1) + return At(0, 0); + + else if constexpr (Rows == 2) + return At(0, 0) * At(1, 1) - At(0, 1) * At(1, 0); + else + { + float det = 0.f; + for (size_t i = 0; i < Columns; ++i) + { + const float cofactor = (i % 2 == 0 ? 1.f : -1.f) * At(0, i) * Minor(0, i).Determinant(); + det += cofactor; + } + return det; + } + } + + [[nodiscard]] + constexpr Mat Minor(size_t row, size_t column) const + { + Mat result; + for (size_t i = 0, m = 0; i < Rows; ++i) + { + if (i == row) + continue; + for (size_t j = 0, n = 0; j < Columns; ++j) + { + if (j == column) + continue; + result.At(m, n) = At(i, j); + ++n; + } + ++m; + } + return result; + } + + [[nodiscard]] + std::string ToString() const + { + std::ostringstream oss; + for (size_t i = 0; i < Rows; ++i) + { + for (size_t j = 0; j < Columns; ++j) + { + oss << At(i, j); + if (j != Columns - 1) + oss << ' '; + } + oss << '\n'; + } + return oss.str(); + } + + // Static methods that return fixed-size matrices + [[nodiscard]] + constexpr static Mat<4, 4> ToScreenMat(float screenWidth, float screenHeight) + { + Mat<4, 4> mat; + mat.At(0, 0) = screenWidth / 2.f; + mat.At(1, 1) = -screenHeight / 2.f; + mat.At(2, 2) = 1.f; + mat.At(3, 0) = screenWidth / 2.f; + mat.At(3, 1) = screenHeight / 2.f; + mat.At(3, 3) = 1.f; + return mat; + } + + [[nodiscard]] + constexpr static Mat<4, 4> TranslationMat(const Vector3& diff) + { + Mat<4, 4> mat; + mat.At(0, 0) = 1.f; + mat.At(1, 1) = 1.f; + mat.At(2, 2) = 1.f; + mat.At(3, 3) = 1.f; + mat.At(3, 0) = diff.x; + mat.At(3, 1) = diff.y; + mat.At(3, 2) = diff.z; + return mat; + } + + [[nodiscard]] + constexpr static Mat<4, 4> OrientationMat(const Vector3& forward, const Vector3& right, const Vector3& up) + { + Mat<4, 4> mat; + + mat.At(0, 0) = right.x; + mat.At(0, 1) = up.x; + mat.At(0, 2) = forward.x; + mat.At(1, 0) = right.y; + mat.At(1, 1) = up.y; + mat.At(1, 2) = forward.y; + mat.At(2, 0) = right.z; + mat.At(2, 1) = up.z; + mat.At(2, 2) = forward.z; + mat.At(3, 3) = 1.f; + + return mat; + } + + [[nodiscard]] + constexpr static Mat<4, 4> ProjectionMat(const float fieldOfView, const float aspectRatio, const float near, const float far) + { + Mat<4, 4> mat; + const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f); + + mat.At(0, 0) = 1.f / (aspectRatio * fovHalfTan); + mat.At(1, 1) = 1.f / fovHalfTan; + mat.At(2, 2) = (far + near) / (far - near); + mat.At(2, 3) = (2.f * near * far) / (far - near); + mat.At(3, 2) = -1.f; + + return mat; + } + + private: + std::array m_data; + }; +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 920fae4..90f0bea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,7 @@ include(GoogleTest) add_executable(unit-tests UnitTestPrediction.cpp UnitTestMatrix.cpp + UnitTestMat.cpp UnitTestAstar.cpp UnitTestProjection.cpp UnitTestVector3.cpp diff --git a/tests/UnitTestMat.cpp b/tests/UnitTestMat.cpp new file mode 100644 index 0000000..7a0048c --- /dev/null +++ b/tests/UnitTestMat.cpp @@ -0,0 +1,245 @@ +// UnitTestMat.cpp +#include +#include "omath/Mat.h" +#include "omath/Vector3.h" + +using namespace omath; + +class UnitTestMat : public ::testing::Test +{ +protected: + Mat<2, 2> m1; + Mat<2, 2> m2; + + void SetUp() override + { + m1 = Mat<2, 2>(); + m2 = Mat<2, 2>{{1.0f, 2.0f}, {3.0f, 4.0f}}; + } +}; + +// Test constructors +TEST_F(UnitTestMat, Constructor_Default) +{ + Mat<3, 3> m; + EXPECT_EQ(m.RowCount(), 3); + EXPECT_EQ(m.ColumnsCount(), 3); + for (size_t i = 0; i < 3; ++i) + for (size_t j = 0; j < 3; ++j) + EXPECT_FLOAT_EQ(m.At(i, j), 0.0f); +} + +TEST_F(UnitTestMat, Constructor_InitializerList) +{ + constexpr Mat<2, 2> m{{1.0f, 2.0f}, {3.0f, 4.0f}}; + EXPECT_EQ(m.RowCount(), 2); + EXPECT_EQ(m.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(m.At(0, 0), 1.0f); + EXPECT_FLOAT_EQ(m.At(0, 1), 2.0f); + EXPECT_FLOAT_EQ(m.At(1, 0), 3.0f); + EXPECT_FLOAT_EQ(m.At(1, 1), 4.0f); +} + +TEST_F(UnitTestMat, Constructor_Copy) +{ + Mat<2, 2> m3 = m2; + EXPECT_EQ(m3.RowCount(), m2.RowCount()); + EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount()); + EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0)); + EXPECT_FLOAT_EQ(m3.At(1, 1), m2.At(1, 1)); +} + +TEST_F(UnitTestMat, Constructor_Move) +{ + Mat<2, 2> m3 = std::move(m2); + EXPECT_EQ(m3.RowCount(), 2); + EXPECT_EQ(m3.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f); + EXPECT_FLOAT_EQ(m3.At(1, 1), 4.0f); + // m2 is in a valid but unspecified state after move +} + +// Test matrix operations +TEST_F(UnitTestMat, Operator_Multiplication_Matrix) +{ + Mat<2, 2> m3 = m2 * m2; + EXPECT_EQ(m3.RowCount(), 2); + EXPECT_EQ(m3.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(m3.At(0, 0), 7.0f); + EXPECT_FLOAT_EQ(m3.At(0, 1), 10.0f); + EXPECT_FLOAT_EQ(m3.At(1, 0), 15.0f); + EXPECT_FLOAT_EQ(m3.At(1, 1), 22.0f); +} + +TEST_F(UnitTestMat, Operator_Multiplication_Scalar) +{ + Mat<2, 2> m3 = m2 * 2.0f; + EXPECT_FLOAT_EQ(m3.At(0, 0), 2.0f); + EXPECT_FLOAT_EQ(m3.At(1, 1), 8.0f); +} + +TEST_F(UnitTestMat, Operator_Division_Scalar) +{ + Mat<2, 2> m3 = m2 / 2.0f; + EXPECT_FLOAT_EQ(m3.At(0, 0), 0.5f); + EXPECT_FLOAT_EQ(m3.At(1, 1), 2.0f); +} + +// Test matrix functions +TEST_F(UnitTestMat, Transpose) +{ + Mat<2, 2> m3 = m2.Transpose(); + EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0)); + EXPECT_FLOAT_EQ(m3.At(0, 1), m2.At(1, 0)); + EXPECT_FLOAT_EQ(m3.At(1, 0), m2.At(0, 1)); + EXPECT_FLOAT_EQ(m3.At(1, 1), m2.At(1, 1)); +} + +TEST_F(UnitTestMat, Determinant) +{ + const float det = m2.Determinant(); + EXPECT_FLOAT_EQ(det, -2.0f); +} + +TEST_F(UnitTestMat, Sum) +{ + const float sum = m2.Sum(); + EXPECT_FLOAT_EQ(sum, 10.0f); +} + +TEST_F(UnitTestMat, Clear) +{ + m2.Clear(); + for (size_t i = 0; i < m2.RowCount(); ++i) + for (size_t j = 0; j < m2.ColumnsCount(); ++j) + EXPECT_FLOAT_EQ(m2.At(i, j), 0.0f); +} + +TEST_F(UnitTestMat, ToString) +{ + const std::string str = m2.ToString(); + EXPECT_FALSE(str.empty()); + EXPECT_EQ(str, "1 2\n3 4\n"); +} + +// Test assignment operators +TEST_F(UnitTestMat, AssignmentOperator_Copy) +{ + Mat<2, 2> m3; + m3 = m2; + EXPECT_EQ(m3.RowCount(), m2.RowCount()); + EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount()); + EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0)); +} + +TEST_F(UnitTestMat, AssignmentOperator_Move) +{ + Mat<2, 2> m3; + m3 = std::move(m2); + EXPECT_EQ(m3.RowCount(), 2); + EXPECT_EQ(m3.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f); + EXPECT_FLOAT_EQ(m3.At(1, 1), 4.0f); + // m2 is in a valid but unspecified state after move +} + +// Test static methods +TEST_F(UnitTestMat, StaticMethod_ToScreenMat) +{ + Mat<4, 4> screenMat = Mat<4, 4>::ToScreenMat(800.0f, 600.0f); + EXPECT_FLOAT_EQ(screenMat.At(0, 0), 400.0f); + EXPECT_FLOAT_EQ(screenMat.At(1, 1), -300.0f); + EXPECT_FLOAT_EQ(screenMat.At(3, 0), 400.0f); + EXPECT_FLOAT_EQ(screenMat.At(3, 1), 300.0f); + EXPECT_FLOAT_EQ(screenMat.At(3, 3), 1.0f); +} + +// Test static method: TranslationMat +TEST_F(UnitTestMat, StaticMethod_TranslationMat) +{ + Vector3 diff{10.0f, 20.0f, 30.0f}; + Mat<4, 4> transMat = Mat<4, 4>::TranslationMat(diff); + EXPECT_FLOAT_EQ(transMat.At(0, 0), 1.0f); + EXPECT_FLOAT_EQ(transMat.At(3, 0), diff.x); + EXPECT_FLOAT_EQ(transMat.At(3, 1), diff.y); + EXPECT_FLOAT_EQ(transMat.At(3, 2), diff.z); + EXPECT_FLOAT_EQ(transMat.At(3, 3), 1.0f); +} + +// Test static method: OrientationMat +TEST_F(UnitTestMat, StaticMethod_OrientationMat) +{ + constexpr Vector3 forward{0.0f, 0.0f, 1.0f}; + constexpr Vector3 right{1.0f, 0.0f, 0.0f}; + constexpr Vector3 up{0.0f, 1.0f, 0.0f}; + constexpr Mat<4, 4> orientMat = Mat<4, 4>::OrientationMat(forward, right, up); + EXPECT_FLOAT_EQ(orientMat.At(0, 0), right.x); + EXPECT_FLOAT_EQ(orientMat.At(0, 1), up.x); + EXPECT_FLOAT_EQ(orientMat.At(0, 2), forward.x); + EXPECT_FLOAT_EQ(orientMat.At(1, 0), right.y); + EXPECT_FLOAT_EQ(orientMat.At(1, 1), up.y); + EXPECT_FLOAT_EQ(orientMat.At(1, 2), forward.y); + EXPECT_FLOAT_EQ(orientMat.At(2, 0), right.z); + EXPECT_FLOAT_EQ(orientMat.At(2, 1), up.z); + EXPECT_FLOAT_EQ(orientMat.At(2, 2), forward.z); +} + +// Test static method: ProjectionMat +TEST_F(UnitTestMat, StaticMethod_ProjectionMat) +{ + constexpr float fieldOfView = 45.0f; + constexpr float aspectRatio = 1.33f; + constexpr float near = 0.1f; + constexpr float far = 100.0f; + const Mat<4, 4> projMat = Mat<4, 4>::ProjectionMat(fieldOfView, aspectRatio, near, far); + + const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f); + + EXPECT_FLOAT_EQ(projMat.At(0, 0), 1.f / (aspectRatio * fovHalfTan)); + EXPECT_FLOAT_EQ(projMat.At(1, 1), 1.f / fovHalfTan); + EXPECT_FLOAT_EQ(projMat.At(2, 2), (far + near) / (far - near)); + EXPECT_FLOAT_EQ(projMat.At(2, 3), (2.f * near * far) / (far - near)); + EXPECT_FLOAT_EQ(projMat.At(3, 2), -1.f); +} + +// Test exception handling in At() method +TEST_F(UnitTestMat, Method_At_OutOfRange) +{ + EXPECT_THROW(std::ignore = m2.At(2, 0), std::out_of_range); + EXPECT_THROW(std::ignore = m2.At(0, 2), std::out_of_range); +} + +// Test Determinant for 3x3 matrix +TEST(UnitTestMatStandalone, Determinant_3x3) +{ + constexpr auto det = Mat<3, 3>{{6, 1, 1}, {4, -2, 5}, {2, 8, 7}}.Determinant(); + EXPECT_FLOAT_EQ(det, -306.0f); +} + +// Test Minor for 3x3 matrix +TEST(UnitTestMatStandalone, Minor_3x3) +{ + constexpr Mat<3, 3> m{{3, 0, 2}, {2, 0, -2}, {0, 1, 1}}; + auto minor = m.Minor(0, 0); + EXPECT_EQ(minor.RowCount(), 2); + EXPECT_EQ(minor.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(minor.At(0, 0), 0.0f); + EXPECT_FLOAT_EQ(minor.At(0, 1), -2.0f); + EXPECT_FLOAT_EQ(minor.At(1, 0), 1.0f); + EXPECT_FLOAT_EQ(minor.At(1, 1), 1.0f); +} + +// Test Transpose for non-square matrix +TEST(UnitTestMatStandalone, Transpose_NonSquare) +{ + constexpr Mat<2, 3> m{{1.0f, 2.0f, 3.0f}, {4.0f, 5.0f, 6.0f}}; + auto transposed = m.Transpose(); + EXPECT_EQ(transposed.RowCount(), 3); + EXPECT_EQ(transposed.ColumnsCount(), 2); + EXPECT_FLOAT_EQ(transposed.At(0, 0), 1.0f); + EXPECT_FLOAT_EQ(transposed.At(1, 0), 2.0f); + EXPECT_FLOAT_EQ(transposed.At(2, 0), 3.0f); + EXPECT_FLOAT_EQ(transposed.At(0, 1), 4.0f); + EXPECT_FLOAT_EQ(transposed.At(1, 1), 5.0f); + EXPECT_FLOAT_EQ(transposed.At(2, 1), 6.0f); +} From ac79326da80a580be2bc5dfbe53feaf0e3784db2 Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 30 Sep 2024 11:54:47 -0700 Subject: [PATCH 2/4] improved projection class --- include/omath/Mat.h | 6 ++++++ include/omath/projection/Camera.h | 4 ++-- source/projection/Camera.cpp | 12 ++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/omath/Mat.h b/include/omath/Mat.h index 36789cf..b1165c9 100644 --- a/include/omath/Mat.h +++ b/include/omath/Mat.h @@ -121,6 +121,12 @@ namespace omath At(i, j) *= f; return *this; } + + template + constexpr Mat operator*=(const Mat& other) + { + return *this = *this * other; + } constexpr Mat operator*(float f) const { diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index a3bfbe1..4d37e67 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include "ErrorCodes.h" @@ -28,7 +28,7 @@ namespace omath::projection Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); - [[nodiscard]] Matrix GetViewMatrix() const; + [[nodiscard]] Mat<4, 4> GetViewMatrix() const; [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const; diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 5f67a6e..0b49e70 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -21,24 +21,24 @@ namespace omath::projection m_farPlaneDistance = far; } - Matrix Camera::GetViewMatrix() const + Mat<4, 4> Camera::GetViewMatrix() const { const auto forward = Vector3::ForwardVector(m_viewAngles.x, m_viewAngles.y); const auto right = Vector3::RightVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z); const auto up = Vector3::UpVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z); - return Matrix::TranslationMatrix(-m_origin) * Matrix::OrientationMatrix(forward, right, up); + return Mat<4, 4>::TranslationMat(-m_origin) * Mat<4, 4>::OrientationMat(forward, right, up); } std::expected Camera::WorldToScreen(const Vector3 &worldPosition) const { - const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); + const auto posVecAsMatrix = Mat<1, 4>({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); - const auto projectionMatrix = Matrix::ProjectionMatrix(m_fieldOfView, m_viewPort.AspectRatio(), + const auto projectionMatrix = Mat<4, 4>::ProjectionMat(m_fieldOfView, m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); - auto projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix); + Mat<1, 4> projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix); if (projected.At(0, 3) <= 0.f) return std::unexpected(Error::WORLD_POSITION_IS_BEHIND_CAMERA); @@ -49,7 +49,7 @@ namespace omath::projection projected.At(0, 1) < -1.f || projected.At(0, 1) > 1.f) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); - projected *= Matrix::ToScreenMatrix(m_viewPort.m_width, m_viewPort.m_height); + projected *= Mat<4, 4>::ToScreenMat(m_viewPort.m_width, m_viewPort.m_height); return Vector2{projected.At(0, 0), projected.At(0, 1)}; } From 1dedc7c01b63c2982a50100880e98af8251f6bc5 Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 30 Sep 2024 11:58:11 -0700 Subject: [PATCH 3/4] added line --- include/omath/Mat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/omath/Mat.h b/include/omath/Mat.h index b1165c9..812d384 100644 --- a/include/omath/Mat.h +++ b/include/omath/Mat.h @@ -121,7 +121,7 @@ namespace omath At(i, j) *= f; return *this; } - + template constexpr Mat operator*=(const Mat& other) { From 2652f55b75104901f1564630386422792de1c9e9 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 1 Oct 2024 05:16:45 -0700 Subject: [PATCH 4/4] updated static methods --- include/omath/Mat.h | 69 ++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/include/omath/Mat.h b/include/omath/Mat.h index 812d384..2923f90 100644 --- a/include/omath/Mat.h +++ b/include/omath/Mat.h @@ -65,7 +65,7 @@ namespace omath static constexpr size_t ColumnsCount() noexcept { return Columns; } [[nodiscard]] - constexpr std::pair Size() const noexcept { return { Rows, Columns }; } + static constexpr std::pair Size() noexcept { return { Rows, Columns }; } [[nodiscard]] constexpr const float& At(const size_t rowIndex, const size_t columnIndex) const @@ -206,7 +206,7 @@ namespace omath } [[nodiscard]] - constexpr Mat Minor(size_t row, size_t column) const + constexpr Mat Minor(const size_t row, const size_t column) const { Mat result; for (size_t i = 0, m = 0; i < Rows; ++i) @@ -244,30 +244,27 @@ namespace omath // Static methods that return fixed-size matrices [[nodiscard]] - constexpr static Mat<4, 4> ToScreenMat(float screenWidth, float screenHeight) + constexpr static Mat<4, 4> ToScreenMat(const float screenWidth, const float screenHeight) { - Mat<4, 4> mat; - mat.At(0, 0) = screenWidth / 2.f; - mat.At(1, 1) = -screenHeight / 2.f; - mat.At(2, 2) = 1.f; - mat.At(3, 0) = screenWidth / 2.f; - mat.At(3, 1) = screenHeight / 2.f; - mat.At(3, 3) = 1.f; - return mat; + return + { + {screenWidth / 2.f, 0.f, 0.f, 0.f}, + {0.f, -screenHeight / 2.f, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {screenWidth / 2.f, screenHeight / 2.f, 0.f, 1.f}, + }; } [[nodiscard]] constexpr static Mat<4, 4> TranslationMat(const Vector3& diff) { - Mat<4, 4> mat; - mat.At(0, 0) = 1.f; - mat.At(1, 1) = 1.f; - mat.At(2, 2) = 1.f; - mat.At(3, 3) = 1.f; - mat.At(3, 0) = diff.x; - mat.At(3, 1) = diff.y; - mat.At(3, 2) = diff.z; - return mat; + return + { + {1.f, 0.f, 0.f, 0.f}, + {0.f, 1.f, 0.f, 0.f}, + {0.f, 0.f, 1.f, 0.f}, + {diff.x, diff.y, diff.z, 1.f}, + }; } [[nodiscard]] @@ -275,16 +272,13 @@ namespace omath { Mat<4, 4> mat; - mat.At(0, 0) = right.x; - mat.At(0, 1) = up.x; - mat.At(0, 2) = forward.x; - mat.At(1, 0) = right.y; - mat.At(1, 1) = up.y; - mat.At(1, 2) = forward.y; - mat.At(2, 0) = right.z; - mat.At(2, 1) = up.z; - mat.At(2, 2) = forward.z; - mat.At(3, 3) = 1.f; + return + { + {right.x, up.x, forward.x, 0.f}, + {right.y, up.y, forward.y, 0.f}, + {right.z, up.z, forward.z, 0.f}, + {0.f, 0.f, 0.f, 1.f}, + }; return mat; } @@ -292,16 +286,15 @@ namespace omath [[nodiscard]] constexpr static Mat<4, 4> ProjectionMat(const float fieldOfView, const float aspectRatio, const float near, const float far) { - Mat<4, 4> mat; const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f); - mat.At(0, 0) = 1.f / (aspectRatio * fovHalfTan); - mat.At(1, 1) = 1.f / fovHalfTan; - mat.At(2, 2) = (far + near) / (far - near); - mat.At(2, 3) = (2.f * near * far) / (far - near); - mat.At(3, 2) = -1.f; - - return mat; + return + { + {1.f / (aspectRatio * fovHalfTan), 0.f, 0.f, 0.f}, + {0.f, 1.f / fovHalfTan, 0.f, 0.f}, + {0.f, 0.f, (far + near) / (far - near), 2.f * near * far / (far - near)}, + {0.f, 0.f, -1.f, 0.f} + }; } private: