Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
- **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!
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine, CryEngine and canonical OpenGL**.
- **Engine support**: Supports coordinate systems of **Source, Rage, Unity, Unreal, Frostbite, IWEngine, CryEngine and canonical OpenGL**.
- **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.
- **Scripting**: Supports to make scripts in Lua out of box.
Expand Down Expand Up @@ -113,6 +113,10 @@ if (auto screen = camera.world_to_screen(world_position)) {

<br>

![GTA5 Preview]

<br>

![OpenGL Preview]

<br>
Expand Down Expand Up @@ -144,6 +148,7 @@ if (auto screen = camera.world_to_screen(world_position)) {
[BO2 Preview]: docs/images/showcase/cod_bo2.png
[CS2 Preview]: docs/images/showcase/cs2.jpeg
[TF2 Preview]: docs/images/showcase/tf2.jpg
[GTA5 Preview]: https://i.imgur.com/W7T8RhZ.png
[OpenGL Preview]: docs/images/showcase/opengl.png
<!----------------------------------{ Buttons }--------------------------------->
[QUICKSTART]: docs/getting_started.md
Expand Down
13 changes: 13 additions & 0 deletions include/omath/engines/rage_engine/camera.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "omath/engines/rage_engine/constants.hpp"
#include "omath/projection/camera.hpp"
#include "traits/camera_trait.hpp"

namespace omath::rage_engine
{
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE>;
} // namespace omath::rage_engine
25 changes: 25 additions & 0 deletions include/omath/engines/rage_engine/constants.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/trigonometry/angle.hpp>
#include <omath/trigonometry/view_angles.hpp>

namespace omath::rage_engine
{
constexpr Vector3<float> k_abs_up = {0, 0, 1};
constexpr Vector3<float> k_abs_right = {1, 0, 0};
constexpr Vector3<float> k_abs_forward = {0, 1, 0};

using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3X3 = Mat<3, 3, float, MatStoreType::ROW_MAJOR>;
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
using PitchAngle = Angle<float, -90.f, 90.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;

using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
} // namespace omath::rage_engine
85 changes: 85 additions & 0 deletions include/omath/engines/rage_engine/formulas.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "omath/engines/rage_engine/constants.hpp"
#include <type_traits>

namespace omath::rage_engine
{
[[nodiscard]]
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;

[[nodiscard]]
Vector3<float> right_vector(const ViewAngles& angles) noexcept;

[[nodiscard]]
Vector3<float> up_vector(const ViewAngles& angles) noexcept;

[[nodiscard]] Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;

[[nodiscard]]
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;

[[nodiscard]]
Vector3<float> extract_origin(const Mat4X4& mat) noexcept;

[[nodiscard]]
Vector3<float> extract_scale(const Mat4X4& mat) noexcept;

[[nodiscard]]
ViewAngles extract_rotation_angles(const Mat4X4& mat) noexcept;

[[nodiscard]]
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far,
NDCDepthRange ndc_depth_range = NDCDepthRange::ZERO_TO_ONE) noexcept;

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType units_to_centimeters(const FloatingType& units)
{
return units / static_cast<FloatingType>(100);
}

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType units_to_meters(const FloatingType& units)
{
return units;
}

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType units_to_kilometers(const FloatingType& units)
{
return units_to_meters(units) / static_cast<FloatingType>(1000);
}

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType centimeters_to_units(const FloatingType& centimeters)
{
return centimeters * static_cast<FloatingType>(100);
}

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType meters_to_units(const FloatingType& meters)
{
return meters;
}

template<class FloatingType>
requires std::is_floating_point_v<FloatingType>
[[nodiscard]]
constexpr FloatingType kilometers_to_units(const FloatingType& kilometers)
{
return meters_to_units(kilometers * static_cast<FloatingType>(1000));
}
} // namespace omath::rage_engine
13 changes: 13 additions & 0 deletions include/omath/engines/rage_engine/mesh.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "constants.hpp"
#include "omath/3d_primitives/mesh.hpp"
#include "traits/mesh_trait.hpp"

namespace omath::rage_engine
{
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait>;
} // namespace omath::rage_engine
24 changes: 24 additions & 0 deletions include/omath/engines/rage_engine/traits/camera_trait.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "omath/engines/rage_engine/formulas.hpp"
#include "omath/projection/camera.hpp"

namespace omath::rage_engine
{
class CameraTrait final
{
public:
[[nodiscard]]
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;

[[nodiscard]]
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
[[nodiscard]]
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
float near, float far, NDCDepthRange ndc_depth_range) noexcept;
};

} // namespace omath::rage_engine
20 changes: 20 additions & 0 deletions include/omath/engines/rage_engine/traits/mesh_trait.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include <omath/engines/rage_engine/constants.hpp>
#include <omath/engines/rage_engine/formulas.hpp>

namespace omath::rage_engine
{
class MeshTrait final
{
public:
[[nodiscard]]
static Mat4X4 rotation_matrix(const ViewAngles& rotation)
{
return rage_engine::rotation_matrix(rotation);
}
};
} // namespace omath::rage_engine
76 changes: 76 additions & 0 deletions include/omath/engines/rage_engine/traits/pred_engine_trait.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// Created by Codex on 6/3/2026.
//

