From 5657282577edae3bc426009cd62c422a367a273a Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 21 Oct 2025 02:59:50 +0300 Subject: [PATCH] Fixes incorrect NDC calculation and updates formulas Corrects the NDC calculation in `world_to_screen` to improve accuracy. Replaces custom perspective projection matrix calculation with `omath::mat_perspective_right_handed` for correctness and consistency. Updates test cases and provides debugging information by printing view and projection matrices. Addresses an issue in the feature/ndc_invalid_calc_fix branch. --- include/omath/projection/camera.hpp | 3 ++- source/engines/unity_engine/formulas.cpp | 11 ++--------- tests/engines/unit_test_unity_engine.cpp | 19 +++++++++++++++++-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/omath/projection/camera.hpp b/include/omath/projection/camera.hpp index 2e835da..097a2e2 100644 --- a/include/omath/projection/camera.hpp +++ b/include/omath/projection/camera.hpp @@ -239,7 +239,8 @@ namespace omath::projection -1 | v */ - return {(ndc.x + 1.f) / 2.f * m_view_port.m_width, (1.f - ndc.y) / 2.f * m_view_port.m_height, ndc.z}; + + return {(ndc.x + 1.f) / 2.f * m_view_port.m_width, (ndc.y / 2.f + 0.5f) * m_view_port.m_height, ndc.z}; } [[nodiscard]] Vector3 screen_to_ndc(const Vector3& screen_pos) const noexcept diff --git a/source/engines/unity_engine/formulas.cpp b/source/engines/unity_engine/formulas.cpp index cb603be..f129826 100644 --- a/source/engines/unity_engine/formulas.cpp +++ b/source/engines/unity_engine/formulas.cpp @@ -25,7 +25,7 @@ namespace omath::unity_engine } Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { - return mat_camera_view(forward_vector(angles), -right_vector(angles), + return mat_camera_view(-forward_vector(angles), right_vector(angles), up_vector(angles), cam_origin); } Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept @@ -37,13 +37,6 @@ namespace omath::unity_engine Mat4X4 calc_perspective_projection_matrix(const float field_of_view, const float aspect_ratio, const float near, const float far) noexcept { - const float fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / 2.f); - - return { - {1.f / (aspect_ratio * fov_half_tan), 0, 0, 0}, - {0, 1.f / (fov_half_tan), 0, 0}, - {0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)}, - {0, 0, -1.f, 0}, - }; + return omath::mat_perspective_right_handed(field_of_view, aspect_ratio, near, far); } } // namespace omath::unity_engine diff --git a/tests/engines/unit_test_unity_engine.cpp b/tests/engines/unit_test_unity_engine.cpp index f5e9abd..cddef0b 100644 --- a/tests/engines/unit_test_unity_engine.cpp +++ b/tests/engines/unit_test_unity_engine.cpp @@ -87,9 +87,9 @@ TEST(unit_test_unity_engine, Project) constexpr auto fov = omath::projection::FieldOfView::from_degrees(60.f); const auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.03f, 1000.f); - const auto proj = cam.world_to_screen({5.f, 3, 10.f}); + const auto proj = cam.world_to_screen({10.f, 3, 10.f}); - EXPECT_NEAR(proj->x, 951.769f, 0.001f); + EXPECT_NEAR(proj->x, 1263.538, 0.001f); EXPECT_NEAR(proj->y, 547.061f, 0.001f); } @@ -233,4 +233,19 @@ TEST(unit_test_unity_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); +} + +TEST(unit_test_unity_engine, to_camera_coordiante_syste) +{ + omath::Vector3 point = {10, 3, 10}; + auto result = omath::unity_engine::calc_view_matrix({}, {}) * omath::mat_column_from_vector(point); + auto perspective = omath::unity_engine::calc_perspective_projection_matrix(60, 1280 / 720.f, 0.3, 1000); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(60.f); + + const auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.03f, 1000.f); + + std::println("View matrix: \n{}", cam.get_view_matrix()); + std::println("Projection: \n{}", cam.get_projection_matrix()); + std::print("NDC: projection {} -> {}", point, cam.world_to_screen(point).value()); } \ No newline at end of file