mirror of
https://github.com/orange-cpp/omath.git
synced 2026-06-10 01:04:34 +00:00
Compare commits
2 Commits
main
..
feature/air
| Author | SHA1 | Date | |
|---|---|---|---|
| 92f5378a70 | |||
| dc56400927 |
@@ -81,7 +81,7 @@ if (auto screen = camera.world_to_screen(world_position)) {
|
|||||||
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
|
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
|
||||||
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
|
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
|
||||||
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
|
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
|
||||||
- **Engine support**: Supports coordinate systems of **Source, Rage, Unity, Unreal, Frostbite, IWEngine, CryEngine and canonical OpenGL**.
|
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine, CryEngine and canonical OpenGL**.
|
||||||
- **Cross platform**: Supports Windows, MacOS and Linux.
|
- **Cross platform**: Supports Windows, MacOS and Linux.
|
||||||
- **Algorithms**: Has ability to scan for byte pattern with wildcards in ELF/Mach-O/PE files/modules, binary slices, works even with Wine apps.
|
- **Algorithms**: Has ability to scan for byte pattern with wildcards in ELF/Mach-O/PE files/modules, binary slices, works even with Wine apps.
|
||||||
- **Scripting**: Supports to make scripts in Lua out of box.
|
- **Scripting**: Supports to make scripts in Lua out of box.
|
||||||
@@ -113,10 +113,6 @@ if (auto screen = camera.world_to_screen(world_position)) {
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
![GTA5 Preview]
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
![OpenGL Preview]
|
![OpenGL Preview]
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -148,7 +144,6 @@ if (auto screen = camera.world_to_screen(world_position)) {
|
|||||||
[BO2 Preview]: docs/images/showcase/cod_bo2.png
|
[BO2 Preview]: docs/images/showcase/cod_bo2.png
|
||||||
[CS2 Preview]: docs/images/showcase/cs2.jpeg
|
[CS2 Preview]: docs/images/showcase/cs2.jpeg
|
||||||
[TF2 Preview]: docs/images/showcase/tf2.jpg
|
[TF2 Preview]: docs/images/showcase/tf2.jpg
|
||||||
[GTA5 Preview]: https://i.imgur.com/W7T8RhZ.png
|
|
||||||
[OpenGL Preview]: docs/images/showcase/opengl.png
|
[OpenGL Preview]: docs/images/showcase/opengl.png
|
||||||
<!----------------------------------{ Buttons }--------------------------------->
|
<!----------------------------------{ Buttons }--------------------------------->
|
||||||
[QUICKSTART]: docs/getting_started.md
|
[QUICKSTART]: docs/getting_started.md
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ namespace imgui_desktop::gui
|
|||||||
ImGui::SliderFloat("X##ent", &m_entity_x, 100.f, vp->Size.x - 100.f);
|
ImGui::SliderFloat("X##ent", &m_entity_x, 100.f, vp->Size.x - 100.f);
|
||||||
ImGui::SliderFloat("Top Y", &m_entity_top_y, 20.f, m_entity_bottom_y - 20.f);
|
ImGui::SliderFloat("Top Y", &m_entity_top_y, 20.f, m_entity_bottom_y - 20.f);
|
||||||
ImGui::SliderFloat("Bottom Y", &m_entity_bottom_y, m_entity_top_y + 20.f, vp->Size.y - 20.f);
|
ImGui::SliderFloat("Bottom Y", &m_entity_bottom_y, m_entity_top_y + 20.f, vp->Size.y - 20.f);
|
||||||
ImGui::SliderFloat("Aspect", &m_entity_aspect, 1.f, 10.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
@@ -197,11 +196,7 @@ namespace imgui_desktop::gui
|
|||||||
const DashedBar dbar{m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width,
|
const DashedBar dbar{m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width,
|
||||||
m_bar_value, m_bar_dash_len, m_bar_dash_gap, m_bar_offset};
|
m_bar_value, m_bar_dash_len, m_bar_dash_gap, m_bar_offset};
|
||||||
|
|
||||||
auto outline_helper = [](const bool is_outline) -> Outlined
|
omath::hud::EntityOverlay({m_entity_x, m_entity_top_y}, {m_entity_x, m_entity_bottom_y},
|
||||||
{
|
|
||||||
return is_outline ? Outlined::On : Outlined::Off;
|
|
||||||
};
|
|
||||||
omath::hud::EntityOverlay({m_entity_x, m_entity_top_y}, {m_entity_x, m_entity_bottom_y}, m_entity_aspect,
|
|
||||||
std::make_shared<omath::hud::ImguiHudRenderer>())
|
std::make_shared<omath::hud::ImguiHudRenderer>())
|
||||||
.contents(
|
.contents(
|
||||||
// ── Boxes ────────────────────────────────────────────────────
|
// ── Boxes ────────────────────────────────────────────────────
|
||||||
@@ -212,18 +207,12 @@ namespace imgui_desktop::gui
|
|||||||
RightSide{
|
RightSide{
|
||||||
when(m_show_right_bar, bar),
|
when(m_show_right_bar, bar),
|
||||||
when(m_show_right_dashed_bar, dbar),
|
when(m_show_right_dashed_bar, dbar),
|
||||||
when(m_show_right_labels, Label{{0.f, 1.f, 0.f, 1.f},
|
when(m_show_right_labels,
|
||||||
m_label_offset,
|
Label{{0.f, 1.f, 0.f, 1.f}, m_label_offset, m_outlined, "Health: 100/100"}),
|
||||||
outline_helper(m_outlined),
|
when(m_show_right_labels,
|
||||||
"Health: 100/100"}),
|
Label{{1.f, 0.f, 0.f, 1.f}, m_label_offset, m_outlined, "Shield: 125/125"}),
|
||||||
when(m_show_right_labels, Label{{1.f, 0.f, 0.f, 1.f},
|
when(m_show_right_labels,
|
||||||
m_label_offset,
|
Label{{1.f, 0.f, 1.f, 1.f}, m_label_offset, m_outlined, "*LOCKED*"}),
|
||||||
outline_helper(m_outlined),
|
|
||||||
"Shield: 125/125"}),
|
|
||||||
when(m_show_right_labels, Label{{1.f, 0.f, 1.f, 1.f},
|
|
||||||
m_label_offset,
|
|
||||||
outline_helper(m_outlined),
|
|
||||||
"*LOCKED*"}),
|
|
||||||
|
|
||||||
SpaceVertical{10},
|
SpaceVertical{10},
|
||||||
when(m_show_ring, ProgressRing{m_ring_color, m_ring_bg, m_ring_radius, m_ring_ratio,
|
when(m_show_ring, ProgressRing{m_ring_color, m_ring_bg, m_ring_radius, m_ring_ratio,
|
||||||
@@ -232,41 +221,33 @@ namespace imgui_desktop::gui
|
|||||||
LeftSide{
|
LeftSide{
|
||||||
when(m_show_left_bar, bar),
|
when(m_show_left_bar, bar),
|
||||||
when(m_show_left_dashed_bar, dbar),
|
when(m_show_left_dashed_bar, dbar),
|
||||||
when(m_show_left_labels,
|
when(m_show_left_labels, Label{omath::Color::from_rgba(255, 128, 0, 255),
|
||||||
Label{omath::Color::from_rgba(255, 128, 0, 255), m_label_offset,
|
m_label_offset, m_outlined, "Armor: 75"}),
|
||||||
outline_helper(m_outlined), "Armor: 75"}),
|
when(m_show_left_labels, Label{omath::Color::from_rgba(0, 200, 255, 255),
|
||||||
when(m_show_left_labels,
|
m_label_offset, m_outlined, "Level: 42"}),
|
||||||
Label{omath::Color::from_rgba(0, 200, 255, 255), m_label_offset,
|
|
||||||
outline_helper(m_outlined), "Level: 42"}),
|
|
||||||
},
|
},
|
||||||
TopSide{
|
TopSide{
|
||||||
when(m_show_top_bar, bar),
|
when(m_show_top_bar, bar),
|
||||||
when(m_show_top_dashed_bar, dbar),
|
when(m_show_top_dashed_bar, dbar),
|
||||||
when(m_show_centered_top,
|
when(m_show_centered_top, Centered{Label{omath::Color::from_rgba(0, 255, 255, 255),
|
||||||
Centered{Label{omath::Color::from_rgba(0, 255, 255, 255), m_label_offset,
|
m_label_offset, m_outlined, "*VISIBLE*"}}),
|
||||||
outline_helper(m_outlined), "*VISIBLE*"}}),
|
|
||||||
when(m_show_top_labels, Label{omath::Color::from_rgba(255, 255, 0, 255), m_label_offset,
|
when(m_show_top_labels, Label{omath::Color::from_rgba(255, 255, 0, 255), m_label_offset,
|
||||||
outline_helper(m_outlined), "*SCOPED*"}),
|
m_outlined, "*SCOPED*"}),
|
||||||
when(m_show_top_labels, Label{omath::Color::from_rgba(255, 0, 0, 255), m_label_offset,
|
when(m_show_top_labels, Label{omath::Color::from_rgba(255, 0, 0, 255), m_label_offset,
|
||||||
outline_helper(m_outlined), "*BLEEDING*"}),
|
m_outlined, "*BLEEDING*"}),
|
||||||
},
|
},
|
||||||
BottomSide{
|
BottomSide{
|
||||||
when(m_show_bottom_bar, bar),
|
when(m_show_bottom_bar, bar),
|
||||||
when(m_show_bottom_dashed_bar, dbar),
|
when(m_show_bottom_dashed_bar, dbar),
|
||||||
when(m_show_centered_bottom,
|
when(m_show_centered_bottom, Centered{Label{omath::Color::from_rgba(255, 255, 255, 255),
|
||||||
Centered{Label{omath::Color::from_rgba(255, 255, 255, 255), m_label_offset,
|
m_label_offset, m_outlined, "PlayerName"}}),
|
||||||
outline_helper(m_outlined), "PlayerName"}}),
|
|
||||||
when(m_show_bottom_labels, Label{omath::Color::from_rgba(200, 200, 0, 255),
|
when(m_show_bottom_labels, Label{omath::Color::from_rgba(200, 200, 0, 255),
|
||||||
m_label_offset, outline_helper(m_outlined), "42m"}),
|
m_label_offset, m_outlined, "42m"}),
|
||||||
},
|
},
|
||||||
when(m_show_aim, AimDot{{m_entity_x, m_entity_top_y + 40.f}, m_aim_color, m_aim_radius}),
|
when(m_show_aim, AimDot{{m_entity_x, m_entity_top_y+40.f}, m_aim_color, m_aim_radius}),
|
||||||
when(m_show_scan, ScanMarker{m_scan_color, m_scan_outline, m_scan_outline_thickness}),
|
when(m_show_scan, ScanMarker{m_scan_color, m_scan_outline, m_scan_outline_thickness}),
|
||||||
when(m_show_skeleton, Skeleton{m_skel_color, m_skel_thickness}),
|
when(m_show_skeleton, Skeleton{m_skel_color, m_skel_thickness}),
|
||||||
when(m_show_proj, ProjectileAim{{m_proj_pos_x, m_proj_pos_y},
|
when(m_show_proj, ProjectileAim{{m_proj_pos_x, m_proj_pos_y}, m_proj_color, m_proj_size, m_proj_line_width, static_cast<ProjectileAim::Figure>(m_proj_figure)}),
|
||||||
m_proj_color,
|
|
||||||
m_proj_size,
|
|
||||||
m_proj_line_width,
|
|
||||||
static_cast<ProjectileAim::Figure>(m_proj_figure)}),
|
|
||||||
when(m_show_snap, SnapLine{{vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width}));
|
when(m_show_snap, SnapLine{{vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ namespace imgui_desktop::gui
|
|||||||
bool m_opened = true;
|
bool m_opened = true;
|
||||||
|
|
||||||
// Entity
|
// Entity
|
||||||
float m_entity_x = 550.f, m_entity_top_y = 150.f, m_entity_bottom_y = 450.f, m_entity_aspect = 4.f;
|
float m_entity_x = 550.f, m_entity_top_y = 150.f, m_entity_bottom_y = 450.f;
|
||||||
|
|
||||||
// Box
|
// Box
|
||||||
omath::Color m_box_color{1.f, 1.f, 1.f, 1.f};
|
omath::Color m_box_color{1.f, 1.f, 1.f, 1.f};
|
||||||
omath::Color m_box_fill{0.f, 0.f, 0.f, 0.f};
|
omath::Color m_box_fill{0.f, 0.f, 0.f, 0.f};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace omath::hud
|
|||||||
class EntityOverlay final
|
class EntityOverlay final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EntityOverlay(const Vector2<float>& top, const Vector2<float>& bottom, float aspect,
|
EntityOverlay(const Vector2<float>& top, const Vector2<float>& bottom,
|
||||||
const std::shared_ptr<HudRendererInterface>& renderer);
|
const std::shared_ptr<HudRendererInterface>& renderer);
|
||||||
|
|
||||||
// ── Boxes ────────────────────────────────────────────────────────
|
// ── Boxes ────────────────────────────────────────────────────────
|
||||||
@@ -57,22 +57,22 @@ namespace omath::hud
|
|||||||
float offset = 5.f);
|
float offset = 5.f);
|
||||||
|
|
||||||
// ── Labels ───────────────────────────────────────────────────────
|
// ── Labels ───────────────────────────────────────────────────────
|
||||||
EntityOverlay& add_right_label(const Color& color, float offset, widget::Outlined outlined, const std::string_view& text);
|
EntityOverlay& add_right_label(const Color& color, float offset, bool outlined, const std::string_view& text);
|
||||||
|
|
||||||
EntityOverlay& add_left_label(const Color& color, float offset, widget::Outlined outlined, const std::string_view& text);
|
EntityOverlay& add_left_label(const Color& color, float offset, bool outlined, const std::string_view& text);
|
||||||
|
|
||||||
EntityOverlay& add_top_label(const Color& color, float offset, widget::Outlined outlined, std::string_view text);
|
EntityOverlay& add_top_label(const Color& color, float offset, bool outlined, std::string_view text);
|
||||||
|
|
||||||
EntityOverlay& add_bottom_label(const Color& color, float offset, widget::Outlined outlined, std::string_view text);
|
EntityOverlay& add_bottom_label(const Color& color, float offset, bool outlined, std::string_view text);
|
||||||
|
|
||||||
EntityOverlay& add_centered_top_label(const Color& color, float offset, widget::Outlined outlined,
|
EntityOverlay& add_centered_top_label(const Color& color, float offset, bool outlined,
|
||||||
const std::string_view& text);
|
const std::string_view& text);
|
||||||
|
|
||||||
EntityOverlay& add_centered_bottom_label(const Color& color, float offset, widget::Outlined outlined,
|
EntityOverlay& add_centered_bottom_label(const Color& color, float offset, bool outlined,
|
||||||
const std::string_view& text);
|
const std::string_view& text);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_right_label(const Color& color, const float offset, const widget::Outlined outlined, std::format_string<Args...> fmt,
|
EntityOverlay& add_right_label(const Color& color, const float offset, const bool outlined, std::format_string<Args...> fmt,
|
||||||
Args&&... args)
|
Args&&... args)
|
||||||
{
|
{
|
||||||
return add_right_label(color, offset, outlined,
|
return add_right_label(color, offset, outlined,
|
||||||
@@ -80,7 +80,7 @@ namespace omath::hud
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_left_label(const Color& color, const float offset, const widget::Outlined outlined, std::format_string<Args...> fmt,
|
EntityOverlay& add_left_label(const Color& color, const float offset, const bool outlined, std::format_string<Args...> fmt,
|
||||||
Args&&... args)
|
Args&&... args)
|
||||||
{
|
{
|
||||||
return add_left_label(color, offset, outlined,
|
return add_left_label(color, offset, outlined,
|
||||||
@@ -88,7 +88,7 @@ namespace omath::hud
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_top_label(const Color& color, const float offset, const widget::Outlined outlined, std::format_string<Args...> fmt,
|
EntityOverlay& add_top_label(const Color& color, const float offset, const bool outlined, std::format_string<Args...> fmt,
|
||||||
Args&&... args)
|
Args&&... args)
|
||||||
{
|
{
|
||||||
return add_top_label(color, offset, outlined,
|
return add_top_label(color, offset, outlined,
|
||||||
@@ -96,7 +96,7 @@ namespace omath::hud
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_bottom_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& add_bottom_label(const Color& color, const float offset, const bool outlined,
|
||||||
std::format_string<Args...> fmt, Args&&... args)
|
std::format_string<Args...> fmt, Args&&... args)
|
||||||
{
|
{
|
||||||
return add_bottom_label(color, offset, outlined,
|
return add_bottom_label(color, offset, outlined,
|
||||||
@@ -104,7 +104,7 @@ namespace omath::hud
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_centered_top_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& add_centered_top_label(const Color& color, const float offset, const bool outlined,
|
||||||
std::format_string<Args...> fmt, Args&&... args)
|
std::format_string<Args...> fmt, Args&&... args)
|
||||||
{
|
{
|
||||||
return add_centered_top_label(color, offset, outlined,
|
return add_centered_top_label(color, offset, outlined,
|
||||||
@@ -112,7 +112,7 @@ namespace omath::hud
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
EntityOverlay& add_centered_bottom_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& add_centered_bottom_label(const Color& color, const float offset, const bool outlined,
|
||||||
std::format_string<Args...> fmt, Args&&... args)
|
std::format_string<Args...> fmt, Args&&... args)
|
||||||
{
|
{
|
||||||
return add_centered_bottom_label(color, offset, outlined,
|
return add_centered_bottom_label(color, offset, outlined,
|
||||||
|
|||||||
@@ -30,11 +30,6 @@ namespace omath::hud::widget
|
|||||||
float thickness = 1.f;
|
float thickness = 1.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Outlined
|
|
||||||
{
|
|
||||||
Off,
|
|
||||||
On,
|
|
||||||
};
|
|
||||||
struct CorneredBox
|
struct CorneredBox
|
||||||
{
|
{
|
||||||
Color color;
|
Color color;
|
||||||
@@ -123,7 +118,7 @@ namespace omath::hud::widget
|
|||||||
{
|
{
|
||||||
Color color;
|
Color color;
|
||||||
float offset;
|
float offset;
|
||||||
Outlined outlined;
|
bool outlined;
|
||||||
std::string_view text;
|
std::string_view text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "omath/projectile_prediction/proj_pred_engine.hpp"
|
#include "omath/projectile_prediction/proj_pred_engine.hpp"
|
||||||
#include "omath/projectile_prediction/projectile.hpp"
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
#include "omath/projectile_prediction/target.hpp"
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
#include <cmath>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
@@ -96,7 +97,7 @@ namespace omath::projectile_prediction
|
|||||||
EngineTrait::predict_target_position(target, time, m_gravity_constant);
|
EngineTrait::predict_target_position(target, time, m_gravity_constant);
|
||||||
|
|
||||||
const auto projectile_pitch =
|
const auto projectile_pitch =
|
||||||
maybe_calculate_projectile_launch_pitch_angle(projectile, predicted_target_position);
|
maybe_calculate_projectile_launch_pitch_angle(projectile, predicted_target_position, time);
|
||||||
|
|
||||||
if (!projectile_pitch.has_value()) [[unlikely]]
|
if (!projectile_pitch.has_value()) [[unlikely]]
|
||||||
continue;
|
continue;
|
||||||
@@ -130,6 +131,19 @@ namespace omath::projectile_prediction
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::optional<ArithmeticType>
|
std::optional<ArithmeticType>
|
||||||
maybe_calculate_projectile_launch_pitch_angle(const Projectile<ArithmeticType>& projectile,
|
maybe_calculate_projectile_launch_pitch_angle(const Projectile<ArithmeticType>& projectile,
|
||||||
|
const Vector3<ArithmeticType>& target_position,
|
||||||
|
const ArithmeticType time) const noexcept
|
||||||
|
{
|
||||||
|
if (projectile.m_air_friction > ArithmeticType{0})
|
||||||
|
return maybe_calculate_projectile_launch_pitch_angle_with_air_friction(projectile, target_position,
|
||||||
|
time);
|
||||||
|
|
||||||
|
return maybe_calculate_projectile_launch_pitch_angle_without_air_friction(projectile, target_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
std::optional<ArithmeticType> maybe_calculate_projectile_launch_pitch_angle_without_air_friction(
|
||||||
|
const Projectile<ArithmeticType>& projectile,
|
||||||
const Vector3<ArithmeticType>& target_position) const noexcept
|
const Vector3<ArithmeticType>& target_position) const noexcept
|
||||||
{
|
{
|
||||||
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
||||||
@@ -160,6 +174,31 @@ namespace omath::projectile_prediction
|
|||||||
return angles::radians_to_degrees(angle);
|
return angles::radians_to_degrees(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
std::optional<ArithmeticType>
|
||||||
|
maybe_calculate_projectile_launch_pitch_angle_with_air_friction(const Projectile<ArithmeticType>& projectile,
|
||||||
|
const Vector3<ArithmeticType>& target_position,
|
||||||
|
const ArithmeticType time) const noexcept
|
||||||
|
{
|
||||||
|
if (time <= ArithmeticType{0})
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
const auto launch_origin = projectile.m_origin + projectile.m_launch_offset;
|
||||||
|
const auto velocity_factor = calculate_air_friction_velocity_factor(projectile.m_air_friction, time);
|
||||||
|
|
||||||
|
if (velocity_factor == ArithmeticType{0}) [[unlikely]]
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
const auto gravity_acceleration = calculate_projectile_gravity_acceleration(projectile);
|
||||||
|
const auto gravity_displacement =
|
||||||
|
gravity_acceleration * ((time - velocity_factor) / projectile.m_air_friction);
|
||||||
|
const auto required_velocity = (target_position - launch_origin - gravity_displacement) / velocity_factor;
|
||||||
|
const auto horizontal_speed = EngineTrait::calc_vector_2d_distance(required_velocity);
|
||||||
|
const auto vertical_speed = EngineTrait::get_vector_height_coordinate(required_velocity);
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::atan2(vertical_speed, horizontal_speed));
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool is_projectile_reached_target(const Vector3<ArithmeticType>& target_position,
|
bool is_projectile_reached_target(const Vector3<ArithmeticType>& target_position,
|
||||||
const Projectile<ArithmeticType>& projectile,
|
const Projectile<ArithmeticType>& projectile,
|
||||||
@@ -167,10 +206,65 @@ namespace omath::projectile_prediction
|
|||||||
{
|
{
|
||||||
const auto yaw = EngineTrait::calc_direct_yaw_angle(
|
const auto yaw = EngineTrait::calc_direct_yaw_angle(
|
||||||
projectile.m_origin + projectile.m_launch_offset, target_position);
|
projectile.m_origin + projectile.m_launch_offset, target_position);
|
||||||
const auto projectile_position =
|
const auto projectile_position = predict_projectile_position(projectile, pitch, yaw, time);
|
||||||
EngineTrait::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<ArithmeticType> predict_projectile_position(const Projectile<ArithmeticType>& projectile,
|
||||||
|
const ArithmeticType pitch, const ArithmeticType yaw,
|
||||||
|
const ArithmeticType time) const noexcept
|
||||||
|
{
|
||||||
|
if (projectile.m_air_friction <= ArithmeticType{0})
|
||||||
|
return EngineTrait::predict_projectile_position(projectile, pitch, yaw, time, m_gravity_constant);
|
||||||
|
|
||||||
|
const auto launch_origin = projectile.m_origin + projectile.m_launch_offset;
|
||||||
|
const auto launch_velocity = calculate_projectile_launch_velocity(projectile, pitch, yaw);
|
||||||
|
const auto gravity_acceleration = calculate_projectile_gravity_acceleration(projectile);
|
||||||
|
const auto velocity_factor = calculate_air_friction_velocity_factor(projectile.m_air_friction, time);
|
||||||
|
const auto gravity_factor = (time - velocity_factor) / projectile.m_air_friction;
|
||||||
|
|
||||||
|
return launch_origin + launch_velocity * velocity_factor + gravity_acceleration * gravity_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static ArithmeticType calculate_air_friction_velocity_factor(const ArithmeticType air_friction,
|
||||||
|
const ArithmeticType time) noexcept
|
||||||
|
{
|
||||||
|
return -std::expm1(-air_friction * time) / air_friction;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<ArithmeticType> calculate_projectile_launch_velocity(const Projectile<ArithmeticType>& projectile,
|
||||||
|
const ArithmeticType pitch,
|
||||||
|
const ArithmeticType yaw) const noexcept
|
||||||
|
{
|
||||||
|
const auto launch_origin = projectile.m_origin + projectile.m_launch_offset;
|
||||||
|
auto projectile_without_air_friction = projectile;
|
||||||
|
projectile_without_air_friction.m_air_friction = ArithmeticType{0};
|
||||||
|
|
||||||
|
return EngineTrait::predict_projectile_position(projectile_without_air_friction, pitch, yaw,
|
||||||
|
ArithmeticType{1}, ArithmeticType{0})
|
||||||
|
- launch_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<ArithmeticType>
|
||||||
|
calculate_projectile_gravity_acceleration(const Projectile<ArithmeticType>& projectile) const noexcept
|
||||||
|
{
|
||||||
|
constexpr ArithmeticType test_time = ArithmeticType{1};
|
||||||
|
constexpr ArithmeticType acceleration_multiplier = ArithmeticType{2};
|
||||||
|
auto projectile_without_air_friction = projectile;
|
||||||
|
projectile_without_air_friction.m_air_friction = ArithmeticType{0};
|
||||||
|
const auto no_gravity_position = EngineTrait::predict_projectile_position(
|
||||||
|
projectile_without_air_friction, ArithmeticType{0}, ArithmeticType{0}, test_time,
|
||||||
|
ArithmeticType{0});
|
||||||
|
const auto with_gravity_position = EngineTrait::predict_projectile_position(
|
||||||
|
projectile_without_air_friction, ArithmeticType{0}, ArithmeticType{0}, test_time,
|
||||||
|
m_gravity_constant);
|
||||||
|
|
||||||
|
return (with_gravity_position - no_gravity_position) * acceleration_multiplier;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ namespace omath::projectile_prediction
|
|||||||
Vector3<ArithmeticType> m_launch_offset{};
|
Vector3<ArithmeticType> m_launch_offset{};
|
||||||
ArithmeticType m_launch_speed{};
|
ArithmeticType m_launch_speed{};
|
||||||
ArithmeticType m_gravity_scale{};
|
ArithmeticType m_gravity_scale{};
|
||||||
|
ArithmeticType m_air_friction{};
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
#include "omath/engines/rage_engine/formulas.hpp"
|
#include "omath/engines/rage_engine/formulas.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
#include "omath/engines/rage_engine/traits/camera_trait.hpp"
|
#include "omath/engines/rage_engine/traits/camera_trait.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ namespace omath::hooks
|
|||||||
|
|
||||||
LRESULT __stdcall HooksManager::wnd_proc_detour(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
LRESULT __stdcall HooksManager::wnd_proc_detour(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||||
{
|
{
|
||||||
const auto& mgr = get();
|
auto& mgr = get();
|
||||||
callback_ptr<wnd_proc_callback> cb;
|
callback_ptr<wnd_proc_callback> cb;
|
||||||
WNDPROC original;
|
WNDPROC original;
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -98,11 +98,10 @@ namespace omath::hud
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
EntityOverlay& EntityOverlay::add_right_label(const Color& color, const float offset,
|
EntityOverlay& EntityOverlay::add_right_label(const Color& color, const float offset, const bool outlined,
|
||||||
const widget::Outlined outlined,
|
|
||||||
const std::string_view& text)
|
const std::string_view& text)
|
||||||
{
|
{
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(m_text_cursor_right + Vector2<float>{offset, 0.f}, color, text);
|
draw_outlined_text(m_text_cursor_right + Vector2<float>{offset, 0.f}, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(m_text_cursor_right + Vector2<float>{offset, 0.f}, color, text.data());
|
m_renderer->add_text(m_text_cursor_right + Vector2<float>{offset, 0.f}, color, text.data());
|
||||||
@@ -111,12 +110,12 @@ namespace omath::hud
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
EntityOverlay& EntityOverlay::add_top_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& EntityOverlay::add_top_label(const Color& color, const float offset, const bool outlined,
|
||||||
const std::string_view text)
|
const std::string_view text)
|
||||||
{
|
{
|
||||||
m_text_cursor_top.y -= m_renderer->calc_text_size(text.data()).y;
|
m_text_cursor_top.y -= m_renderer->calc_text_size(text.data()).y;
|
||||||
|
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(m_text_cursor_top + Vector2<float>{0.f, -offset}, color, text);
|
draw_outlined_text(m_text_cursor_top + Vector2<float>{0.f, -offset}, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(m_text_cursor_top + Vector2<float>{0.f, -offset}, color, text.data());
|
m_renderer->add_text(m_text_cursor_top + Vector2<float>{0.f, -offset}, color, text.data());
|
||||||
@@ -393,12 +392,12 @@ namespace omath::hud
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityOverlay& EntityOverlay::add_bottom_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& EntityOverlay::add_bottom_label(const Color& color, const float offset, const bool outlined,
|
||||||
const std::string_view text)
|
const std::string_view text)
|
||||||
{
|
{
|
||||||
const auto text_size = m_renderer->calc_text_size(text);
|
const auto text_size = m_renderer->calc_text_size(text);
|
||||||
|
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(m_text_cursor_bottom + Vector2<float>{0.f, offset}, color, text);
|
draw_outlined_text(m_text_cursor_bottom + Vector2<float>{0.f, offset}, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(m_text_cursor_bottom + Vector2<float>{0.f, offset}, color, text);
|
m_renderer->add_text(m_text_cursor_bottom + Vector2<float>{0.f, offset}, color, text);
|
||||||
@@ -408,13 +407,13 @@ namespace omath::hud
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityOverlay& EntityOverlay::add_left_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& EntityOverlay::add_left_label(const Color& color, const float offset, const bool outlined,
|
||||||
const std::string_view& text)
|
const std::string_view& text)
|
||||||
{
|
{
|
||||||
const auto text_size = m_renderer->calc_text_size(text);
|
const auto text_size = m_renderer->calc_text_size(text);
|
||||||
const auto pos = m_text_cursor_left + Vector2<float>{-(offset + text_size.x), 0.f};
|
const auto pos = m_text_cursor_left + Vector2<float>{-(offset + text_size.x), 0.f};
|
||||||
|
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(pos, color, text);
|
draw_outlined_text(pos, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(pos, color, text);
|
m_renderer->add_text(pos, color, text);
|
||||||
@@ -424,7 +423,7 @@ namespace omath::hud
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityOverlay& EntityOverlay::add_centered_bottom_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& EntityOverlay::add_centered_bottom_label(const Color& color, const float offset, const bool outlined,
|
||||||
const std::string_view& text)
|
const std::string_view& text)
|
||||||
{
|
{
|
||||||
const auto text_size = m_renderer->calc_text_size(text);
|
const auto text_size = m_renderer->calc_text_size(text);
|
||||||
@@ -432,7 +431,7 @@ namespace omath::hud
|
|||||||
m_canvas.bottom_left_corner.x + (m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x) / 2.f;
|
m_canvas.bottom_left_corner.x + (m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x) / 2.f;
|
||||||
const auto pos = Vector2<float>{box_center_x - text_size.x / 2.f, m_text_cursor_bottom.y + offset};
|
const auto pos = Vector2<float>{box_center_x - text_size.x / 2.f, m_text_cursor_bottom.y + offset};
|
||||||
|
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(pos, color, text);
|
draw_outlined_text(pos, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(pos, color, text);
|
m_renderer->add_text(pos, color, text);
|
||||||
@@ -442,7 +441,7 @@ namespace omath::hud
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityOverlay& EntityOverlay::add_centered_top_label(const Color& color, const float offset, const widget::Outlined outlined,
|
EntityOverlay& EntityOverlay::add_centered_top_label(const Color& color, const float offset, const bool outlined,
|
||||||
const std::string_view& text)
|
const std::string_view& text)
|
||||||
{
|
{
|
||||||
const auto text_size = m_renderer->calc_text_size(text);
|
const auto text_size = m_renderer->calc_text_size(text);
|
||||||
@@ -452,7 +451,7 @@ namespace omath::hud
|
|||||||
m_text_cursor_top.y -= text_size.y;
|
m_text_cursor_top.y -= text_size.y;
|
||||||
const auto pos = Vector2<float>{box_center_x - text_size.x / 2.f, m_text_cursor_top.y - offset};
|
const auto pos = Vector2<float>{box_center_x - text_size.x / 2.f, m_text_cursor_top.y - offset};
|
||||||
|
|
||||||
if (outlined == widget::Outlined::On)
|
if (outlined)
|
||||||
draw_outlined_text(pos, color, text);
|
draw_outlined_text(pos, color, text);
|
||||||
else
|
else
|
||||||
m_renderer->add_text(pos, color, text);
|
m_renderer->add_text(pos, color, text);
|
||||||
@@ -460,9 +459,9 @@ namespace omath::hud
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityOverlay::EntityOverlay(const Vector2<float>& top, const Vector2<float>& bottom, const float aspect,
|
EntityOverlay::EntityOverlay(const Vector2<float>& top, const Vector2<float>& bottom,
|
||||||
const std::shared_ptr<HudRendererInterface>& renderer)
|
const std::shared_ptr<HudRendererInterface>& renderer)
|
||||||
: m_canvas(top, bottom, aspect), m_text_cursor_right(m_canvas.top_right_corner),
|
: m_canvas(top, bottom), m_text_cursor_right(m_canvas.top_right_corner),
|
||||||
m_text_cursor_top(m_canvas.top_left_corner), m_text_cursor_bottom(m_canvas.bottom_left_corner),
|
m_text_cursor_top(m_canvas.top_left_corner), m_text_cursor_bottom(m_canvas.bottom_left_corner),
|
||||||
m_text_cursor_left(m_canvas.top_left_corner), m_renderer(renderer)
|
m_text_cursor_left(m_canvas.top_left_corner), m_renderer(renderer)
|
||||||
{
|
{
|
||||||
|
|||||||
+7
-13
@@ -159,19 +159,13 @@ namespace
|
|||||||
return {1.f, 1.f, 1.f, 1.f};
|
return {1.f, 1.f, 1.f, 1.f};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
omath::hud::widget::Outlined outlined_from_bool(const bool outlined)
|
|
||||||
{
|
|
||||||
return outlined ? omath::hud::widget::Outlined::On : omath::hud::widget::Outlined::Off;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
omath::hud::EntityOverlay make_overlay(const omath::Vector2<float>& top, const omath::Vector2<float>& bottom,
|
omath::hud::EntityOverlay make_overlay(const omath::Vector2<float>& top, const omath::Vector2<float>& bottom,
|
||||||
const std::shared_ptr<LuaHudRenderer>& renderer)
|
const std::shared_ptr<LuaHudRenderer>& renderer)
|
||||||
{
|
{
|
||||||
if (!renderer)
|
if (!renderer)
|
||||||
throw std::invalid_argument("hud renderer must not be nil");
|
throw std::invalid_argument("hud renderer must not be nil");
|
||||||
return {top, bottom, 4.f, renderer};
|
return {top, bottom, renderer};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -380,37 +374,37 @@ namespace omath::lua
|
|||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_right_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_right_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
"add_left_label",
|
"add_left_label",
|
||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_left_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_left_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
"add_top_label",
|
"add_top_label",
|
||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_top_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_top_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
"add_bottom_label",
|
"add_bottom_label",
|
||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_bottom_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_bottom_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
"add_centered_top_label",
|
"add_centered_top_label",
|
||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_centered_top_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_centered_top_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
"add_centered_bottom_label",
|
"add_centered_bottom_label",
|
||||||
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
|
||||||
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
|
||||||
{
|
{
|
||||||
return overlay.add_centered_bottom_label(color, offset, outlined_from_bool(outlined), text);
|
return overlay.add_centered_bottom_label(color, offset, outlined, text);
|
||||||
},
|
},
|
||||||
|
|
||||||
"add_right_space_vertical", &omath::hud::EntityOverlay::add_right_space_vertical,
|
"add_right_space_vertical", &omath::hud::EntityOverlay::add_right_space_vertical,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 6/3/2026.
|
// Created by Codex on 6/3/2026.
|
||||||
//
|
//
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <omath/engines/rage_engine/camera.hpp>
|
#include <omath/engines/rage_engine/camera.hpp>
|
||||||
|
|||||||
@@ -283,6 +283,34 @@ TEST(ProjectileSimulation, HitsNegativeYawTarget_WithOffset)
|
|||||||
expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f);
|
expect_projectile_hits_target(proj, target, 400, 1.f / 1000.f, 50, 5.f, 10.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ProjectileSimulation, HitsStaticTarget_WithAirFriction)
|
||||||
|
{
|
||||||
|
constexpr Target target{
|
||||||
|
.m_origin = {75, 0, 0}, .m_velocity = {0, 0, 0}, .m_is_airborne = false};
|
||||||
|
constexpr Projectile proj = {
|
||||||
|
.m_origin = {0, 0, 0}, .m_launch_speed = 100.f, .m_gravity_scale = 0.f, .m_air_friction = 0.5f};
|
||||||
|
|
||||||
|
const Engine engine(0.f, 1.f / 1000.f, 10.f, 0.1f);
|
||||||
|
const auto aim_angles = engine.maybe_calculate_aim_angles(proj, target);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aim_angles.has_value());
|
||||||
|
EXPECT_NEAR(aim_angles->pitch, 0.f, 0.1f);
|
||||||
|
EXPECT_NEAR(aim_angles->yaw, 0.f, 0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ProjectileSimulation, AirFrictionLimitsMaximumReach)
|
||||||
|
{
|
||||||
|
constexpr Target target{
|
||||||
|
.m_origin = {150, 0, 0}, .m_velocity = {0, 0, 0}, .m_is_airborne = false};
|
||||||
|
constexpr Projectile proj = {
|
||||||
|
.m_origin = {0, 0, 0}, .m_launch_speed = 100.f, .m_gravity_scale = 0.f, .m_air_friction = 1.f};
|
||||||
|
|
||||||
|
const Engine engine(0.f, 1.f / 1000.f, 10.f, 0.1f);
|
||||||
|
|
||||||
|
EXPECT_FALSE(engine.maybe_calculate_aim_point(proj, target).has_value());
|
||||||
|
EXPECT_FALSE(engine.maybe_calculate_aim_angles(proj, target).has_value());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(UnitTestPrediction, AimAnglesReturnsNulloptWhenNoSolution)
|
TEST(UnitTestPrediction, AimAnglesReturnsNulloptWhenNoSolution)
|
||||||
{
|
{
|
||||||
constexpr Target target{
|
constexpr Target target{
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <omath/engines/frostbite_engine/camera.hpp>
|
#include <omath/engines/frostbite_engine/camera.hpp>
|
||||||
#include <omath/engines/iw_engine/camera.hpp>
|
#include <omath/engines/iw_engine/camera.hpp>
|
||||||
#include <omath/engines/opengl_engine/camera.hpp>
|
#include <omath/engines/opengl_engine/camera.hpp>
|
||||||
#include <omath/engines/rage_engine/camera.hpp>
|
|
||||||
#include <omath/engines/source_engine/camera.hpp>
|
#include <omath/engines/source_engine/camera.hpp>
|
||||||
#include <omath/engines/unreal_engine/camera.hpp>
|
#include <omath/engines/unreal_engine/camera.hpp>
|
||||||
#include <omath/linear_algebra/triangle.hpp>
|
#include <omath/linear_algebra/triangle.hpp>
|
||||||
@@ -17,49 +16,6 @@
|
|||||||
#include <print>
|
#include <print>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
template<class NumericType>
|
|
||||||
static NumericType random_visible_component(std::mt19937& gen, std::uniform_real_distribution<NumericType>& dist)
|
|
||||||
{
|
|
||||||
auto value = dist(gen);
|
|
||||||
if (std::abs(value) < static_cast<NumericType>(50))
|
|
||||||
value += value < NumericType{} ? -static_cast<NumericType>(50) : static_cast<NumericType>(50);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class CameraType, class ViewAnglesType, class NumericType>
|
|
||||||
static void verify_random_look_at_targets_project_to_screen_center(const omath::Vector3<NumericType>& origin,
|
|
||||||
const ViewAnglesType& view_angles,
|
|
||||||
const omath::projection::ViewPort& view_port,
|
|
||||||
const NumericType near_plane,
|
|
||||||
const NumericType far_plane, const unsigned int seed)
|
|
||||||
{
|
|
||||||
std::mt19937 gen(seed);
|
|
||||||
std::uniform_real_distribution<NumericType> dist(static_cast<NumericType>(-500), static_cast<NumericType>(500));
|
|
||||||
|
|
||||||
constexpr auto fov = omath::projection::FieldOfView::from_degrees(75.f);
|
|
||||||
auto cam = CameraType(origin, view_angles, view_port, fov, near_plane, far_plane);
|
|
||||||
const auto screen_center_x = static_cast<NumericType>(view_port.m_width / 2.f);
|
|
||||||
const auto screen_center_y = static_cast<NumericType>(view_port.m_height / 2.f);
|
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
const auto target = origin
|
|
||||||
+ omath::Vector3<NumericType>{
|
|
||||||
random_visible_component(gen, dist),
|
|
||||||
random_visible_component(gen, dist),
|
|
||||||
random_visible_component(gen, dist),
|
|
||||||
};
|
|
||||||
|
|
||||||
cam.look_at(target);
|
|
||||||
|
|
||||||
const auto projected = cam.world_to_screen(target);
|
|
||||||
ASSERT_TRUE(projected.has_value()) << "iteration: " << i;
|
|
||||||
EXPECT_NEAR(projected->x, screen_center_x, static_cast<NumericType>(0.1));
|
|
||||||
EXPECT_NEAR(projected->y, screen_center_y, static_cast<NumericType>(0.1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, Projection)
|
TEST(UnitTestProjection, Projection)
|
||||||
{
|
{
|
||||||
constexpr auto fov = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::from_degrees(90.f);
|
constexpr auto fov = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::from_degrees(90.f);
|
||||||
@@ -1159,54 +1115,6 @@ TEST(UnitTestProjection, LookAt_ForwardVectorPointsAtTarget)
|
|||||||
EXPECT_NEAR(fwd.z, 0.f, 1e-4f);
|
EXPECT_NEAR(fwd.z, 0.f, 1e-4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UnitTestProjection, SourceEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::source_engine::Camera>(
|
|
||||||
{10.f, -20.f, 30.f}, omath::source_engine::ViewAngles{}, {1920.f, 1080.f}, 0.01f, 5000.f, 101);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, UnityEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::unity_engine::Camera>(
|
|
||||||
{-15.f, 25.f, -35.f}, omath::unity_engine::ViewAngles{}, {1280.f, 720.f}, 0.03f, 5000.f, 102);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, UnrealEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::unreal_engine::Camera>(
|
|
||||||
{100.0, -50.0, 25.0}, omath::unreal_engine::ViewAngles{}, {1920.f, 1080.f}, 0.01, 5000.0, 103);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, FrostbiteEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::frostbite_engine::Camera>(
|
|
||||||
{-4.f, 2.f, 8.f}, omath::frostbite_engine::ViewAngles{}, {1600.f, 900.f}, 0.01f, 5000.f, 104);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, IWEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::iw_engine::Camera>(
|
|
||||||
{40.f, -60.f, 20.f}, omath::iw_engine::ViewAngles{}, {1920.f, 1080.f}, 0.01f, 5000.f, 105);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, OpenGLEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::opengl_engine::Camera>(
|
|
||||||
{-30.f, 70.f, 15.f}, omath::opengl_engine::ViewAngles{}, {1920.f, 1080.f}, 0.01f, 5000.f, 106);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, CryEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::cry_engine::Camera>(
|
|
||||||
{5.f, 15.f, -25.f}, omath::cry_engine::ViewAngles{}, {1280.f, 720.f}, 0.01f, 5000.f, 107);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, RageEngine_LookAtRandomWorldPointsProjectToScreenCenter)
|
|
||||||
{
|
|
||||||
verify_random_look_at_targets_project_to_screen_center<omath::rage_engine::Camera>(
|
|
||||||
{-5.f, 45.f, 10.f}, omath::rage_engine::ViewAngles{}, {1280.f, 720.f}, 0.01f, 5000.f, 108);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- is_culled_by_frustum (triangle) ----
|
// ---- is_culled_by_frustum (triangle) ----
|
||||||
|
|
||||||
TEST(UnitTestProjection, TriangleInsideFrustumNotCulled)
|
TEST(UnitTestProjection, TriangleInsideFrustumNotCulled)
|
||||||
|
|||||||
Reference in New Issue
Block a user