From 792db7a6731bacb9be789761be6e8de7559d9126 Mon Sep 17 00:00:00 2001 From: Orange Date: Sat, 20 Sep 2025 02:09:59 +0300 Subject: [PATCH] added new mat function more tests --- .../engines/iw_engine/traits/camera_trait.hpp | 2 +- .../opengl_engine/traits/camera_trait.hpp | 2 +- .../source_engine/traits/camera_trait.hpp | 2 +- .../unity_engine/traits/camera_trait.hpp | 2 +- .../unreal_engine/traits/camera_trait.hpp | 2 +- include/omath/linear_algebra/mat.hpp | 17 +++ include/omath/projection/camera.hpp | 9 +- .../engines/iw_engine/traits/camera_trait.cpp | 8 +- .../opengl_engine/traits/camera_trait.cpp | 8 +- .../source_engine/traits/camera_trait.cpp | 8 +- .../unity_engine/traits/camera_trait.cpp | 8 +- .../unreal_engine/traits/camera_trait.cpp | 8 +- tests/engines/unit_test_open_gl.cpp | 109 +++++++++++++++++- tests/engines/unit_test_unity_engine.cpp | 109 ++++++++++++++++++ tests/engines/unit_test_unreal_engine.cpp | 108 +++++++++++++++++ 15 files changed, 362 insertions(+), 40 deletions(-) diff --git a/include/omath/engines/iw_engine/traits/camera_trait.hpp b/include/omath/engines/iw_engine/traits/camera_trait.hpp index 88c2156..805e2ea 100644 --- a/include/omath/engines/iw_engine/traits/camera_trait.hpp +++ b/include/omath/engines/iw_engine/traits/camera_trait.hpp @@ -12,7 +12,7 @@ namespace omath::iw_engine { public: [[nodiscard]] - static ViewAngles calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept; + static Mat4X4 calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept; [[nodiscard]] static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept; diff --git a/include/omath/engines/opengl_engine/traits/camera_trait.hpp b/include/omath/engines/opengl_engine/traits/camera_trait.hpp index 3fb57c0..2ea734e 100644 --- a/include/omath/engines/opengl_engine/traits/camera_trait.hpp +++ b/include/omath/engines/opengl_engine/traits/camera_trait.hpp @@ -12,7 +12,7 @@ namespace omath::opengl_engine { public: [[nodiscard]] - static ViewAngles calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept; + static Mat4X4 calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept; [[nodiscard]] static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept; diff --git a/include/omath/engines/source_engine/traits/camera_trait.hpp b/include/omath/engines/source_engine/traits/camera_trait.hpp index d027d25..999f9f5 100644 --- a/include/omath/engines/source_engine/traits/camera_trait.hpp +++ b/include/omath/engines/source_engine/traits/camera_trait.hpp @@ -12,7 +12,7 @@ namespace omath::source_engine { public: [[nodiscard]] - static ViewAngles calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept; + static Mat4X4 calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept; [[nodiscard]] static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept; diff --git a/include/omath/engines/unity_engine/traits/camera_trait.hpp b/include/omath/engines/unity_engine/traits/camera_trait.hpp index 2d98b9d..c5a6169 100644 --- a/include/omath/engines/unity_engine/traits/camera_trait.hpp +++ b/include/omath/engines/unity_engine/traits/camera_trait.hpp @@ -12,7 +12,7 @@ namespace omath::unity_engine { public: [[nodiscard]] - static ViewAngles calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept; + static Mat4X4 calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept; [[nodiscard]] static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept; diff --git a/include/omath/engines/unreal_engine/traits/camera_trait.hpp b/include/omath/engines/unreal_engine/traits/camera_trait.hpp index f2de27e..35dc8ae 100644 --- a/include/omath/engines/unreal_engine/traits/camera_trait.hpp +++ b/include/omath/engines/unreal_engine/traits/camera_trait.hpp @@ -12,7 +12,7 @@ namespace omath::unreal_engine { public: [[nodiscard]] - static ViewAngles calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept; + static Mat4X4 calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept; [[nodiscard]] static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept; diff --git a/include/omath/linear_algebra/mat.hpp b/include/omath/linear_algebra/mat.hpp index 99c6081..50d6cf7 100644 --- a/include/omath/linear_algebra/mat.hpp +++ b/include/omath/linear_algebra/mat.hpp @@ -675,6 +675,23 @@ namespace omath { 0.f, 0.f, 0.f, 1.f } }; } + template + Mat<4, 4, T, St> mat_look_at_left_handed(const Vector3& eye, const Vector3& center, const Vector3& up) + { + const Vector3 f = (center - eye).normalized(); + const Vector3 s = f.cross(up).normalized(); + const Vector3 u = s.cross(f); + return mat_camera_view(f, s, u, eye); + } + + template + Mat<4, 4, T, St>mat_look_at_right_handed(const Vector3& eye, const Vector3& center, const Vector3& up) + { + const Vector3 f = (center - eye).normalized(); + const Vector3 s = f.cross(up).normalized(); + const Vector3 u = s.cross(f); + return mat_camera_view(-f, s, u, eye); + } } // namespace omath diff --git a/include/omath/projection/camera.hpp b/include/omath/projection/camera.hpp index 7d7feb1..38917b1 100644 --- a/include/omath/projection/camera.hpp +++ b/include/omath/projection/camera.hpp @@ -36,12 +36,12 @@ namespace omath::projection requires(const Vector3& cam_origin, const Vector3& look_at, const ViewAnglesType& angles, const FieldOfView& fov, const ViewPort& viewport, float znear, float zfar) { // Presence + return types - { T::calc_look_at_angle(cam_origin, look_at) } -> std::same_as; + { T::calc_look_at_mat(cam_origin, look_at) } -> std::same_as; { T::calc_view_matrix(angles, cam_origin) } -> std::same_as; { T::calc_projection_matrix(fov, viewport, znear, zfar) } -> std::same_as; // Enforce noexcept as in the trait declaration - requires noexcept(T::calc_look_at_angle(cam_origin, look_at)); + requires noexcept(T::calc_look_at_mat(cam_origin, look_at)); requires noexcept(T::calc_view_matrix(angles, cam_origin)); requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar)); }; @@ -64,8 +64,9 @@ namespace omath::projection void look_at(const Vector3& target) { - m_view_angles = TraitClass::calc_look_at_angle(m_origin, target); - m_view_projection_matrix = std::nullopt; + m_view_projection_matrix = TraitClass::calc_projection_matrix(m_field_of_view, m_view_port, + m_near_plane_distance, m_far_plane_distance) + * TraitClass::calc_look_at_mat(m_origin, target); } protected: diff --git a/source/engines/iw_engine/traits/camera_trait.cpp b/source/engines/iw_engine/traits/camera_trait.cpp index a791751..7531cd8 100644 --- a/source/engines/iw_engine/traits/camera_trait.cpp +++ b/source/engines/iw_engine/traits/camera_trait.cpp @@ -6,13 +6,9 @@ namespace omath::iw_engine { - ViewAngles CameraTrait::calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept + Mat4X4 CameraTrait::calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept { - const auto distance = cam_origin.distance_to(look_at); - const auto delta = look_at - cam_origin; - - return {PitchAngle::from_radians(-std::asin(delta.z / distance)), - YawAngle::from_radians(std::atan2(delta.y, delta.x)), RollAngle::from_radians(0.f)}; + return mat_look_at_left_handed(cam_origin, look_at, k_abs_up); } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/source/engines/opengl_engine/traits/camera_trait.cpp b/source/engines/opengl_engine/traits/camera_trait.cpp index 24970cb..1fac148 100644 --- a/source/engines/opengl_engine/traits/camera_trait.cpp +++ b/source/engines/opengl_engine/traits/camera_trait.cpp @@ -7,13 +7,9 @@ namespace omath::opengl_engine { - ViewAngles CameraTrait::calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept + Mat4X4 CameraTrait::calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept { - const auto distance = cam_origin.distance_to(look_at); - const auto delta = look_at - cam_origin; - - return {PitchAngle::from_radians(std::asin(delta.y / distance)), - YawAngle::from_radians(std::atan2(delta.x, -delta.z)), RollAngle::from_radians(0.f)}; + return mat_look_at_right_handed(cam_origin, look_at, k_abs_up); } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/source/engines/source_engine/traits/camera_trait.cpp b/source/engines/source_engine/traits/camera_trait.cpp index 4f49a3e..6af732d 100644 --- a/source/engines/source_engine/traits/camera_trait.cpp +++ b/source/engines/source_engine/traits/camera_trait.cpp @@ -6,13 +6,9 @@ namespace omath::source_engine { - ViewAngles CameraTrait::calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept + Mat4X4 CameraTrait::calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept { - const auto distance = cam_origin.distance_to(look_at); - const auto delta = look_at - cam_origin; - - return {PitchAngle::from_radians(-std::asin(delta.z / distance)), - YawAngle::from_radians(std::atan2(delta.y, delta.x)), RollAngle::from_radians(0.f)}; + return mat_look_at_left_handed(cam_origin, look_at, k_abs_up); } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/source/engines/unity_engine/traits/camera_trait.cpp b/source/engines/unity_engine/traits/camera_trait.cpp index d76426b..7b1ec35 100644 --- a/source/engines/unity_engine/traits/camera_trait.cpp +++ b/source/engines/unity_engine/traits/camera_trait.cpp @@ -6,13 +6,9 @@ namespace omath::unity_engine { - ViewAngles CameraTrait::calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept + Mat4X4 CameraTrait::calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept { - const auto distance = cam_origin.distance_to(look_at); - const auto delta = cam_origin - look_at; - - return {PitchAngle::from_radians(-std::asin(delta.y / distance)), - YawAngle::from_radians(std::atan2(delta.z, delta.x)), RollAngle::from_radians(0.f)}; + return mat_look_at_left_handed(cam_origin, look_at, k_abs_up); } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/source/engines/unreal_engine/traits/camera_trait.cpp b/source/engines/unreal_engine/traits/camera_trait.cpp index 5eb8126..dfc4e78 100644 --- a/source/engines/unreal_engine/traits/camera_trait.cpp +++ b/source/engines/unreal_engine/traits/camera_trait.cpp @@ -6,13 +6,9 @@ namespace omath::unreal_engine { - ViewAngles CameraTrait::calc_look_at_angle(const Vector3& cam_origin, const Vector3& look_at) noexcept + Mat4X4 CameraTrait::calc_look_at_mat(const Vector3& cam_origin, const Vector3& look_at) noexcept { - const auto distance = cam_origin.distance_to(look_at); - const auto delta = cam_origin - look_at; - - return {PitchAngle::from_radians(-std::asin(delta.z / distance)), - YawAngle::from_radians(std::atan2(delta.x, delta.y)), RollAngle::from_radians(0.f)}; + return mat_look_at_left_handed(cam_origin, look_at, k_abs_up); } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/tests/engines/unit_test_open_gl.cpp b/tests/engines/unit_test_open_gl.cpp index 89506e6..57ddb5f 100644 --- a/tests/engines/unit_test_open_gl.cpp +++ b/tests/engines/unit_test_open_gl.cpp @@ -5,7 +5,7 @@ #include #include #include - +#include TEST(unit_test_opengl, ForwardVector) { @@ -102,4 +102,111 @@ TEST(unit_test_opengl, CameraSetAndGetOrigin) cam.set_field_of_view(omath::projection::FieldOfView::from_degrees(50.f)); EXPECT_EQ(cam.get_field_of_view().as_degrees(), 50.f); +} +TEST(unit_test_opengl_engine, loook_at_random_all_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 100; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), dist(gen), dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_opengl_engine, loook_at_random_x_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), 0.f, 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_opengl_engine, loook_at_random_y_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, dist(gen), 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_opengl_engine, loook_at_random_z_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, 0.f, dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.025f); + } } \ No newline at end of file diff --git a/tests/engines/unit_test_unity_engine.cpp b/tests/engines/unit_test_unity_engine.cpp index 47ce136..faad096 100644 --- a/tests/engines/unit_test_unity_engine.cpp +++ b/tests/engines/unit_test_unity_engine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include TEST(unit_test_unity_engine, ForwardVector) { @@ -112,4 +113,112 @@ TEST(unit_test_unity_engine, CameraSetAndGetOrigin) cam.set_field_of_view(omath::projection::FieldOfView::from_degrees(50.f)); EXPECT_EQ(cam.get_field_of_view().as_degrees(), 50.f); + +} +TEST(unit_test_unity_engine, loook_at_random_all_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 100; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), dist(gen), dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unity_engine, loook_at_random_x_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), 0.f, 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unity_engine, loook_at_random_y_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, dist(gen), 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unity_engine, loook_at_random_z_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, 0.f, dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.025f); + } } \ No newline at end of file diff --git a/tests/engines/unit_test_unreal_engine.cpp b/tests/engines/unit_test_unreal_engine.cpp index 0991209..0ad715e 100644 --- a/tests/engines/unit_test_unreal_engine.cpp +++ b/tests/engines/unit_test_unreal_engine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include TEST(unit_test_unreal_engine, ForwardVector) { @@ -102,4 +103,111 @@ TEST(unit_test_unreal_engine, CameraSetAndGetOrigin) cam.set_field_of_view(omath::projection::FieldOfView::from_degrees(50.f)); EXPECT_EQ(cam.get_field_of_view().as_degrees(), 50.f); +} +TEST(unit_test_unreal_engine, loook_at_random_all_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unreal_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 100; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), dist(gen), dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unreal_engine, loook_at_random_x_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unreal_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{dist(gen), 0.f, 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unreal_engine, loook_at_random_y_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unreal_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, dist(gen), 0.f}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.00001f); + } +} + +TEST(unit_test_unreal_engine, loook_at_random_z_axis) +{ + std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source + std::uniform_real_distribution dist(-500.f, 500.f); + + constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); + auto cam = omath::unreal_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f); + + + + for (int i = 0; i < 1000; i++) + { + const auto position_to_look = omath::Vector3{0.f, 0.f, dist(gen)}; + cam.look_at(position_to_look); + + auto projected_pos = cam.world_to_view_port(position_to_look); + + EXPECT_TRUE(projected_pos.has_value()); + + if (!projected_pos) + continue; + + EXPECT_NEAR(projected_pos->x, 0.f, 0.00001f); + EXPECT_NEAR(projected_pos->y, 0.f, 0.025f); + } } \ No newline at end of file