#pragma once
#include "omath/engines/rage_engine/formulas.hpp"
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include <optional>

namespace omath::rage_engine
{
class PredEngineTrait final
{
public:
constexpr static Vector3<float>
predict_projectile_position(const projectile_prediction::Projectile<float>& projectile, const float pitch,
const float yaw, const float time, const float gravity) noexcept
{
const auto launch_pos = projectile.m_origin + projectile.m_launch_offset;
auto current_pos = launch_pos
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
RollAngle::from_degrees(0)})
* projectile.m_launch_speed * time;
current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;

return current_pos;
}
[[nodiscard]]
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target<float>& target,
const float time, const float gravity) noexcept
{
auto predicted = target.m_origin + target.m_velocity * time;

if (target.m_is_airborne)
predicted.z -= gravity * (time * time) * 0.5f;

return predicted;
}
[[nodiscard]]
static float calc_vector_2d_distance(const Vector3<float>& delta) noexcept
{
return std::sqrt(delta.x * delta.x + delta.y * delta.y);
}

[[nodiscard]]
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
{
return vec.z;
}

[[nodiscard]]
static Vector3<float> calc_viewpoint_from_angles(const projectile_prediction::Projectile<float>& projectile,
Vector3<float> predicted_target_position,
const std::optional<float> 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};
}
[[nodiscard]]
static float calc_direct_pitch_angle(const Vector3<float>& origin, const Vector3<float>& 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<float>& origin, const Vector3<float>& view_to) noexcept
{
const auto direction = (view_to - origin).normalized();

return angles::radians_to_degrees(-std::atan2(direction.x, direction.y));
};
};
} // namespace omath::rage_engine
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace omath::hud
const Color& tint = Color{1.f, 1.f, 1.f, 1.f}) override;
void add_text(const Vector2<float>& position, const Color& color, const std::string_view& text) override;
[[nodiscard]]
virtual Vector2<float> calc_text_size(const std::string_view& text) override;
Vector2<float> calc_text_size(const std::string_view& text) override;
};
} // namespace omath::hud
#endif // OMATH_IMGUI_INTEGRATION
8 changes: 7 additions & 1 deletion include/omath/omath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@
#include "omath/engines/frostbite_engine/traits/camera_trait.hpp"
#include "omath/engines/frostbite_engine/traits/pred_engine_trait.hpp"

// RAGE Engine
#include "omath/engines/rage_engine/constants.hpp"
#include "omath/engines/rage_engine/formulas.hpp"
#include "omath/engines/rage_engine/camera.hpp"
#include "omath/engines/rage_engine/traits/camera_trait.hpp"
#include "omath/engines/rage_engine/traits/pred_engine_trait.hpp"

// Unreal Engine
#include "omath/engines/unreal_engine/constants.hpp"
Expand All @@ -101,4 +107,4 @@

// Utility
#include "omath/utility/pattern_scan.hpp"
#include "omath/utility/pe_pattern_scan.hpp"
#include "omath/utility/pe_pattern_scan.hpp"
71 changes: 71 additions & 0 deletions source/engines/rage_engine/formulas.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Created by Codex on 6/3/2026.
//
#include "omath/engines/rage_engine/formulas.hpp"

namespace omath::rage_engine
{
Vector3<float> forward_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_forward);

return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Vector3<float> right_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_right);

return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Vector3<float> up_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_up);

return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
{
return mat_camera_view<float, MatStoreType::ROW_MAJOR>(forward_vector(angles), right_vector(angles),
up_vector(angles), cam_origin);
}
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept
{
return mat_rotation_axis_z<float, MatStoreType::ROW_MAJOR>(angles.yaw)
* mat_rotation_axis_y<float, MatStoreType::ROW_MAJOR>(angles.roll)
* mat_rotation_axis_x<float, MatStoreType::ROW_MAJOR>(angles.pitch);
}

Vector3<float> extract_origin(const Mat4X4& mat) noexcept
{
return mat_extract_origin(mat);
}

Vector3<float> extract_scale(const Mat4X4& mat) noexcept
{
return mat_extract_scale(mat);
}

ViewAngles extract_rotation_angles(const Mat4X4& mat) noexcept
{
const auto angles = mat_extract_rotation_zyx(mat);
return {
PitchAngle::from_degrees(angles.x),
YawAngle::from_degrees(angles.z),
RollAngle::from_degrees(angles.y),
};
}

Mat4X4 calc_perspective_projection_matrix(const float field_of_view, const float aspect_ratio, const float near,
const float far, const NDCDepthRange ndc_depth_range) noexcept
{
if (ndc_depth_range == NDCDepthRange::ZERO_TO_ONE)
return mat_perspective_left_handed_vertical_fov<float, MatStoreType::ROW_MAJOR, NDCDepthRange::ZERO_TO_ONE>(
field_of_view, aspect_ratio, near, far);

if (ndc_depth_range == NDCDepthRange::NEGATIVE_ONE_TO_ONE)
return mat_perspective_left_handed_vertical_fov<float, MatStoreType::ROW_MAJOR,
NDCDepthRange::NEGATIVE_ONE_TO_ONE>(
field_of_view, aspect_ratio, near, far);
std::unreachable();
}
} // namespace omath::rage_engine
Loading
Loading