mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-14 07:23:26 +00:00
Merge pull request #51 from orange-cpp/feature/projectile_pred_custom
Refactors projectile prediction engine
This commit is contained in:
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngine
|
class ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
virtual std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
||||||
const Target& target) const = 0;
|
const Target& target) const = 0;
|
||||||
virtual ~ProjPredEngine() = default;
|
virtual ~ProjPredEngineInterface() = default;
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngineAvx2 final : public ProjPredEngine
|
class ProjPredEngineAvx2 final : public ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] std::optional<Vector3<float>>
|
[[nodiscard]] std::optional<Vector3<float>>
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngineLegacy final : public ProjPredEngine
|
// ReSharper disable once CppClassCanBeFinal
|
||||||
|
class ProjPredEngineLegacy : public ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ProjPredEngineLegacy(float gravity_constant, float simulation_time_step, float maximum_simulation_time,
|
explicit ProjPredEngineLegacy(float gravity_constant, float simulation_time_step, float maximum_simulation_time,
|
||||||
@@ -48,5 +49,25 @@ namespace omath::projectile_prediction
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool is_projectile_reached_target(const Vector3<float>& target_position, const Projectile& projectile,
|
bool is_projectile_reached_target(const Vector3<float>& target_position, const Projectile& projectile,
|
||||||
float pitch, float time) const noexcept;
|
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
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ namespace omath::projectile_prediction
|
|||||||
class Projectile final
|
class Projectile final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
|
||||||
Vector3<float> predict_position(float pitch, float yaw, float time, float gravity) const noexcept;
|
|
||||||
|
|
||||||
Vector3<float> m_origin;
|
Vector3<float> m_origin;
|
||||||
float m_launch_speed{};
|
float m_launch_speed{};
|
||||||
float m_gravity_scale{};
|
float m_gravity_scale{};
|
||||||
|
|||||||
@@ -27,10 +27,7 @@ namespace omath::projectile_prediction
|
|||||||
if (!is_projectile_reached_target(predicted_target_position, projectile, projectile_pitch.value(), time))
|
if (!is_projectile_reached_target(predicted_target_position, projectile, projectile_pitch.value(), time))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto delta2d = (predicted_target_position - projectile.m_origin).length_2d();
|
return calc_viewpoint_from_angles(projectile, predicted_target_position, projectile_pitch);
|
||||||
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 std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@@ -41,12 +38,14 @@ namespace omath::projectile_prediction
|
|||||||
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
||||||
const auto delta = target_position - projectile.m_origin;
|
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 distance2d_sqr = distance2d * distance2d;
|
||||||
const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed;
|
const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed;
|
||||||
|
|
||||||
float root = launch_speed_sqr * launch_speed_sqr
|
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]]
|
if (root < 0.0f) [[unlikely]]
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -62,8 +61,40 @@ namespace omath::projectile_prediction
|
|||||||
const float time) const noexcept
|
const float time) const noexcept
|
||||||
{
|
{
|
||||||
const auto yaw = projectile.m_origin.view_angle_to(target_position).y;
|
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;
|
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
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -7,16 +7,4 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
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
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
Reference in New Issue
Block a user