mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-14 07:23:26 +00:00
Refactors projectile prediction engine
Migrates projectile prediction logic to leverage engine traits for improved flexibility and testability. This change decouples core prediction algorithms from specific engine implementations, allowing for easier adaptation to different game engines or simulation environments.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "engine_traits/source_engine_trait.hpp"
|
||||
#include "omath/projectile_prediction/proj_pred_engine.hpp"
|
||||
#include "omath/projectile_prediction/projectile.hpp"
|
||||
#include "omath/projectile_prediction/target.hpp"
|
||||
@@ -13,15 +14,40 @@
|
||||
namespace omath::projectile_prediction
|
||||
{
|
||||
// ReSharper disable once CppClassCanBeFinal
|
||||
template<class EngineTrait = traits::SourceEngineTrait>
|
||||
class ProjPredEngineLegacy : public ProjPredEngineInterface
|
||||
{
|
||||
public:
|
||||
explicit ProjPredEngineLegacy(float gravity_constant, float simulation_time_step, float maximum_simulation_time,
|
||||
float distance_tolerance);
|
||||
explicit ProjPredEngineLegacy(const float gravity_constant, const float simulation_time_step,
|
||||
const float maximum_simulation_time, const float distance_tolerance)
|
||||
: m_gravity_constant(gravity_constant), m_simulation_time_step(simulation_time_step),
|
||||
m_maximum_simulation_time(maximum_simulation_time), m_distance_tolerance(distance_tolerance)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
||||
const Target& target) const override;
|
||||
const Target& target) const override
|
||||
{
|
||||
for (float time = 0.f; time < m_maximum_simulation_time; time += m_simulation_time_step)
|
||||
{
|
||||
const auto predicted_target_position = target.predict_position(time, m_gravity_constant);
|
||||
|
||||
const auto projectile_pitch =
|
||||
maybe_calculate_projectile_launch_pitch_angle(projectile, predicted_target_position);
|
||||
|
||||
if (!projectile_pitch.has_value()) [[unlikely]]
|
||||
continue;
|
||||
|
||||
if (!EngineTrait::is_projectile_reached_target(predicted_target_position, projectile,
|
||||
projectile_pitch.value(), time, m_gravity_constant,
|
||||
m_distance_tolerance))
|
||||
continue;
|
||||
|
||||
return EngineTrait::calc_viewpoint_from_angles(projectile, predicted_target_position, projectile_pitch);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
const float m_gravity_constant;
|
||||
@@ -44,30 +70,27 @@ namespace omath::projectile_prediction
|
||||
[[nodiscard]]
|
||||
std::optional<float>
|
||||
maybe_calculate_projectile_launch_pitch_angle(const Projectile& projectile,
|
||||
const Vector3<float>& target_position) const noexcept;
|
||||
const Vector3<float>& target_position) const noexcept
|
||||
{
|
||||
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
||||
const auto delta = target_position - projectile.m_origin;
|
||||
|
||||
[[nodiscard]]
|
||||
bool is_projectile_reached_target(const Vector3<float>& target_position, const Projectile& projectile,
|
||||
float pitch, float time) const noexcept;
|
||||
const auto distance2d = EngineTrait::calc_vector_2d_distance(delta);
|
||||
const auto distance2d_sqr = distance2d * distance2d;
|
||||
const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed;
|
||||
|
||||
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<float>& delta) const;
|
||||
float root = launch_speed_sqr * launch_speed_sqr
|
||||
- bullet_gravity
|
||||
* (bullet_gravity * distance2d_sqr
|
||||
+ 2.0f * EngineTrait::get_vector_height_coordinate(delta) * launch_speed_sqr);
|
||||
|
||||
[[nodiscard]]
|
||||
virtual float get_vector_height_coordinate(const Vector3<float>& vec) const;
|
||||
if (root < 0.0f) [[unlikely]]
|
||||
return std::nullopt;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual Vector3<float> calc_viewpoint_from_angles(const Projectile& projectile,
|
||||
Vector3<float> predicted_target_position,
|
||||
std::optional<float> projectile_pitch) const;
|
||||
root = std::sqrt(root);
|
||||
const float angle = std::atan((launch_speed_sqr - root) / (bullet_gravity * distance2d));
|
||||
|
||||
[[nodiscard]]
|
||||
virtual Vector3<float> predict_projectile_position(const Projectile& projectile, float pitch, float yaw,
|
||||
float time, float gravity) const;
|
||||
// ===============================================================================================
|
||||
return angles::radians_to_degrees(angle);
|
||||
}
|
||||
};
|
||||
} // namespace omath::projectile_prediction
|
||||
|
||||
Reference in New Issue
Block a user