From af880be056c45efde0ae6bdcdf2dca2391a9b9c3 Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 23 Dec 2024 15:34:38 +0300 Subject: [PATCH] added methods --- include/omath/engines/Source/Camera.hpp | 4 +- include/omath/projection/Camera.hpp | 79 ++++++++++++++++++++++--- source/engines/Source/Camera.cpp | 6 +- tests/engines/UnitTestSourceEngine.cpp | 27 +++++++-- tests/general/UnitTestProjection.cpp | 4 +- 5 files changed, 102 insertions(+), 18 deletions(-) diff --git a/include/omath/engines/Source/Camera.hpp b/include/omath/engines/Source/Camera.hpp index 7298cfe..53641f2 100644 --- a/include/omath/engines/Source/Camera.hpp +++ b/include/omath/engines/Source/Camera.hpp @@ -13,7 +13,7 @@ namespace omath::source Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort, const Angle& fov, float near, float far); void LookAt(const Vector3& target) override; - [[nodiscard]] Mat4x4 GetViewMatrix() const override; - [[nodiscard]] Mat4x4 GetProjectionMatrix() const override; + [[nodiscard]] Mat4x4 CalcViewMatrix() const override; + [[nodiscard]] Mat4x4 CalcProjectionMatrix() const override; }; } \ No newline at end of file diff --git a/include/omath/projection/Camera.hpp b/include/omath/projection/Camera.hpp index 1b93b4a..381aee6 100644 --- a/include/omath/projection/Camera.hpp +++ b/include/omath/projection/Camera.hpp @@ -29,7 +29,6 @@ namespace omath::projection template class Camera { - public: virtual ~Camera() = default; Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort, @@ -42,18 +41,82 @@ namespace omath::projection virtual void LookAt(const Vector3& target) = 0; - [[nodiscard]] virtual Mat4x4Type GetViewMatrix() const = 0; + [[nodiscard]] virtual Mat4x4Type CalcViewMatrix() const = 0; - [[nodiscard]] virtual Mat4x4Type GetProjectionMatrix() const = 0; + [[nodiscard]] virtual Mat4x4Type CalcProjectionMatrix() const = 0; - [[nodiscard]] Mat4x4Type GetViewProjectionMatrix() + [[nodiscard]] Mat4x4Type CalcViewProjectionMatrix() const { - return GetProjectionMatrix() * GetViewMatrix(); + return CalcProjectionMatrix() * CalcViewMatrix(); } - [[nodiscard]] std::expected WorldToScreen(const Mat4x4Type& viewProj, const Vector3& worldPosition) const + void SetFieldOfView(const FieldOfView& fov) { - auto projected = viewProj * MatColumnFromVector(worldPosition); + m_fieldOfView = fov; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + void SetNearPlane(const float near) + { + m_nearPlaneDistance = near; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + void SetFarPlane(const float far) + { + m_farPlaneDistance = far; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + void SetViewAngles(const ViewAnglesType& viewAngles) + { + m_viewAngles = viewAngles; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + void SetOrigin(const Vector3& origin) + { + m_origin = origin; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + void SetViewPort(const ViewPort& viewPort) + { + m_viewPort = viewPort; + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + } + + [[nodiscard]] const FieldOfView& GetFieldOfView() const + { + return m_fieldOfView; + } + + [[nodiscard]] const float& GetNearPlane() const + { + return m_nearPlaneDistance; + } + + [[nodiscard]] const float& GetFarPlane() const + { + return m_farPlaneDistance; + } + + [[nodiscard]] const ViewAnglesType& GetViewAngles() const + { + return m_viewAngles; + } + + [[nodiscard]] const Vector3& GetOrigin() const + { + return m_origin; + } + + [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const + { + if (!m_viewProjectionMatrix.has_value()) + m_viewProjectionMatrix = CalcViewProjectionMatrix(); + + auto projected = m_viewProjectionMatrix.value() * MatColumnFromVector(worldPosition); if (projected.At(3, 0) == 0.0f) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); @@ -70,6 +133,8 @@ namespace omath::projection ViewPort m_viewPort{}; Angle m_fieldOfView; + mutable std::optional m_viewProjectionMatrix; + float m_farPlaneDistance; float m_nearPlaneDistance; diff --git a/source/engines/Source/Camera.cpp b/source/engines/Source/Camera.cpp index 51eb507..370e2bd 100644 --- a/source/engines/Source/Camera.cpp +++ b/source/engines/Source/Camera.cpp @@ -24,12 +24,12 @@ namespace omath::source m_viewAngles.roll = RollAngle::FromRadians(0.f); } - Mat4x4 Camera::GetViewMatrix() const + Mat4x4 Camera::CalcViewMatrix() const { - return CalcViewMatrix(m_viewAngles, m_origin); + return source::CalcViewMatrix(m_viewAngles, m_origin); } - Mat4x4 Camera::GetProjectionMatrix() const + Mat4x4 Camera::CalcProjectionMatrix() const { return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); } diff --git a/tests/engines/UnitTestSourceEngine.cpp b/tests/engines/UnitTestSourceEngine.cpp index 4d641a1..2313ae3 100644 --- a/tests/engines/UnitTestSourceEngine.cpp +++ b/tests/engines/UnitTestSourceEngine.cpp @@ -27,17 +27,15 @@ TEST(UnitTestSourceEngine, UpVector) EXPECT_EQ(up, omath::source::kAbsUp); } -TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter) +TEST(UnitTestSourceEngine, ProjectTargetMovedFromCamera) { constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); - const auto viewProjMatrix = cam.GetViewProjectionMatrix(); - for (float distance = 0.02f; distance < 1000.f; distance += 0.01f) { - const auto projected = cam.WorldToScreen(viewProjMatrix, {distance, 0, 0}); + const auto projected = cam.WorldToScreen({distance, 0, 0}); EXPECT_TRUE(projected.has_value()); @@ -47,4 +45,25 @@ TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter) EXPECT_NEAR(projected->x, 960, 0.00001f); EXPECT_NEAR(projected->y, 540, 0.00001f); } +} + +TEST(UnitTestSourceEngine, CameraSetAndGetFov) +{ + constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); + auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f); + cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f)); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f); +} + +TEST(UnitTestSourceEngine, CameraSetAndGetOrigin) +{ + auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f); + + EXPECT_EQ(cam.GetOrigin(), omath::Vector3{}); + cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f)); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f); } \ No newline at end of file diff --git a/tests/general/UnitTestProjection.cpp b/tests/general/UnitTestProjection.cpp index ab8b71c..3d9b507 100644 --- a/tests/general/UnitTestProjection.cpp +++ b/tests/general/UnitTestProjection.cpp @@ -10,9 +10,9 @@ TEST(UnitTestProjection, Projection) { - auto x = omath::Angle::FromDegrees(90.f); + const auto x = omath::Angle::FromDegrees(90.f); auto cam = omath::source::Camera({0, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.01f, 1000.f); - const auto projected = cam.WorldToScreen(cam.GetViewProjectionMatrix(), {1000, 0, 50}); + const auto projected = cam.WorldToScreen({1000, 0, 50}); std::print("{} {} {}", projected->x, projected->y, projected->z); } \ No newline at end of file