From 11b2129d6d6b851af46f77d9e9e50103bdb4081a Mon Sep 17 00:00:00 2001 From: Orange Date: Wed, 5 Aug 2026 21:37:18 +0300 Subject: [PATCH] improved radar --- include/omath/algorithm/radar.hpp | 36 +++++++++++++++++++++------- tests/general/unit_test_radar.cpp | 40 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/include/omath/algorithm/radar.hpp b/include/omath/algorithm/radar.hpp index 6c59ff9..f9c7b8a 100644 --- a/include/omath/algorithm/radar.hpp +++ b/include/omath/algorithm/radar.hpp @@ -3,6 +3,8 @@ // #pragma once #include "omath/linear_algebra/vector3.hpp" +#include +#include #include namespace omath::algorithm @@ -10,7 +12,10 @@ namespace omath::algorithm template requires std::is_floating_point_v [[nodiscard]] - constexpr Vector2 world_to_radar(const Camera& camera, const Vector3& position, const FloatingType scale) + constexpr Vector2 world_to_radar( + const Camera& camera, const Vector3& position, const FloatingType scale, + const std::optional&, const Vector3&)>> + calc_distance = std::nullopt) { const auto look_at_angles = camera.calc_look_at_angles(position); const auto current_angles = camera.get_view_angles(); @@ -18,25 +23,40 @@ namespace omath::algorithm if consteval { const auto right_yaw = current_angles.yaw - - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw - - decltype(current_angles.yaw)::from_degrees(90); - const auto sign = right_yaw.cos() < 0 ? -1.f : 1.f; + - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw + - decltype(current_angles.yaw)::from_degrees(90); + const auto sign = right_yaw.cos() < 0 ? -1.f : 1.f; const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90); + + auto distance = FloatingType{0}; + + if (calc_distance.has_value()) + distance = calc_distance.value()(camera.get_origin(), position); + else + distance = camera.get_origin().distance_to(position); + return omath::Vector2(static_cast(yaw.cos()) * sign, static_cast(yaw.sin())) - * (camera.get_origin().distance_to(position) * scale); + * (distance * scale); } static const auto sign = [&camera, ¤t_angles] { const auto right_yaw = current_angles.yaw - - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw - - decltype(current_angles.yaw)::from_degrees(90); + - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw + - decltype(current_angles.yaw)::from_degrees(90); return right_yaw.cos() < 0 ? -1.f : 1.f; }(); const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90); + auto distance = FloatingType{0}; + + if (calc_distance.has_value()) + distance = calc_distance.value()(camera.get_origin(), position); + else + distance = camera.get_origin().distance_to(position); + return omath::Vector2(static_cast(yaw.cos()) * sign, static_cast(yaw.sin())) - * (camera.get_origin().distance_to(position) * scale); + * (distance * scale); } } // namespace omath::algorithm diff --git a/tests/general/unit_test_radar.cpp b/tests/general/unit_test_radar.cpp index 4b75080..c8eedc7 100644 --- a/tests/general/unit_test_radar.cpp +++ b/tests/general/unit_test_radar.cpp @@ -91,6 +91,38 @@ static void verify_world_to_radar_ignores_camera_pitch(const Vector3 +static void verify_world_to_radar_uses_custom_distance(const Vector3& world_forward) +{ + const Vector3 origin{NumericType{10}, NumericType{-20}, NumericType{5}}; + const NumericType world_distance = NumericType{20}; + const NumericType custom_distance = NumericType{6}; + const NumericType scale = NumericType{0.5}; + const auto radar_distance = static_cast(custom_distance * scale); + + CameraType camera{ + origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01}, + NumericType{1000}}; + + const auto forward_position = origin + world_forward * world_distance; + auto custom_distance_called = false; + const std::optional&, const Vector3&)>> + calc_distance{[&custom_distance_called, &origin, &forward_position, + custom_distance](const Vector3& distance_origin, + const Vector3& distance_position) + { + custom_distance_called = true; + EXPECT_EQ(distance_origin, origin); + EXPECT_EQ(distance_position, forward_position); + return custom_distance; + }}; + const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale, calc_distance); + + EXPECT_TRUE(custom_distance_called); + EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f); + EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f); +} + TEST(WorldToRadarTests, SourceEngineCamera) { verify_world_to_radar_uses_engine_world_axes(source_engine::k_abs_forward, @@ -98,6 +130,7 @@ TEST(WorldToRadarTests, SourceEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(-90.f, source_engine::k_abs_forward, source_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(source_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(source_engine::k_abs_forward); } TEST(WorldToRadarTests, IWEngineCamera) @@ -107,6 +140,7 @@ TEST(WorldToRadarTests, IWEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(-90.f, iw_engine::k_abs_forward, iw_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(iw_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(iw_engine::k_abs_forward); } TEST(WorldToRadarTests, FrostbiteEngineCamera) @@ -116,6 +150,7 @@ TEST(WorldToRadarTests, FrostbiteEngineCamera) verify_world_to_radar_uses_changed_camera_yaw( 90.f, frostbite_engine::k_abs_forward, frostbite_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(frostbite_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(frostbite_engine::k_abs_forward); } TEST(WorldToRadarTests, OpenGLEngineCamera) @@ -125,6 +160,7 @@ TEST(WorldToRadarTests, OpenGLEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(-90.f, opengl_engine::k_abs_forward, opengl_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(opengl_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(opengl_engine::k_abs_forward); } TEST(WorldToRadarTests, UnityEngineCamera) @@ -134,6 +170,7 @@ TEST(WorldToRadarTests, UnityEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(90.f, unity_engine::k_abs_forward, unity_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(unity_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(unity_engine::k_abs_forward); } TEST(WorldToRadarTests, CryEngineCamera) @@ -143,6 +180,7 @@ TEST(WorldToRadarTests, CryEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(-90.f, cry_engine::k_abs_forward, cry_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(cry_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(cry_engine::k_abs_forward); } TEST(WorldToRadarTests, RageEngineCamera) @@ -152,6 +190,7 @@ TEST(WorldToRadarTests, RageEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(-90.f, rage_engine::k_abs_forward, rage_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(rage_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(rage_engine::k_abs_forward); } TEST(WorldToRadarTests, UnrealEngineCamera) @@ -161,4 +200,5 @@ TEST(WorldToRadarTests, UnrealEngineCamera) verify_world_to_radar_uses_changed_camera_yaw(90.f, unreal_engine::k_abs_forward, unreal_engine::k_abs_right); verify_world_to_radar_ignores_camera_pitch(unreal_engine::k_abs_forward); + verify_world_to_radar_uses_custom_distance(unreal_engine::k_abs_forward); }