diff --git a/include/omath/projection/camera.hpp b/include/omath/projection/camera.hpp index b386cfb..e0dd8ca 100644 --- a/include/omath/projection/camera.hpp +++ b/include/omath/projection/camera.hpp @@ -36,8 +36,8 @@ namespace omath::projection m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near), m_viewAngles(viewAngles), m_origin(position) { - } + protected: virtual void LookAt(const Vector3& target) = 0; @@ -49,8 +49,8 @@ namespace omath::projection { return CalcProjectionMatrix() * CalcViewMatrix(); } - public: + public: [[nodiscard]] const Mat4x4Type& GetViewProjectionMatrix() const { if (!m_viewProjectionMatrix.has_value()) @@ -116,10 +116,18 @@ namespace omath::projection [[nodiscard]] std::expected, Error> WorldToScreen(const Vector3& worldPosition) const { - const auto& viewProjMatrix = GetViewProjectionMatrix(); - const auto cameraCord = CalcViewMatrix() * MatColumnFromVector(worldPosition);; + auto normalizedCords = WorldToViewPort(worldPosition); - auto projected = CalcProjectionMatrix() * cameraCord; + if (!normalizedCords.has_value()) + return normalizedCords; + + + return NdcToScreenPosition(*normalizedCords); + } + [[nodiscard]] std::expected, Error> WorldToViewPort(const Vector3& worldPosition) const + { + auto projected = GetViewProjectionMatrix() * + MatColumnFromVector(worldPosition); if (projected.At(3, 0) == 0.0f) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); @@ -129,10 +137,7 @@ namespace omath::projection if (IsNdcOutOfBounds(projected)) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); - const auto screenPositionX = (projected.At(0,0)+1.f) / 2.f * m_viewPort.m_width; - const auto screenPositionY = (projected.At(1,0)+1.f) / 2.f * m_viewPort.m_height; - - return Vector3{screenPositionX, screenPositionY, projected.At(2,0)}; + return Vector3{projected.At(0, 0), projected.At(1, 0), projected.At(2, 0)}; } protected: @@ -153,7 +158,17 @@ namespace omath::projection [[nodiscard]] constexpr static bool IsNdcOutOfBounds(const Type& ndc) { - return std::ranges::any_of( ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; }); + return std::ranges::any_of(ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; }); + } + + [[nodiscard]] Vector3 NdcToScreenPosition(const Vector3& ndc) const + { + return + { + (ndc.x + 1.f) / 2.f * m_viewPort.m_width, + (1.f - ndc.y) / 2.f * m_viewPort.m_height, + ndc.z + }; } }; } // namespace omath::projection diff --git a/source/engines/iw_engine/formulas.cpp b/source/engines/iw_engine/formulas.cpp index ec9220d..f4fe076 100644 --- a/source/engines/iw_engine/formulas.cpp +++ b/source/engines/iw_engine/formulas.cpp @@ -26,10 +26,10 @@ namespace omath::iw_engine return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)}; } - + Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin) { - return MatCameraView(ForwardVector(angles), RightVector(angles), -UpVector(angles), cam_origin); + return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin); } Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, diff --git a/source/engines/opengl_engine/formulas.cpp b/source/engines/opengl_engine/formulas.cpp index be1a638..8162bdb 100644 --- a/source/engines/opengl_engine/formulas.cpp +++ b/source/engines/opengl_engine/formulas.cpp @@ -40,7 +40,6 @@ namespace omath::opengl_engine {0, 1.f / (fovHalfTan), 0, 0}, {0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)}, {0, 0, -1, 0}, - }; } } // namespace omath::opengl_engine diff --git a/source/engines/source_engine/formulas.cpp b/source/engines/source_engine/formulas.cpp index 620e9f3..f037cad 100644 --- a/source/engines/source_engine/formulas.cpp +++ b/source/engines/source_engine/formulas.cpp @@ -28,7 +28,7 @@ namespace omath::source_engine Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin) { - return MatCameraView(ForwardVector(angles), RightVector(angles), -UpVector(angles), cam_origin); + return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin); } Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, diff --git a/source/engines/unity_engine/formulas.cpp b/source/engines/unity_engine/formulas.cpp index 2a09d7d..ef85100 100644 --- a/source/engines/unity_engine/formulas.cpp +++ b/source/engines/unity_engine/formulas.cpp @@ -39,7 +39,7 @@ namespace omath::unity_engine {1.f / (aspectRatio * fovHalfTan), 0, 0, 0}, {0, 1.f / (fovHalfTan), 0, 0}, {0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)}, - {0, 0, 1.f, 0}, + {0, 0, -1.f, 0}, }; } diff --git a/tests/engines/unit_test_iw_engine.cpp b/tests/engines/unit_test_iw_engine.cpp index cd42ee4..286d599 100644 --- a/tests/engines/unit_test_iw_engine.cpp +++ b/tests/engines/unit_test_iw_engine.cpp @@ -9,28 +9,28 @@ TEST(UnitTestEwEngine, ForwardVector) { - const auto forward = omath::source_engine::ForwardVector({}); + const auto forward = omath::iw_engine::ForwardVector({}); - EXPECT_EQ(forward, omath::source_engine::kAbsForward); + EXPECT_EQ(forward, omath::iw_engine::kAbsForward); } TEST(UnitTestEwEngine, RightVector) { - const auto right = omath::source_engine::RightVector({}); + const auto right = omath::iw_engine::RightVector({}); - EXPECT_EQ(right, omath::source_engine::kAbsRight); + EXPECT_EQ(right, omath::iw_engine::kAbsRight); } TEST(UnitTestEwEngine, UpVector) { - const auto up = omath::source_engine::UpVector({}); - EXPECT_EQ(up, omath::source_engine::kAbsUp); + const auto up = omath::iw_engine::UpVector({}); + EXPECT_EQ(up, omath::iw_engine::kAbsUp); } TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera) { constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); - const auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); + const auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); for (float distance = 0.02f; distance < 1000.f; distance += 0.01f) @@ -50,7 +50,7 @@ TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera) TEST(UnitTestEwEngine, CameraSetAndGetFov) { constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); - auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); + auto cam = omath::iw_engine::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)); @@ -60,7 +60,7 @@ TEST(UnitTestEwEngine, CameraSetAndGetFov) TEST(UnitTestEwEngine, CameraSetAndGetOrigin) { - auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f); + auto cam = omath::iw_engine::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));