diff --git a/include/omath/engines/cry_engine/traits/pred_engine_trait.hpp b/include/omath/engines/cry_engine/traits/pred_engine_trait.hpp index fc28b53..13f58c6 100644 --- a/include/omath/engines/cry_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/cry_engine/traits/pred_engine_trait.hpp @@ -12,7 +12,7 @@ namespace omath::cry_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -26,7 +26,7 @@ namespace omath::cry_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -49,7 +49,7 @@ namespace omath::cry_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/frostbite_engine/traits/pred_engine_trait.hpp b/include/omath/engines/frostbite_engine/traits/pred_engine_trait.hpp index 0a5ad75..4e6197c 100644 --- a/include/omath/engines/frostbite_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/frostbite_engine/traits/pred_engine_trait.hpp @@ -12,7 +12,7 @@ namespace omath::frostbite_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -26,7 +26,7 @@ namespace omath::frostbite_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -49,7 +49,7 @@ namespace omath::frostbite_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/iw_engine/traits/pred_engine_trait.hpp b/include/omath/engines/iw_engine/traits/pred_engine_trait.hpp index 728fd75..5b441b9 100644 --- a/include/omath/engines/iw_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/iw_engine/traits/pred_engine_trait.hpp @@ -13,7 +13,7 @@ namespace omath::iw_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -27,7 +27,7 @@ namespace omath::iw_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -50,7 +50,7 @@ namespace omath::iw_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/opengl_engine/traits/pred_engine_trait.hpp b/include/omath/engines/opengl_engine/traits/pred_engine_trait.hpp index 83e758c..f9f463f 100644 --- a/include/omath/engines/opengl_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/opengl_engine/traits/pred_engine_trait.hpp @@ -12,7 +12,7 @@ namespace omath::opengl_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -26,7 +26,7 @@ namespace omath::opengl_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -49,7 +49,7 @@ namespace omath::opengl_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/source_engine/traits/pred_engine_trait.hpp b/include/omath/engines/source_engine/traits/pred_engine_trait.hpp index 7f8cc8e..ef4144c 100644 --- a/include/omath/engines/source_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/source_engine/traits/pred_engine_trait.hpp @@ -13,7 +13,7 @@ namespace omath::source_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -27,7 +27,7 @@ namespace omath::source_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -50,7 +50,7 @@ namespace omath::source_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/unity_engine/traits/pred_engine_trait.hpp b/include/omath/engines/unity_engine/traits/pred_engine_trait.hpp index 52044b8..8c71141 100644 --- a/include/omath/engines/unity_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/unity_engine/traits/pred_engine_trait.hpp @@ -12,7 +12,7 @@ namespace omath::unity_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, const float pitch, const float yaw, const float time, const float gravity) noexcept { @@ -26,7 +26,7 @@ namespace omath::unity_engine return current_pos; } [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, + static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, const float time, const float gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; @@ -49,7 +49,7 @@ namespace omath::unity_engine } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, Vector3 predicted_target_position, const std::optional projectile_pitch) noexcept { diff --git a/include/omath/engines/unreal_engine/traits/pred_engine_trait.hpp b/include/omath/engines/unreal_engine/traits/pred_engine_trait.hpp index 99f5818..b98b65d 100644 --- a/include/omath/engines/unreal_engine/traits/pred_engine_trait.hpp +++ b/include/omath/engines/unreal_engine/traits/pred_engine_trait.hpp @@ -12,69 +12,72 @@ namespace omath::unreal_engine class PredEngineTrait final { public: - constexpr static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, - const float pitch, const float yaw, - const float time, const float gravity) noexcept + static Vector3 predict_projectile_position(const projectile_prediction::Projectile& projectile, + const double pitch, const double yaw, + const double time, const double gravity) noexcept { const auto launch_pos = projectile.m_origin + projectile.m_launch_offset; const auto fwd_d = forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw), RollAngle::from_degrees(0)}); auto current_pos = launch_pos - + Vector3{static_cast(fwd_d.x), static_cast(fwd_d.y), - static_cast(fwd_d.z)} + + Vector3{fwd_d.x, fwd_d.y, fwd_d.z} * projectile.m_launch_speed * time; - current_pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f; + current_pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5; return current_pos; } + [[nodiscard]] - static constexpr Vector3 predict_target_position(const projectile_prediction::Target& target, - const float time, const float gravity) noexcept + static Vector3 predict_target_position(const projectile_prediction::Target& target, + const double time, const double gravity) noexcept { auto predicted = target.m_origin + target.m_velocity * time; if (target.m_is_airborne) - predicted.y -= gravity * (time * time) * 0.5f; + predicted.y -= gravity * (time * time) * 0.5; return predicted; } + [[nodiscard]] - static float calc_vector_2d_distance(const Vector3& delta) noexcept + static double calc_vector_2d_distance(const Vector3& delta) noexcept { return std::sqrt(delta.x * delta.x + delta.z * delta.z); } [[nodiscard]] - constexpr static float get_vector_height_coordinate(const Vector3& vec) noexcept + static double get_vector_height_coordinate(const Vector3& vec) noexcept { return vec.y; } [[nodiscard]] - static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, - Vector3 predicted_target_position, - const std::optional projectile_pitch) noexcept + static Vector3 calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile, + Vector3 predicted_target_position, + const std::optional projectile_pitch) noexcept { 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}; } + // Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be: // 89 look up, -89 look down [[nodiscard]] - static float calc_direct_pitch_angle(const Vector3& origin, const Vector3& view_to) noexcept + static double calc_direct_pitch_angle(const Vector3& origin, const Vector3& view_to) noexcept { const auto direction = (view_to - origin).normalized(); return angles::radians_to_degrees(std::asin(direction.z)); } + [[nodiscard]] - static float calc_direct_yaw_angle(const Vector3& origin, const Vector3& view_to) noexcept + static double calc_direct_yaw_angle(const Vector3& origin, const Vector3& view_to) noexcept { const auto direction = (view_to - origin).normalized(); return angles::radians_to_degrees(std::atan2(direction.y, direction.x)); - }; + } }; } // namespace omath::unreal_engine diff --git a/include/omath/projectile_prediction/proj_pred_engine.hpp b/include/omath/projectile_prediction/proj_pred_engine.hpp index 8b2b6f7..f4c2fbc 100644 --- a/include/omath/projectile_prediction/proj_pred_engine.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine.hpp @@ -8,22 +8,24 @@ namespace omath::projectile_prediction { + template struct AimAngles { - float pitch{}; - float yaw{}; + ArithmeticType pitch{}; + ArithmeticType yaw{}; }; + template class ProjPredEngineInterface { public: [[nodiscard]] - virtual std::optional> maybe_calculate_aim_point(const Projectile& projectile, - const Target& target) const = 0; + virtual std::optional> maybe_calculate_aim_point( + const Projectile& projectile, const Target& target) const = 0; [[nodiscard]] - virtual std::optional maybe_calculate_aim_angles(const Projectile& projectile, - const Target& target) const = 0; + virtual std::optional> maybe_calculate_aim_angles( + const Projectile& projectile, const Target& target) const = 0; virtual ~ProjPredEngineInterface() = default; }; diff --git a/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp b/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp index da41c64..0ec2eb3 100644 --- a/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine_avx2.hpp @@ -6,14 +6,14 @@ namespace omath::projectile_prediction { - class ProjPredEngineAvx2 final : public ProjPredEngineInterface + class ProjPredEngineAvx2 final : public ProjPredEngineInterface { public: [[nodiscard]] std::optional> - maybe_calculate_aim_point(const Projectile& projectile, const Target& target) const override; + maybe_calculate_aim_point(const Projectile& projectile, const Target& target) const override; - [[nodiscard]] std::optional - maybe_calculate_aim_angles(const Projectile& projectile, const Target& target) const override; + [[nodiscard]] std::optional> + maybe_calculate_aim_angles(const Projectile& projectile, const Target& target) const override; ProjPredEngineAvx2(float gravity_constant, float simulation_time_step, float maximum_simulation_time); ~ProjPredEngineAvx2() override = default; @@ -21,7 +21,7 @@ namespace omath::projectile_prediction private: [[nodiscard]] static std::optional calculate_pitch(const Vector3& proj_origin, const Vector3& target_pos, - float bullet_gravity, float v0, float time) ; + float bullet_gravity, float v0, float time); // We use [[maybe_unused]] here since AVX2 is not available for ARM and ARM64 CPU [[maybe_unused]] const float m_gravity_constant; diff --git a/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp b/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp index eb2b983..0800a44 100644 --- a/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp +++ b/include/omath/projectile_prediction/proj_pred_engine_legacy.hpp @@ -13,24 +13,23 @@ namespace omath::projectile_prediction { - template + template concept PredEngineConcept = - requires(const Projectile& projectile, const Target& target, const Vector3& vec_a, - const Vector3& vec_b, - Vector3 v3, // by-value for calc_viewpoint_from_angles - float pitch, float yaw, float time, float gravity, std::optional maybe_pitch) { - // Presence + return types + requires(const Projectile& projectile, const Target& target, + const Vector3& vec_a, const Vector3& vec_b, + Vector3 v3, + ArithmeticType pitch, ArithmeticType yaw, ArithmeticType time, ArithmeticType gravity, + std::optional maybe_pitch) { { T::predict_projectile_position(projectile, pitch, yaw, time, gravity) - } -> std::same_as>; - { T::predict_target_position(target, time, gravity) } -> std::same_as>; - { T::calc_vector_2d_distance(vec_a) } -> std::same_as; - { T::get_vector_height_coordinate(vec_b) } -> std::same_as; - { T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as>; - { T::calc_direct_pitch_angle(vec_a, vec_b) } -> std::same_as; - { T::calc_direct_yaw_angle(vec_a, vec_b) } -> std::same_as; + } -> std::same_as>; + { T::predict_target_position(target, time, gravity) } -> std::same_as>; + { T::calc_vector_2d_distance(vec_a) } -> std::same_as; + { T::get_vector_height_coordinate(vec_b) } -> std::same_as; + { T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as>; + { T::calc_direct_pitch_angle(vec_a, vec_b) } -> std::same_as; + { T::calc_direct_yaw_angle(vec_a, vec_b) } -> std::same_as; - // Enforce noexcept as in PredEngineTrait requires noexcept(T::predict_projectile_position(projectile, pitch, yaw, time, gravity)); requires noexcept(T::predict_target_position(target, time, gravity)); requires noexcept(T::calc_vector_2d_distance(vec_a)); @@ -39,21 +38,24 @@ namespace omath::projectile_prediction requires noexcept(T::calc_direct_pitch_angle(vec_a, vec_b)); requires noexcept(T::calc_direct_yaw_angle(vec_a, vec_b)); }; - template - requires PredEngineConcept - class ProjPredEngineLegacy final : public ProjPredEngineInterface + + template + requires PredEngineConcept + class ProjPredEngineLegacy final : public ProjPredEngineInterface { public: - explicit ProjPredEngineLegacy(const float gravity_constant, const float simulation_time_step, - const float maximum_simulation_time, const float distance_tolerance) + explicit ProjPredEngineLegacy(const ArithmeticType gravity_constant, + const ArithmeticType simulation_time_step, + const ArithmeticType maximum_simulation_time, + const ArithmeticType 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> maybe_calculate_aim_point(const Projectile& projectile, - const Target& target) const override + std::optional> maybe_calculate_aim_point( + const Projectile& projectile, const Target& target) const override { const auto solution = find_solution(projectile, target); if (!solution) @@ -64,28 +66,31 @@ namespace omath::projectile_prediction } [[nodiscard]] - std::optional maybe_calculate_aim_angles(const Projectile& projectile, - const Target& target) const override + std::optional> maybe_calculate_aim_angles( + const Projectile& projectile, const Target& target) const override { const auto solution = find_solution(projectile, target); if (!solution) return std::nullopt; - const auto yaw = EngineTrait::calc_direct_yaw_angle(projectile.m_origin + projectile.m_launch_offset, solution->predicted_target_position); - return AimAngles{solution->pitch, yaw}; + const auto yaw = EngineTrait::calc_direct_yaw_angle( + projectile.m_origin + projectile.m_launch_offset, solution->predicted_target_position); + return AimAngles{solution->pitch, yaw}; } private: struct Solution { - Vector3 predicted_target_position; - float pitch; + Vector3 predicted_target_position; + ArithmeticType pitch; }; [[nodiscard]] - std::optional find_solution(const Projectile& projectile, const Target& target) const + std::optional find_solution(const Projectile& projectile, + const Target& target) const { - for (float time = 0.f; time < m_maximum_simulation_time; time += m_simulation_time_step) + for (ArithmeticType time = ArithmeticType{0}; time < m_maximum_simulation_time; + time += m_simulation_time_step) { const auto predicted_target_position = EngineTrait::predict_target_position(target, time, m_gravity_constant); @@ -105,10 +110,10 @@ namespace omath::projectile_prediction return std::nullopt; } - const float m_gravity_constant; - const float m_simulation_time_step; - const float m_maximum_simulation_time; - const float m_distance_tolerance; + const ArithmeticType m_gravity_constant; + const ArithmeticType m_simulation_time_step; + const ArithmeticType m_maximum_simulation_time; + const ArithmeticType m_distance_tolerance; // Realization of this formula: // https://stackoverflow.com/questions/54917375/how-to-calculate-the-angle-to-shoot-a-bullet-in-order-to-hit-a-moving-target @@ -123,15 +128,15 @@ namespace omath::projectile_prediction \] */ [[nodiscard]] - std::optional - maybe_calculate_projectile_launch_pitch_angle(const Projectile& projectile, - const Vector3& target_position) const noexcept + std::optional + maybe_calculate_projectile_launch_pitch_angle(const Projectile& projectile, + const Vector3& target_position) const noexcept { const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale; const auto launch_origin = projectile.m_origin + projectile.m_launch_offset; - if (bullet_gravity == 0.f) + if (bullet_gravity == ArithmeticType{0}) return EngineTrait::calc_direct_pitch_angle(launch_origin, target_position); const auto delta = target_position - launch_origin; @@ -140,24 +145,28 @@ namespace omath::projectile_prediction 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 * EngineTrait::get_vector_height_coordinate(delta) * launch_speed_sqr); + ArithmeticType root = launch_speed_sqr * launch_speed_sqr + - bullet_gravity + * (bullet_gravity * distance2d_sqr + + ArithmeticType{2} * EngineTrait::get_vector_height_coordinate(delta) + * launch_speed_sqr); - if (root < 0.0f) [[unlikely]] + if (root < ArithmeticType{0}) [[unlikely]] return std::nullopt; root = std::sqrt(root); - const float angle = std::atan((launch_speed_sqr - root) / (bullet_gravity * distance2d)); + const ArithmeticType angle = std::atan((launch_speed_sqr - root) / (bullet_gravity * distance2d)); return angles::radians_to_degrees(angle); } + [[nodiscard]] - bool is_projectile_reached_target(const Vector3& target_position, const Projectile& projectile, - const float pitch, const float time) const noexcept + bool is_projectile_reached_target(const Vector3& target_position, + const Projectile& projectile, + const ArithmeticType pitch, const ArithmeticType time) const noexcept { - const auto yaw = EngineTrait::calc_direct_yaw_angle(projectile.m_origin + projectile.m_launch_offset, target_position); + const auto yaw = EngineTrait::calc_direct_yaw_angle( + projectile.m_origin + projectile.m_launch_offset, target_position); const auto projectile_position = EngineTrait::predict_projectile_position(projectile, pitch, yaw, time, m_gravity_constant); diff --git a/include/omath/projectile_prediction/projectile.hpp b/include/omath/projectile_prediction/projectile.hpp index 92537ed..841ea50 100644 --- a/include/omath/projectile_prediction/projectile.hpp +++ b/include/omath/projectile_prediction/projectile.hpp @@ -7,12 +7,13 @@ namespace omath::projectile_prediction { + template class Projectile final { public: - Vector3 m_origin; - Vector3 m_launch_offset{0.f, 0.f, 0.f}; - float m_launch_speed{}; - float m_gravity_scale{}; + Vector3 m_origin; + Vector3 m_launch_offset{}; + ArithmeticType m_launch_speed{}; + ArithmeticType m_gravity_scale{}; }; } // namespace omath::projectile_prediction \ No newline at end of file diff --git a/include/omath/projectile_prediction/target.hpp b/include/omath/projectile_prediction/target.hpp index 5b3f5db..6866da5 100644 --- a/include/omath/projectile_prediction/target.hpp +++ b/include/omath/projectile_prediction/target.hpp @@ -7,11 +7,12 @@ namespace omath::projectile_prediction { + template class Target final { public: - Vector3 m_origin; - Vector3 m_velocity; + Vector3 m_origin; + Vector3 m_velocity; bool m_is_airborne{}; }; -} // namespace omath::projectile_prediction \ No newline at end of file +} // namespace omath::projectile_prediction diff --git a/source/projectile_prediction/proj_pred_engine_avx2.cpp b/source/projectile_prediction/proj_pred_engine_avx2.cpp index b942a87..13080fa 100644 --- a/source/projectile_prediction/proj_pred_engine_avx2.cpp +++ b/source/projectile_prediction/proj_pred_engine_avx2.cpp @@ -14,8 +14,8 @@ namespace omath::projectile_prediction { std::optional> - ProjPredEngineAvx2::maybe_calculate_aim_point([[maybe_unused]] const Projectile& projectile, - [[maybe_unused]] const Target& target) const + ProjPredEngineAvx2::maybe_calculate_aim_point([[maybe_unused]] const Projectile& projectile, + [[maybe_unused]] const Target& target) const { #if defined(OMATH_USE_AVX2) && defined(__i386__) && defined(__x86_64__) const float bullet_gravity = m_gravity_constant * projectile.m_gravity_scale; @@ -124,9 +124,9 @@ namespace omath::projectile_prediction std::format("{} AVX2 feature is not enabled!", std::source_location::current().function_name())); #endif } - std::optional - ProjPredEngineAvx2::maybe_calculate_aim_angles([[maybe_unused]] const Projectile& projectile, - [[maybe_unused]] const Target& target) const + std::optional> + ProjPredEngineAvx2::maybe_calculate_aim_angles([[maybe_unused]] const Projectile& projectile, + [[maybe_unused]] const Target& target) const { #if defined(OMATH_USE_AVX2) && defined(__i386__) && defined(__x86_64__) const float bullet_gravity = m_gravity_constant * projectile.m_gravity_scale; @@ -201,7 +201,7 @@ namespace omath::projectile_prediction const Vector3 delta = target_pos - projectile.m_origin; const float yaw = angles::radians_to_degrees(std::atan2(delta.y, delta.x)); - return AimAngles{*pitch, yaw}; + return AimAngles{*pitch, yaw}; } } } diff --git a/tests/engines/unit_test_traits_engines.cpp b/tests/engines/unit_test_traits_engines.cpp index 8b343fb..d01efc0 100644 --- a/tests/engines/unit_test_traits_engines.cpp +++ b/tests/engines/unit_test_traits_engines.cpp @@ -44,46 +44,46 @@ static void expect_matrix_near(const MatT& a, const MatT& b, float eps = 1e-5f) #include // Helper: verify that zero offset matches default-initialized offset behavior -template -static void verify_launch_offset_at_time_zero(const Vector3& origin, const Vector3& offset) +template +static void verify_launch_offset_at_time_zero(const Vector3& origin, const Vector3& offset) { - projectile_prediction::Projectile p; + projectile_prediction::Projectile p; p.m_origin = origin; p.m_launch_offset = offset; - p.m_launch_speed = 100.f; - p.m_gravity_scale = 1.f; + p.m_launch_speed = static_cast(100); + p.m_gravity_scale = static_cast(1); - const auto pos = Trait::predict_projectile_position(p, 0.f, 0.f, 0.f, 9.81f); + const auto pos = Trait::predict_projectile_position(p, AT{0}, AT{0}, AT{0}, static_cast(9.81)); const auto expected = origin + offset; - EXPECT_NEAR(pos.x, expected.x, 1e-4f); - EXPECT_NEAR(pos.y, expected.y, 1e-4f); - EXPECT_NEAR(pos.z, expected.z, 1e-4f); + EXPECT_NEAR(static_cast(pos.x), static_cast(expected.x), 1e-4); + EXPECT_NEAR(static_cast(pos.y), static_cast(expected.y), 1e-4); + EXPECT_NEAR(static_cast(pos.z), static_cast(expected.z), 1e-4); } -template +template static void verify_zero_offset_matches_default() { - projectile_prediction::Projectile p; - p.m_origin = {10.f, 20.f, 30.f}; - p.m_launch_offset = {0.f, 0.f, 0.f}; - p.m_launch_speed = 50.f; - p.m_gravity_scale = 1.f; + projectile_prediction::Projectile p; + p.m_origin = {static_cast(10), static_cast(20), static_cast(30)}; + p.m_launch_offset = {}; + p.m_launch_speed = static_cast(50); + p.m_gravity_scale = static_cast(1); - projectile_prediction::Projectile p2; - p2.m_origin = {10.f, 20.f, 30.f}; - p2.m_launch_speed = 50.f; - p2.m_gravity_scale = 1.f; + projectile_prediction::Projectile p2; + p2.m_origin = {static_cast(10), static_cast(20), static_cast(30)}; + p2.m_launch_speed = static_cast(50); + p2.m_gravity_scale = static_cast(1); - const auto pos1 = Trait::predict_projectile_position(p, 15.f, 30.f, 1.f, 9.81f); - const auto pos2 = Trait::predict_projectile_position(p2, 15.f, 30.f, 1.f, 9.81f); + const auto pos1 = Trait::predict_projectile_position(p, static_cast(15), static_cast(30), static_cast(1), static_cast(9.81)); + const auto pos2 = Trait::predict_projectile_position(p2, static_cast(15), static_cast(30), static_cast(1), static_cast(9.81)); #if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) - constexpr float tol = 1e-6f; + constexpr double tol = 1e-6; #else - constexpr float tol = 1e-4f; + constexpr double tol = 1e-4; #endif - EXPECT_NEAR(pos1.x, pos2.x, tol); - EXPECT_NEAR(pos1.y, pos2.y, tol); - EXPECT_NEAR(pos1.z, pos2.z, tol); + EXPECT_NEAR(static_cast(pos1.x), static_cast(pos2.x), tol); + EXPECT_NEAR(static_cast(pos1.y), static_cast(pos2.y), tol); + EXPECT_NEAR(static_cast(pos1.z), static_cast(pos2.z), tol); } TEST(LaunchOffsetTests, Source_OffsetAtTimeZero) @@ -128,11 +128,11 @@ TEST(LaunchOffsetTests, Unity_ZeroOffsetMatchesDefault) } TEST(LaunchOffsetTests, Unreal_OffsetAtTimeZero) { - verify_launch_offset_at_time_zero({0, 0, 0}, {5, 3, -2}); + verify_launch_offset_at_time_zero({0, 0, 0}, {5, 3, -2}); } TEST(LaunchOffsetTests, Unreal_ZeroOffsetMatchesDefault) { - verify_zero_offset_matches_default(); + verify_zero_offset_matches_default(); } TEST(LaunchOffsetTests, CryEngine_OffsetAtTimeZero) { @@ -401,38 +401,38 @@ TEST(TraitTests, Unreal_Pred_And_Mesh_And_Camera) { namespace e = omath::unreal_engine; - projectile_prediction::Projectile p; - p.m_origin = {0.f, 0.f, 0.f}; - p.m_launch_speed = 10.f; - p.m_gravity_scale = 1.f; + projectile_prediction::Projectile p; + p.m_origin = {0.0, 0.0, 0.0}; + p.m_launch_speed = 10.0; + p.m_gravity_scale = 1.0; - const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); - EXPECT_NEAR(pos.x, 10.f, 1e-4f); - EXPECT_NEAR(pos.y, -9.81f * 0.5f, 1e-4f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.0, 0.0, 1.0, 9.81); + EXPECT_NEAR(pos.x, 10.0, 1e-4); + EXPECT_NEAR(pos.y, -9.81 * 0.5, 1e-4); - projectile_prediction::Target t; - t.m_origin = {0.f, 5.f, 0.f}; - t.m_velocity = {2.f, 0.f, 0.f}; + projectile_prediction::Target t; + t.m_origin = {0.0, 5.0, 0.0}; + t.m_velocity = {2.0, 0.0, 0.0}; t.m_is_airborne = true; - const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); - EXPECT_NEAR(pred.x, 4.f, 1e-6f); - EXPECT_NEAR(pred.y, 5.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.0, 9.81); + EXPECT_NEAR(pred.x, 4.0, 1e-6); + EXPECT_NEAR(pred.y, 5.0 - 9.81 * (2.0 * 2.0) * 0.5, 1e-6); - EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); - EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.0, 0.0, 4.0}), 5.0, 1e-6); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.0, 2.5, 3.0}), 2.5, 1e-6); - std::optional pitch = 45.f; - auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); - EXPECT_NEAR(vp.z, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); + std::optional pitch = 45.0; + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, Vector3{10.0, 0.0, 0.0}, pitch); + EXPECT_NEAR(vp.z, 0.0 + 10.0 * std::tan(angles::degrees_to_radians(45.0)), 1e-6); - Vector3 origin{0.f, 0.f, 0.f}; - Vector3 view_to{1.f, 1.f, 1.f}; + Vector3 origin{0.0, 0.0, 0.0}; + Vector3 view_to{1.0, 1.0, 1.0}; const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dir = (view_to - origin).normalized(); - EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.z)), 1e-3f); + EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.z)), 1e-3); const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); - EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(dir.y, dir.x)), 1e-3f); + EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(dir.y, dir.x)), 1e-3); e::ViewAngles va; expect_matrix_near(e::MeshTrait::rotation_matrix(va), e::rotation_matrix(va)); @@ -448,8 +448,8 @@ TEST(TraitTests, Unreal_Pred_And_Mesh_And_Camera) // non-airborne t.m_is_airborne = false; - const auto pred_ground_unreal = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); - EXPECT_NEAR(pred_ground_unreal.x, 4.f, 1e-6f); + const auto pred_ground_unreal = e::PredEngineTrait::predict_target_position(t, 2.0, 9.81); + EXPECT_NEAR(pred_ground_unreal.x, 4.0, 1e-6); } // ── NDC Depth Range tests for Source and CryEngine camera traits ──────────── diff --git a/tests/general/unit_test_pred_engine_trait.cpp b/tests/general/unit_test_pred_engine_trait.cpp index eb9defc..fd20773 100644 --- a/tests/general/unit_test_pred_engine_trait.cpp +++ b/tests/general/unit_test_pred_engine_trait.cpp @@ -7,9 +7,12 @@ using namespace omath; using namespace omath::source_engine; +using Projectile = projectile_prediction::Projectile; +using Target = projectile_prediction::Target; + TEST(PredEngineTrait, PredictProjectilePositionBasic) { - projectile_prediction::Projectile p; + Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; @@ -23,7 +26,7 @@ TEST(PredEngineTrait, PredictProjectilePositionBasic) TEST(PredEngineTrait, PredictTargetPositionAirborne) { - projectile_prediction::Target t; + Target t; t.m_origin = {0.f, 0.f, 10.f}; t.m_velocity = {1.f, 0.f, 0.f}; t.m_is_airborne = true; @@ -42,7 +45,7 @@ TEST(PredEngineTrait, CalcVector2dDistance) TEST(PredEngineTrait, CalcViewpointFromAngles) { - projectile_prediction::Projectile p; + Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; @@ -55,7 +58,7 @@ TEST(PredEngineTrait, CalcViewpointFromAngles) TEST(PredEngineTrait, PredictProjectilePositionWithLaunchOffset) { - projectile_prediction::Projectile p; + Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_offset = {5.f, 3.f, -2.f}; p.m_launch_speed = 10.f; @@ -76,13 +79,13 @@ TEST(PredEngineTrait, PredictProjectilePositionWithLaunchOffset) TEST(PredEngineTrait, ZeroLaunchOffsetMatchesOriginalBehavior) { - projectile_prediction::Projectile p; + Projectile p; p.m_origin = {10.f, 20.f, 30.f}; p.m_launch_offset = {0.f, 0.f, 0.f}; p.m_launch_speed = 15.f; p.m_gravity_scale = 0.5f; - projectile_prediction::Projectile p_no_offset; + Projectile p_no_offset; p_no_offset.m_origin = {10.f, 20.f, 30.f}; p_no_offset.m_launch_speed = 15.f; p_no_offset.m_gravity_scale = 0.5f; diff --git a/tests/general/unit_test_prediction.cpp b/tests/general/unit_test_prediction.cpp index dc66d41..6e856d8 100644 --- a/tests/general/unit_test_prediction.cpp +++ b/tests/general/unit_test_prediction.cpp @@ -1,14 +1,19 @@ #include #include #include + +using Projectile = omath::projectile_prediction::Projectile; +using Target = omath::projectile_prediction::Target; +using Engine = omath::projectile_prediction::ProjPredEngineLegacy<>; + TEST(UnitTestPrediction, PredictionTest) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {3, 2, 1}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + constexpr Projectile proj = { + .m_origin = {3, 2, 1}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; const auto viewPoint = - omath::projectile_prediction::ProjPredEngineLegacy(400, 1.f / 1000.f, 50, 5.f).maybe_calculate_aim_point(proj, target); + Engine(400.f, 1.f / 1000.f, 50.f, 5.f).maybe_calculate_aim_point(proj, target); const auto [pitch, yaw, _] =omath::source_engine::CameraTrait::calc_look_at_angle(proj.m_origin, viewPoint.value()); @@ -18,12 +23,12 @@ TEST(UnitTestPrediction, PredictionTest) } // Helper: verify aim_angles match angles derived from aim_point via CameraTrait -static void expect_angles_match_aim_point(const omath::projectile_prediction::Projectile& proj, - const omath::projectile_prediction::Target& target, +static void expect_angles_match_aim_point(const Projectile& proj, + const Target& target, float gravity, float step, float max_time, float tolerance, float angle_eps = 0.01f) { - const omath::projectile_prediction::ProjPredEngineLegacy engine(gravity, step, max_time, tolerance); + const Engine engine(gravity, step, max_time, tolerance); const auto aim_point = engine.maybe_calculate_aim_point(proj, target); const auto aim_angles = engine.maybe_calculate_aim_angles(proj, target); @@ -45,30 +50,30 @@ static void expect_angles_match_aim_point(const omath::projectile_prediction::Pr TEST(UnitTestPrediction, AimAnglesMatchAimPoint_StaticTarget) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {3, 2, 1}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + constexpr Projectile proj = { + .m_origin = {3, 2, 1}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_angles_match_aim_point(proj, target, 400, 1.f / 1000.f, 50, 5.f); } TEST(UnitTestPrediction, AimAnglesMatchAimPoint_MovingTarget) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {500, 100, 0}, .m_velocity = {-50, 20, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 3000, .m_gravity_scale = 1.0}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 3000.f, .m_gravity_scale = 1.0f}; expect_angles_match_aim_point(proj, target, 800, 1.f / 500.f, 30, 10.f); } TEST(UnitTestPrediction, AimAnglesMatchAimPoint_AirborneTarget) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {200, 50, 300}, .m_velocity = {10, -5, -20}, .m_is_airborne = true}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 4000, .m_gravity_scale = 0.5}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 4000.f, .m_gravity_scale = 0.5f}; expect_angles_match_aim_point(proj, target, 400, 1.f / 1000.f, 50, 10.f); } @@ -76,10 +81,10 @@ TEST(UnitTestPrediction, AimAnglesMatchAimPoint_AirborneTarget) TEST(UnitTestPrediction, AimAnglesMatchAimPoint_HighArc) { // Target nearly directly above — high pitch angle - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {10, 0, 500}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.3}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.3f}; expect_angles_match_aim_point(proj, target, 400, 1.f / 1000.f, 50, 5.f); } @@ -87,20 +92,20 @@ TEST(UnitTestPrediction, AimAnglesMatchAimPoint_HighArc) TEST(UnitTestPrediction, AimAnglesMatchAimPoint_NegativeYaw) { // Target behind and to the left — negative yaw quadrant - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {-200, -150, 10}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_angles_match_aim_point(proj, target, 400, 1.f / 1000.f, 50, 5.f); } TEST(UnitTestPrediction, AimAnglesMatchAimPoint_WithLaunchOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {200, 0, 50}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {5, 0, -3}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {5, 0, -3}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_angles_match_aim_point(proj, target, 400, 1.f / 1000.f, 50, 5.f); } @@ -108,13 +113,13 @@ TEST(UnitTestPrediction, AimAnglesMatchAimPoint_WithLaunchOffset) // Helper: simulate projectile flight using aim_angles and verify it reaches the target. // Steps the projectile forward in small increments, simultaneously predicts target position, // and checks that the minimum distance is within hit_tolerance. -static void expect_projectile_hits_target(const omath::projectile_prediction::Projectile& proj, - const omath::projectile_prediction::Target& target, +static void expect_projectile_hits_target(const Projectile& proj, + const Target& target, float gravity, float engine_step, float max_time, float engine_tolerance, float hit_tolerance, float sim_step = 1.f / 2000.f) { using Trait = omath::source_engine::PredEngineTrait; - const omath::projectile_prediction::ProjPredEngineLegacy engine(gravity, engine_step, max_time, engine_tolerance); + const Engine engine(gravity, engine_step, max_time, engine_tolerance); const auto aim_angles = engine.maybe_calculate_aim_angles(proj, target); ASSERT_TRUE(aim_angles.has_value()) << "engine must find a solution"; @@ -148,50 +153,50 @@ static void expect_projectile_hits_target(const omath::projectile_prediction::Pr TEST(ProjectileSimulation, HitsStaticTarget_NoOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {3, 2, 1}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + constexpr Projectile proj = { + .m_origin = {3, 2, 1}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsMovingTarget_NoOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {500, 100, 0}, .m_velocity = {-50, 20, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 3000, .m_gravity_scale = 1.0}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 3000.f, .m_gravity_scale = 1.0f}; expect_projectile_hits_target(proj, target, 800, 1.f / 500.f, 30, 10.f, 15.f); } TEST(ProjectileSimulation, HitsAirborneTarget_NoOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {200, 50, 300}, .m_velocity = {10, -5, -20}, .m_is_airborne = true}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 4000, .m_gravity_scale = 0.5}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 4000.f, .m_gravity_scale = 0.5f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 10.f, 15.f); } TEST(ProjectileSimulation, HitsHighTarget_NoOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {10, 0, 500}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.3}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.3f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsNegativeYawTarget_NoOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {-200, -150, 10}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } @@ -200,92 +205,92 @@ TEST(ProjectileSimulation, HitsNegativeYawTarget_NoOffset) TEST(ProjectileSimulation, HitsStaticTarget_SmallOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {200, 0, 50}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {5, 0, -3}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {5, 0, -3}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsStaticTarget_LargeXOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {300, 100, 0}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {20, 0, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {20, 0, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsStaticTarget_LargeYOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {150, -200, 30}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {0, 15, 0}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {0, 15, 0}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsStaticTarget_LargeZOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {100, 0, 200}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {0, 0, -10}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {0, 0, -10}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsStaticTarget_AllAxesOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {250, 80, 60}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {10, 5, 20}, .m_launch_offset = {8, -4, -6}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {10, 5, 20}, .m_launch_offset = {8, -4, -6}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(ProjectileSimulation, HitsMovingTarget_WithOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {400, 0, 50}, .m_velocity = {-30, 10, 5}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {10, -5, 2}, .m_launch_speed = 3000, .m_gravity_scale = 0.8}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {10, -5, 2}, .m_launch_speed = 3000.f, .m_gravity_scale = 0.8f}; expect_projectile_hits_target(proj, target, 800, 1.f / 500.f, 30, 10.f, 15.f); } TEST(ProjectileSimulation, HitsAirborneTarget_WithOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {150, 80, 250}, .m_velocity = {5, -10, -30}, .m_is_airborne = true}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 50}, .m_launch_offset = {3, 7, -5}, .m_launch_speed = 4000, .m_gravity_scale = 0.5}; + const Projectile proj = { + .m_origin = {0, 0, 50}, .m_launch_offset = {3, 7, -5}, .m_launch_speed = 4000.f, .m_gravity_scale = 0.5f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 10.f, 15.f); } TEST(ProjectileSimulation, HitsNegativeYawTarget_WithOffset) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {-200, -150, 10}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - const omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_offset = {-5, 3, 2}, .m_launch_speed = 5000, .m_gravity_scale = 0.4}; + const Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_offset = {-5, 3, 2}, .m_launch_speed = 5000.f, .m_gravity_scale = 0.4f}; expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f); } TEST(UnitTestPrediction, AimAnglesReturnsNulloptWhenNoSolution) { - constexpr omath::projectile_prediction::Target target{ + constexpr Target target{ .m_origin = {100000, 0, 0}, .m_velocity = {0, 0, 0}, .m_is_airborne = false}; - constexpr omath::projectile_prediction::Projectile proj = { - .m_origin = {0, 0, 0}, .m_launch_speed = 1, .m_gravity_scale = 1}; + constexpr Projectile proj = { + .m_origin = {0, 0, 0}, .m_launch_speed = 1.f, .m_gravity_scale = 1.f}; - const omath::projectile_prediction::ProjPredEngineLegacy engine(9.81f, 0.1f, 2.f, 5.f); + const Engine engine(9.81f, 0.1f, 2.f, 5.f); const auto aim_point = engine.maybe_calculate_aim_point(proj, target); const auto aim_angles = engine.maybe_calculate_aim_angles(proj, target); diff --git a/tests/general/unit_test_proj_pred_engine_legacy_more.cpp b/tests/general/unit_test_proj_pred_engine_legacy_more.cpp index 73011ca..02e5e07 100644 --- a/tests/general/unit_test_proj_pred_engine_legacy_more.cpp +++ b/tests/general/unit_test_proj_pred_engine_legacy_more.cpp @@ -4,8 +4,8 @@ #include #include -using omath::projectile_prediction::Projectile; -using omath::projectile_prediction::Target; +using Projectile = omath::projectile_prediction::Projectile; +using Target = omath::projectile_prediction::Target; using omath::Vector3; // Fake engine trait where gravity is effectively zero and projectile prediction always hits the target