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