From f1fbea21a7f3ef1d27cc2050a09fa8abebc040b3 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 3 Aug 2025 17:33:22 +0300 Subject: [PATCH] Refactors projectile prediction engine Refactors the projectile prediction engine by introducing an interface and making the legacy implementation more flexible. The legacy engine is updated to allow for coordinate system customization through virtual methods, enabling usage in different game environments. Also introduces vcpkg support for easier dependency management and adds boost-asio as a dependency. --- .../proj_pred_engine.hpp | 4 +- .../proj_pred_engine_avx2.hpp | 2 +- .../proj_pred_engine_legacy.hpp | 23 +++++++++- .../projectile_prediction/projectile.hpp | 3 -- .../proj_pred_engine_legacy.cpp | 45 ++++++++++++++++--- source/projectile_prediction/projectile.cpp | 12 ----- 6 files changed, 63 insertions(+), 26 deletions(-) diff --git a/include/omath/projectile_prediction/proj_pred_engine.hpp b/include/omath/projectile_prediction/proj_pred_engine.hpp index e4be97e..5117c8b 100644 --- a/include/omath/projectile_prediction/proj_pred_engine.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine.hpp @@ -8,12 +8,12 @@ namespace omath::projectile_prediction { - class ProjPredEngine + class ProjPredEngineInterface { public: [[nodiscard]] virtual std::optional> maybe_calculate_aim_point(const Projectile& projectile, const Target& target) const = 0; - virtual ~ProjPredEngine() = default; + virtual ~ProjPredEngineInterface() = default; }; } // namespace omath::projectile_prediction diff --git a/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp b/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp index 59d0592..e4a7dc5 100644 --- a/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp @@ -6,7 +6,7 @@ namespace omath::projectile_prediction { - class ProjPredEngineAvx2 final : public ProjPredEngine + class ProjPredEngineAvx2 final : public ProjPredEngineInterface { public: [[nodiscard]] std::optional> diff --git a/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp b/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp index 8a72ee9..4de7a8c 100644 --- a/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp @@ -12,7 +12,8 @@ namespace omath::projectile_prediction { - class ProjPredEngineLegacy final : public ProjPredEngine + // ReSharper disable once CppClassCanBeFinal + class ProjPredEngineLegacy : public ProjPredEngineInterface { public: explicit ProjPredEngineLegacy(float gravity_constant, float simulation_time_step, float maximum_simulation_time, @@ -48,5 +49,25 @@ namespace omath::projectile_prediction [[nodiscard]] bool is_projectile_reached_target(const Vector3& target_position, const Projectile& projectile, float pitch, float time) const noexcept; + + protected: + // NOTE: Override this if you need to use engine with different coordinate system + // Like where Z is not height coordinate + // =============================================================================================== + [[nodiscard]] + virtual float calc_vector_2d_distance(const Vector3& delta) const; + + [[nodiscard]] + virtual float get_vector_height_coordinate(const Vector3& vec) const; + + [[nodiscard]] + virtual Vector3 calc_viewpoint_from_angles(const Projectile& projectile, + Vector3 predicted_target_position, + std::optional projectile_pitch) const; + + [[nodiscard]] + virtual Vector3 predict_projectile_position(const Projectile& projectile, float pitch, float yaw, + float time, float gravity) const; + // =============================================================================================== }; } // namespace omath::projectile_prediction diff --git a/include/omath/projectile_prediction/projectile.hpp b/include/omath/projectile_prediction/projectile.hpp index ee0cafd..b772712 100644 --- a/include/omath/projectile_prediction/projectile.hpp +++ b/include/omath/projectile_prediction/projectile.hpp @@ -10,9 +10,6 @@ namespace omath::projectile_prediction class Projectile final { public: - [[nodiscard]] - Vector3 predict_position(float pitch, float yaw, float time, float gravity) const noexcept; - Vector3 m_origin; float m_launch_speed{}; float m_gravity_scale{}; diff --git a/source/projectile_prediction/proj_pred_engine_legacy.cpp b/source/projectile_prediction/proj_pred_engine_legacy.cpp index b2f5c7d..96fd7a0 100644 --- a/source/projectile_prediction/proj_pred_engine_legacy.cpp +++ b/source/projectile_prediction/proj_pred_engine_legacy.cpp @@ -27,10 +27,7 @@ namespace omath::projectile_prediction if (!is_projectile_reached_target(predicted_target_position, projectile, projectile_pitch.value(), time)) continue; - const auto delta2d = (predicted_target_position - projectile.m_origin).length_2d(); - const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value())); - - return Vector3(predicted_target_position.x, predicted_target_position.y, projectile.m_origin.z + height); + return calc_viewpoint_from_angles(projectile, predicted_target_position, projectile_pitch); } return std::nullopt; } @@ -41,12 +38,14 @@ namespace omath::projectile_prediction const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale; const auto delta = target_position - projectile.m_origin; - const auto distance2d = delta.length_2d(); + const auto distance2d = calc_vector_2d_distance(delta); const auto distance2d_sqr = distance2d * distance2d; const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed; float root = launch_speed_sqr * launch_speed_sqr - - bullet_gravity * (bullet_gravity * distance2d_sqr + 2.0f * delta.z * launch_speed_sqr); + - bullet_gravity + * (bullet_gravity * distance2d_sqr + + 2.0f * get_vector_height_coordinate(delta) * launch_speed_sqr); if (root < 0.0f) [[unlikely]] return std::nullopt; @@ -62,8 +61,40 @@ namespace omath::projectile_prediction const float time) const noexcept { const auto yaw = projectile.m_origin.view_angle_to(target_position).y; - const auto projectile_position = projectile.predict_position(pitch, yaw, time, m_gravity_constant); + const auto projectile_position = predict_projectile_position(projectile, pitch, yaw, time, m_gravity_constant); return projectile_position.distance_to(target_position) <= m_distance_tolerance; } + + float ProjPredEngineLegacy::calc_vector_2d_distance(const Vector3& delta) const + { + return std::sqrt(delta.x * delta.x + delta.y * delta.y); + } + + float ProjPredEngineLegacy::get_vector_height_coordinate(const Vector3& vec) const + { + return vec.z; + } + Vector3 ProjPredEngineLegacy::calc_viewpoint_from_angles(const Projectile& projectile, + const Vector3 predicted_target_position, + const std::optional projectile_pitch) const + { + const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin); + const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value())); + + return {predicted_target_position.x, predicted_target_position.y, projectile.m_origin.z + height}; + } + Vector3 ProjPredEngineLegacy::predict_projectile_position(const Projectile& projectile, const float pitch, + const float yaw, const float time, + const float gravity) const + { + auto current_pos = projectile.m_origin + + source_engine::forward_vector({source_engine::PitchAngle::from_degrees(-pitch), + source_engine::YawAngle::from_degrees(yaw), + source_engine::RollAngle::from_degrees(0)}) + * projectile.m_launch_speed * time; + current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f; + + return current_pos; + } } // namespace omath::projectile_prediction diff --git a/source/projectile_prediction/projectile.cpp b/source/projectile_prediction/projectile.cpp index c37151f..c37daaa 100644 --- a/source/projectile_prediction/projectile.cpp +++ b/source/projectile_prediction/projectile.cpp @@ -7,16 +7,4 @@ namespace omath::projectile_prediction { - Vector3 Projectile::predict_position(const float pitch, const float yaw, const float time, - const float gravity) const noexcept - { - auto current_pos = m_origin - + source_engine::forward_vector({source_engine::PitchAngle::from_degrees(-pitch), - source_engine::YawAngle::from_degrees(yaw), - source_engine::RollAngle::from_degrees(0)}) - * m_launch_speed * time; - current_pos.z -= (gravity * m_gravity_scale) * (time * time) * 0.5f; - - return current_pos; - } } // namespace omath::projectile_prediction