Merge pull request #51 from orange-cpp/feature/projectile_pred_custom

Refactors projectile prediction engine
This commit is contained in:
2025-08-03 17:38:08 +03:00
committed by GitHub
6 changed files with 63 additions and 26 deletions

View File

@@ -8,12 +8,12 @@
namespace omath::projectile_prediction
{
class ProjPredEngine
class ProjPredEngineInterface
{
public:
[[nodiscard]]
virtual std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
const Target& target) const = 0;
virtual ~ProjPredEngine() = default;
virtual ~ProjPredEngineInterface() = default;
};
} // namespace omath::projectile_prediction

View File

@@ -6,7 +6,7 @@
namespace omath::projectile_prediction
{
class ProjPredEngineAvx2 final : public ProjPredEngine
class ProjPredEngineAvx2 final : public ProjPredEngineInterface
{
public:
[[nodiscard]] std::optional<Vector3<float>>

View File

@@ -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<float>& 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<float>& delta) const;
[[nodiscard]]
virtual float get_vector_height_coordinate(const Vector3<float>& vec) const;
[[nodiscard]]
virtual Vector3<float> calc_viewpoint_from_angles(const Projectile& projectile,
Vector3<float> predicted_target_position,
std::optional<float> projectile_pitch) const;
[[nodiscard]]
virtual Vector3<float> predict_projectile_position(const Projectile& projectile, float pitch, float yaw,
float time, float gravity) const;
// ===============================================================================================
};
} // namespace omath::projectile_prediction

View File

@@ -10,9 +10,6 @@ namespace omath::projectile_prediction
class Projectile final
{
public:
[[nodiscard]]
Vector3<float> predict_position(float pitch, float yaw, float time, float gravity) const noexcept;
Vector3<float> m_origin;
float m_launch_speed{};
float m_gravity_scale{};

View File

@@ -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<float>& delta) const
{
return std::sqrt(delta.x * delta.x + delta.y * delta.y);
}
float ProjPredEngineLegacy::get_vector_height_coordinate(const Vector3<float>& vec) const
{
return vec.z;
}
Vector3<float> ProjPredEngineLegacy::calc_viewpoint_from_angles(const Projectile& projectile,
const Vector3<float> predicted_target_position,
const std::optional<float> 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<float> 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

View File

@@ -7,16 +7,4 @@
namespace omath::projectile_prediction
{
Vector3<float> 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