Add comprehensive documentation improvements

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-11-01 09:51:38 +00:00
parent b8ed0bd5a5
commit 0b89c1d36d
7 changed files with 3078 additions and 2 deletions

527
docs/api_overview.md Normal file
View File

@@ -0,0 +1,527 @@
# API Overview
This document provides a high-level overview of OMath's API, organized by functionality area.
---
## Module Organization
OMath is organized into several logical modules:
### Core Mathematics
- **Linear Algebra** - Vectors, matrices, triangles
- **Trigonometry** - Angles, view angles, trigonometric functions
- **3D Primitives** - Boxes, planes, geometric shapes
### Game Development
- **Collision Detection** - Ray tracing, intersection tests
- **Projectile Prediction** - Ballistics and aim-assist calculations
- **Projection** - Camera systems and world-to-screen transformations
- **Pathfinding** - A* algorithm, navigation meshes
### Engine Support
- **Source Engine** - Valve's Source Engine (CS:GO, TF2, etc.)
- **Unity Engine** - Unity game engine
- **Unreal Engine** - Epic's Unreal Engine
- **Frostbite Engine** - EA's Frostbite Engine
- **IW Engine** - Infinity Ward's engine (Call of Duty)
- **OpenGL Engine** - Canonical OpenGL coordinate system
### Utilities
- **Color** - RGBA color representation
- **Pattern Scanning** - Memory pattern search (wildcards, PE files)
- **Reverse Engineering** - Internal/external memory manipulation
---
## Core Types
### Vectors
All vector types are template-based and support arithmetic types.
| Type | Description | Key Methods |
|------|-------------|-------------|
| `Vector2<T>` | 2D vector | `length()`, `normalized()`, `dot()`, `distance_to()` |
| `Vector3<T>` | 3D vector | `length()`, `normalized()`, `dot()`, `cross()`, `angle_between()` |
| `Vector4<T>` | 4D vector | Extends Vector3 with `w` component |
**Common aliases:**
```cpp
using Vec2f = Vector2<float>;
using Vec3f = Vector3<float>;
using Vec4f = Vector4<float>;
```
**Key features:**
- Component-wise arithmetic (+, -, *, /)
- Scalar multiplication/division
- Dot and cross products
- Safe normalization (returns original if length is zero)
- Distance calculations
- Angle calculations with error handling
- Hash support for `float` variants
- `std::formatter` support
### Matrices
| Type | Description | Key Methods |
|------|-------------|-------------|
| `Mat4X4` | 4×4 matrix | `identity()`, `transpose()`, `determinant()`, `inverse()` |
**Use cases:**
- Transformation matrices
- View matrices
- Projection matrices
- Model-view-projection pipelines
### Angles
Strong-typed angle system with compile-time range enforcement:
| Type | Range | Description |
|------|-------|-------------|
| `Angle<T, Min, Max, Flags>` | Custom | Generic angle type with bounds |
| `PitchAngle` | [-89°, 89°] | Vertical camera rotation |
| `YawAngle` | [-180°, 180°] | Horizontal camera rotation |
| `RollAngle` | [-180°, 180°] | Camera roll |
| `ViewAngles` | - | Composite pitch/yaw/roll |
**Features:**
- Automatic normalization/clamping based on flags
- Conversions between degrees and radians
- Type-safe arithmetic
- Prevents common angle bugs
---
## Projection System
### Camera
Generic camera template that works with any engine trait:
```cpp
template<class MatrixType, class AnglesType, class EngineTrait>
class Camera;
```
**Engine-specific cameras:**
```cpp
omath::source_engine::Camera // Source Engine
omath::unity_engine::Camera // Unity
omath::unreal_engine::Camera // Unreal
omath::frostbite_engine::Camera // Frostbite
omath::iw_engine::Camera // IW Engine
omath::opengl_engine::Camera // OpenGL
```
**Core methods:**
- `world_to_screen(Vector3<float>)` - Project 3D point to 2D screen
- `get_view_matrix()` - Get current view matrix
- `get_projection_matrix()` - Get current projection matrix
- `update(position, angles)` - Update camera state
**Supporting types:**
- `ViewPort` - Screen dimensions and aspect ratio
- `FieldOfView` - FOV in degrees with validation
- `ProjectionError` - Error codes for projection failures
---
## Collision Detection
### LineTracer
Ray-casting and line tracing utilities:
```cpp
namespace omath::collision {
class LineTracer;
}
```
**Features:**
- Ray-triangle intersection
- Ray-plane intersection
- Ray-box intersection
- Distance calculations
- Normal calculations at hit points
### 3D Primitives
| Type | Description | Key Methods |
|------|-------------|-------------|
| `Plane` | Infinite plane | `intersects_ray()`, `distance_to_point()` |
| `Box` | Axis-aligned bounding box | `contains()`, `intersects()` |
---
## Projectile Prediction
### Interfaces
**`ProjPredEngineInterface`** - Base interface for all prediction engines
```cpp
virtual std::optional<Vector3<float>>
maybe_calculate_aim_point(const Projectile&, const Target&) const = 0;
```
### Implementations
| Engine | Description | Optimizations |
|--------|-------------|---------------|
| `ProjPredEngineLegacy` | Standard implementation | Portable, works everywhere |
| `ProjPredEngineAVX2` | AVX2 optimized | 2-4x faster on modern CPUs |
### Supporting Types
**`Projectile`** - Defines projectile properties:
```cpp
struct Projectile {
Vector3<float> origin;
float speed;
Vector3<float> gravity;
// ... additional properties
};
```
**`Target`** - Defines target state:
```cpp
struct Target {
Vector3<float> position;
Vector3<float> velocity;
// ... additional properties
};
```
---
## Pathfinding
### A* Algorithm
```cpp
namespace omath::pathfinding {
template<typename NodeType>
class AStar;
}
```
**Features:**
- Generic node type support
- Customizable heuristics
- Efficient priority queue implementation
- Path reconstruction
### Navigation Mesh
```cpp
namespace omath::pathfinding {
class NavigationMesh;
}
```
**Features:**
- Triangle-based navigation
- Neighbor connectivity
- Walkable area definitions
---
## Engine Traits
Each game engine has a trait system providing engine-specific math:
### CameraTrait
Implements camera math for an engine:
- `calc_look_at_angle()` - Calculate angles to look at a point
- `calc_view_matrix()` - Build view matrix from angles and position
- `calc_projection_matrix()` - Build projection matrix from FOV and viewport
### PredEngineTrait
Provides physics/ballistics specific to an engine:
- Gravity vectors
- Coordinate system conventions
- Unit conversions
- Physics parameters
### Available Traits
| Engine | Camera Trait | Pred Engine Trait | Constants | Formulas |
|--------|--------------|-------------------|-----------|----------|
| Source Engine | ✓ | ✓ | ✓ | ✓ |
| Unity Engine | ✓ | ✓ | ✓ | ✓ |
| Unreal Engine | ✓ | ✓ | ✓ | ✓ |
| Frostbite | ✓ | ✓ | ✓ | ✓ |
| IW Engine | ✓ | ✓ | ✓ | ✓ |
| OpenGL | ✓ | ✓ | ✓ | ✓ |
**Documentation:**
- See `docs/engines/<engine_name>/` for detailed per-engine docs
- Each engine has separate docs for camera_trait, pred_engine_trait, constants, and formulas
---
## Utility Functions
### Color
```cpp
struct Color {
uint8_t r, g, b, a;
// Conversions
static Color from_hsv(float h, float s, float v);
static Color from_hex(uint32_t hex);
uint32_t to_hex() const;
// Blending
Color blend(const Color& other, float t) const;
};
```
### Pattern Scanning
**Binary pattern search with wildcards:**
```cpp
// Pattern with wildcards (?? = any byte)
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
// Scan memory
auto result = pattern_scan(memory_buffer, pattern);
if (result) {
std::cout << "Found at offset: " << result->offset << "\n";
}
```
**PE file scanning:**
```cpp
PEPatternScanner scanner("target.exe");
if (auto addr = scanner.scan_pattern(pattern)) {
std::cout << "Found at RVA: " << *addr << "\n";
}
```
### Reverse Engineering
**External memory access:**
```cpp
ExternalRevObject process("game.exe");
Vector3<float> position = process.read<Vector3<float>>(address);
process.write(address, new_position);
```
**Internal memory access:**
```cpp
InternalRevObject memory;
auto value = memory.read<float>(address);
memory.write(address, new_value);
```
---
## Concepts and Constraints
OMath uses C++20 concepts for type safety:
```cpp
template<class T>
concept Arithmetic = std::is_arithmetic_v<T>;
template<class EngineTrait>
concept CameraEngineConcept = requires(EngineTrait t) {
{ t.calc_look_at_angle(...) } -> /* returns angles */;
{ t.calc_view_matrix(...) } -> /* returns matrix */;
{ t.calc_projection_matrix(...) } -> /* returns matrix */;
};
```
---
## Error Handling
OMath uses modern C++ error handling:
### std::expected (C++23)
```cpp
std::expected<Angle<...>, Vector3Error>
angle_between(const Vector3& other) const;
if (auto angle = v1.angle_between(v2)) {
// Success: use *angle
} else {
// Error: angle.error() gives Vector3Error
}
```
### std::optional
```cpp
std::optional<Vector2<float>>
world_to_screen(const Vector3<float>& world);
if (auto screen = camera.world_to_screen(pos)) {
// Success: use screen->x, screen->y
} else {
// Point not visible
}
```
### Error Codes
```cpp
enum class ProjectionError {
SUCCESS = 0,
POINT_BEHIND_CAMERA,
INVALID_VIEWPORT,
// ...
};
```
---
## Performance Considerations
### constexpr Support
Most operations are `constexpr` where possible:
```cpp
constexpr Vector3<float> v{1, 2, 3};
constexpr auto len_sq = v.length_sqr(); // Computed at compile time
```
### AVX2 Optimizations
Use AVX2 variants when available:
```cpp
// Standard: portable but slower
ProjPredEngineLegacy legacy_engine;
// AVX2: 2-4x faster on modern CPUs
ProjPredEngineAVX2 fast_engine;
```
**When to use AVX2:**
- Modern Intel/AMD processors (2013+)
- Performance-critical paths
- Batch operations
**When to use Legacy:**
- Older processors
- ARM platforms
- Guaranteed compatibility
### Cache Efficiency
```cpp
// Good: contiguous storage
std::vector<Vector3<float>> positions;
// Good: structure of arrays for SIMD
struct Particles {
std::vector<float> x, y, z;
};
```
---
## Platform Support
| Platform | Support | Notes |
|----------|---------|-------|
| Windows | ✓ | MSVC, Clang, GCC |
| Linux | ✓ | GCC, Clang |
| macOS | ✓ | Clang |
**Minimum requirements:**
- C++20 compiler
- C++23 recommended for `std::expected`
---
## Thread Safety
- **Vector/Matrix types**: Thread-safe (immutable operations)
- **Camera**: Not thread-safe (mutable state)
- **Pattern scanning**: Thread-safe (read-only operations)
- **Memory access**: Depends on OS/process synchronization
**Thread-safe example:**
```cpp
// Safe: each thread gets its own camera
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back([i]() {
Camera camera = /* create camera */;
// Use camera in this thread
});
}
```
---
## Best Practices
### 1. Use Type Aliases
```cpp
using Vec3f = omath::Vector3<float>;
using Mat4 = omath::Mat4X4;
```
### 2. Prefer constexpr When Possible
```cpp
constexpr auto compute_at_compile_time() {
Vector3<float> v{1, 2, 3};
return v.length_sqr();
}
```
### 3. Check Optional/Expected Results
```cpp
// Good
if (auto result = camera.world_to_screen(pos)) {
use(*result);
}
// Bad - may crash
auto result = camera.world_to_screen(pos);
use(result->x); // Undefined behavior if nullopt
```
### 4. Use Engine-Specific Types
```cpp
// Good: uses correct coordinate system
using namespace omath::source_engine;
Camera camera = /* ... */;
// Bad: mixing engine types
using UnityCamera = omath::unity_engine::Camera;
using SourceAngles = omath::source_engine::ViewAngles;
UnityCamera camera{pos, SourceAngles{}}; // Wrong!
```
---
## See Also
- [Getting Started Guide](getting_started.md)
- [Installation Instructions](install.md)
- [Examples Directory](../examples/)
- Individual module documentation in respective folders
---
*Last updated: 1 Nov 2025*

532
docs/best_practices.md Normal file
View File

@@ -0,0 +1,532 @@
# Best Practices
Guidelines for using OMath effectively and avoiding common pitfalls.
---
## Code Organization
### Use Type Aliases
Define clear type aliases for commonly used types:
```cpp
// Good: Clear and concise
using Vec3f = omath::Vector3<float>;
using Vec2f = omath::Vector2<float>;
using Mat4 = omath::Mat4X4;
Vec3f position{1.0f, 2.0f, 3.0f};
```
```cpp
// Avoid: Verbose and repetitive
omath::Vector3<float> position{1.0f, 2.0f, 3.0f};
omath::Vector3<float> velocity{0.0f, 0.0f, 0.0f};
```
### Namespace Usage
Be selective with `using namespace`:
```cpp
// Good: Specific namespace for your engine
using namespace omath::source_engine;
// Good: Import specific types
using omath::Vector3;
using omath::Vector2;
// Avoid: Too broad
using namespace omath; // Imports everything
```
### Include What You Use
```cpp
// Good: Include specific headers
#include <omath/linear_algebra/vector3.hpp>
#include <omath/projection/camera.hpp>
// Okay for development
#include <omath/omath.hpp>
// Production: Include only what you need
// to reduce compile times
```
---
## Error Handling
### Always Check Optional Results
```cpp
// Good: Check before using
if (auto screen = camera.world_to_screen(world_pos)) {
draw_at(screen->x, screen->y);
} else {
// Handle point not visible
}
// Bad: Unchecked access can crash
auto screen = camera.world_to_screen(world_pos);
draw_at(screen->x, screen->y); // Undefined behavior if nullopt!
```
### Handle Expected Errors
```cpp
// Good: Handle error case
if (auto angle = v1.angle_between(v2)) {
use_angle(*angle);
} else {
switch (angle.error()) {
case Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE:
// Handle zero-length vector
break;
}
}
// Bad: Assume success
auto angle = v1.angle_between(v2);
use_angle(*angle); // Throws if error!
```
### Validate Inputs
```cpp
// Good: Validate before expensive operations
bool is_valid_projectile(const Projectile& proj) {
return proj.speed > 0.0f &&
std::isfinite(proj.speed) &&
std::isfinite(proj.origin.length());
}
if (is_valid_projectile(proj) && is_valid_target(target)) {
auto aim = engine.maybe_calculate_aim_point(proj, target);
}
```
---
## Performance
### Use constexpr When Possible
```cpp
// Good: Computed at compile time
constexpr Vector3<float> gravity{0.0f, 0.0f, -9.81f};
constexpr float max_range = 1000.0f;
constexpr float max_range_sq = max_range * max_range;
// Use in runtime calculations
if (position.length_sqr() < max_range_sq) {
// ...
}
```
### Prefer Squared Distance
```cpp
// Good: Avoids expensive sqrt
constexpr float max_dist_sq = 100.0f * 100.0f;
for (const auto& entity : entities) {
if (entity.pos.distance_to_sqr(player_pos) < max_dist_sq) {
// Process nearby entity
}
}
// Avoid: Unnecessary sqrt calls
constexpr float max_dist = 100.0f;
for (const auto& entity : entities) {
if (entity.pos.distance_to(player_pos) < max_dist) {
// More expensive
}
}
```
### Cache Expensive Calculations
```cpp
// Good: Update camera once per frame
void update_frame() {
camera.update(current_position, current_angles);
// All projections use cached matrices
for (const auto& entity : entities) {
if (auto screen = camera.world_to_screen(entity.pos)) {
draw_entity(screen->x, screen->y);
}
}
}
// Bad: Camera recreated each call
for (const auto& entity : entities) {
Camera cam(pos, angles, viewport, fov, near, far); // Expensive!
auto screen = cam.world_to_screen(entity.pos);
}
```
### Choose the Right Engine
```cpp
// Good: Use AVX2 when available
#ifdef __AVX2__
using Engine = ProjPredEngineAVX2;
#else
using Engine = ProjPredEngineLegacy;
#endif
Engine prediction_engine;
// Or runtime detection
Engine* create_best_engine() {
if (cpu_supports_avx2()) {
return new ProjPredEngineAVX2();
}
return new ProjPredEngineLegacy();
}
```
### Minimize Allocations
```cpp
// Good: Reuse vectors
std::vector<Vector3<float>> positions;
positions.reserve(expected_count);
// In loop
positions.clear(); // Doesn't deallocate
for (...) {
positions.push_back(compute_position());
}
// Bad: Allocate every time
for (...) {
std::vector<Vector3<float>> positions; // Allocates each iteration
// ...
}
```
---
## Type Safety
### Use Strong Angle Types
```cpp
// Good: Type-safe angles
PitchAngle pitch = PitchAngle::from_degrees(45.0f);
YawAngle yaw = YawAngle::from_degrees(90.0f);
ViewAngles angles{pitch, yaw, RollAngle::from_degrees(0.0f)};
// Bad: Raw floats lose safety
float pitch = 45.0f; // No range checking
float yaw = 90.0f; // Can go out of bounds
```
### Match Engine Types
```cpp
// Good: Use matching types from same engine
using namespace omath::source_engine;
Camera camera = /* ... */;
ViewAngles angles = /* ... */;
// Bad: Mixing engine types
using UnityCamera = omath::unity_engine::Camera;
using SourceAngles = omath::source_engine::ViewAngles;
UnityCamera camera{pos, SourceAngles{}, ...}; // May cause issues!
```
### Template Type Parameters
```cpp
// Good: Explicit and clear
Vector3<float> position;
Vector3<double> high_precision_pos;
// Okay: Use default float
Vector3<> position; // Defaults to float
// Avoid: Mixing types unintentionally
Vector3<float> a;
Vector3<double> b;
auto result = a + b; // Type mismatch!
```
---
## Testing & Validation
### Test Edge Cases
```cpp
void test_projection() {
Camera camera = setup_camera();
// Test normal case
assert(camera.world_to_screen({100, 100, 100}).has_value());
// Test edge cases
assert(!camera.world_to_screen({0, 0, -100}).has_value()); // Behind
assert(!camera.world_to_screen({1e10, 0, 0}).has_value()); // Too far
// Test boundaries
Vector3<float> at_near{0, 0, camera.near_plane() + 0.1f};
assert(camera.world_to_screen(at_near).has_value());
}
```
### Validate Assumptions
```cpp
void validate_game_data() {
// Validate FOV
float fov = read_game_fov();
assert(fov > 1.0f && fov < 179.0f);
// Validate positions
Vector3<float> pos = read_player_position();
assert(std::isfinite(pos.x));
assert(std::isfinite(pos.y));
assert(std::isfinite(pos.z));
// Validate viewport
ViewPort vp = read_viewport();
assert(vp.width > 0 && vp.height > 0);
}
```
### Use Assertions
```cpp
// Good: Catch errors early in development
void shoot_projectile(const Projectile& proj) {
assert(proj.speed > 0.0f && "Projectile speed must be positive");
assert(std::isfinite(proj.origin.length()) && "Invalid projectile origin");
// Continue with logic
}
// Add debug-only checks
#ifndef NDEBUG
if (!is_valid_input(data)) {
std::cerr << "Warning: Invalid input detected\n";
}
#endif
```
---
## Memory & Resources
### RAII for Resources
```cpp
// Good: Automatic cleanup
class GameOverlay {
Camera camera_;
std::vector<Entity> entities_;
public:
GameOverlay(/* ... */) : camera_(/* ... */) {
entities_.reserve(1000);
}
// Resources cleaned up automatically
~GameOverlay() = default;
};
```
### Avoid Unnecessary Copies
```cpp
// Good: Pass by const reference
void draw_entities(const std::vector<Vector3<float>>& positions) {
for (const auto& pos : positions) {
// Process position
}
}
// Bad: Copies entire vector
void draw_entities(std::vector<Vector3<float>> positions) {
// Expensive copy!
}
// Good: Move when transferring ownership
std::vector<Vector3<float>> compute_positions();
auto positions = compute_positions(); // Move, not copy
```
### Use Structured Bindings
```cpp
// Good: Clear and concise
if (auto [success, screen_pos] = try_project(world_pos); success) {
draw_at(screen_pos.x, screen_pos.y);
}
// Good: Decompose results
auto [x, y, z] = position.as_tuple();
```
---
## Documentation
### Document Assumptions
```cpp
// Good: Clear documentation
/**
* Projects world position to screen space.
*
* @param world_pos Position in world coordinates (meters)
* @return Screen position if visible, nullopt if behind camera or out of view
*
* @note Assumes camera.update() was called this frame
* @note Screen coordinates are in viewport space [0, width] x [0, height]
*/
std::optional<Vector2<float>> project(const Vector3<float>& world_pos);
```
### Explain Non-Obvious Code
```cpp
// Good: Explain the math
// Use squared distance to avoid expensive sqrt
// max_range = 100.0 → max_range_sq = 10000.0
constexpr float max_range_sq = 100.0f * 100.0f;
if (dist_sq < max_range_sq) {
// Entity is in range
}
// Explain engine-specific quirks
// Source Engine uses Z-up coordinates, but angles are in degrees
// Pitch: [-89, 89], Yaw: [-180, 180], Roll: [-180, 180]
ViewAngles angles{pitch, yaw, roll};
```
---
## Debugging
### Add Debug Visualization
```cpp
#ifndef NDEBUG
void debug_draw_projection() {
// Draw camera frustum
draw_frustum(camera);
// Draw world axes
draw_line({0,0,0}, {100,0,0}, Color::Red); // X
draw_line({0,0,0}, {0,100,0}, Color::Green); // Y
draw_line({0,0,0}, {0,0,100}, Color::Blue); // Z
// Draw projected points
for (const auto& entity : entities) {
if (auto screen = camera.world_to_screen(entity.pos)) {
draw_cross(screen->x, screen->y);
}
}
}
#endif
```
### Log Important Values
```cpp
void debug_projection_failure(const Vector3<float>& pos) {
std::cerr << "Projection failed for position: "
<< pos.x << ", " << pos.y << ", " << pos.z << "\n";
auto view_matrix = camera.get_view_matrix();
std::cerr << "View matrix:\n";
// Print matrix...
std::cerr << "Camera position: "
<< camera.position().x << ", "
<< camera.position().y << ", "
<< camera.position().z << "\n";
}
```
### Use Debug Builds
```cmake
# CMakeLists.txt
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(your_target PRIVATE
DEBUG_PROJECTION=1
VALIDATE_INPUTS=1
)
endif()
```
```cpp
#ifdef DEBUG_PROJECTION
std::cout << "Projecting: " << world_pos << "\n";
#endif
#ifdef VALIDATE_INPUTS
assert(std::isfinite(world_pos.length()));
#endif
```
---
## Platform Considerations
### Cross-Platform Code
```cpp
// Good: Platform-agnostic
constexpr float PI = 3.14159265359f;
// Avoid: Platform-specific
#ifdef _WIN32
// Windows-only code
#endif
```
### Handle Different Compilers
```cpp
// Good: Compiler-agnostic
#if defined(_MSC_VER)
// MSVC-specific
#elif defined(__GNUC__)
// GCC/Clang-specific
#endif
// Use OMath's built-in compatibility
// It handles compiler differences automatically
```
---
## Summary
**Key principles:**
1. **Safety first**: Always check optional/expected results
2. **Performance matters**: Use constexpr, avoid allocations, cache results
3. **Type safety**: Use strong types, match engine types
4. **Clear code**: Use aliases, document assumptions, explain non-obvious logic
5. **Test thoroughly**: Validate inputs, test edge cases, add assertions
6. **Debug effectively**: Add visualization, log values, use debug builds
---
## See Also
- [Troubleshooting Guide](troubleshooting.md)
- [FAQ](faq.md)
- [API Overview](api_overview.md)
- [Tutorials](tutorials.md)
---
*Last updated: 1 Nov 2025*

406
docs/faq.md Normal file
View File

@@ -0,0 +1,406 @@
# Frequently Asked Questions (FAQ)
Common questions and answers about OMath.
---
## General Questions
### What is OMath?
OMath is a modern C++ math library designed for game development, graphics programming, and high-performance computing. It provides:
- Vector and matrix operations
- 3D projection and camera systems
- Projectile prediction
- Collision detection
- Support for multiple game engines (Source, Unity, Unreal, etc.)
- Pattern scanning utilities
### Why choose OMath over other math libraries?
- **Modern C++**: Uses C++20/23 features (concepts, `constexpr`, `std::expected`)
- **No legacy code**: Built from scratch without legacy baggage
- **Game engine support**: Pre-configured for Source, Unity, Unreal, Frostbite, etc.
- **Zero dependencies**: No external dependencies needed (except for testing)
- **Performance**: AVX2 optimizations available
- **Type safety**: Strong typing prevents common errors
- **Cross-platform**: Works on Windows, Linux, and macOS
### Is OMath suitable for production use?
Yes! OMath is production-ready and used in various projects. It has:
- Comprehensive test coverage
- Clear error handling
- Well-documented API
- Active maintenance and community support
---
## Installation & Setup
### How do I install OMath?
Three main methods:
**vcpkg (recommended):**
```bash
vcpkg install orange-math
```
**xrepo:**
```bash
xrepo install omath
```
**From source:**
See [Installation Guide](install.md)
### What are the minimum requirements?
- **Compiler**: C++20 support required
- GCC 10+
- Clang 11+
- MSVC 2019 16.10+
- **CMake**: 3.15+ (if building from source)
- **Platform**: Windows, Linux, or macOS
### Do I need C++23?
C++23 is **recommended** but not required. Some features like `std::expected` work better with C++23, but fallbacks are available for C++20.
### Can I use OMath in a C++17 project?
No, OMath requires C++20 minimum due to use of concepts, `constexpr` enhancements, and other C++20 features.
---
## Usage Questions
### How do I include OMath in my project?
**Full library:**
```cpp
#include <omath/omath.hpp>
```
**Specific components:**
```cpp
#include <omath/linear_algebra/vector3.hpp>
#include <omath/engines/source_engine/camera.hpp>
```
### Which game engine should I use?
Choose based on your target game or application:
| Engine | Use For |
|--------|---------|
| **Source Engine** | CS:GO, TF2, CS2, Half-Life, Portal, L4D |
| **Unity Engine** | Unity games (many indie and mobile games) |
| **Unreal Engine** | Fortnite, Unreal games |
| **Frostbite** | Battlefield, Star Wars games (EA titles) |
| **IW Engine** | Call of Duty series |
| **OpenGL** | Custom OpenGL applications, generic 3D |
### How do I switch between engines?
Just change the namespace:
```cpp
// Source Engine
using namespace omath::source_engine;
Camera cam = /* ... */;
// Unity Engine
using namespace omath::unity_engine;
Camera cam = /* ... */;
```
Each engine has the same API but different coordinate system handling.
### What if my game isn't listed?
Use the **OpenGL engine** as a starting point - it uses canonical OpenGL conventions. You may need to adjust coordinate transformations based on your specific game.
---
## Performance Questions
### Should I use the AVX2 or Legacy engine?
**Use AVX2 if:**
- Target modern CPUs (2013+)
- Need maximum performance
- Can accept reduced compatibility
**Use Legacy if:**
- Need broad compatibility
- Target older CPUs or ARM
- Unsure about target hardware
The API is identical - just change the class:
```cpp
// Legacy (compatible)
ProjPredEngineLegacy engine;
// AVX2 (faster)
ProjPredEngineAVX2 engine;
```
### How much faster is AVX2?
Typically 2-4x faster for projectile prediction calculations, depending on the CPU and specific use case.
### Are vector operations constexpr?
Yes! Most operations are `constexpr` and can be evaluated at compile-time:
```cpp
constexpr Vector3<float> v{1, 2, 3};
constexpr auto len_sq = v.length_sqr(); // Computed at compile time
```
### Is OMath thread-safe?
- **Immutable operations** (vector math, etc.) are thread-safe
- **Mutable state** (Camera updates) is NOT thread-safe
- Use separate instances per thread or synchronize access
---
## Troubleshooting
### `world_to_screen()` always returns `nullopt`
Check:
1. **Is the point behind the camera?** Points behind the camera cannot be projected.
2. **Are near/far planes correct?** Ensure `near < far` and both are positive.
3. **Is FOV valid?** FOV should be between 1° and 179°.
4. **Are camera angles normalized?** Use engine-provided angle types.
### Angles are wrapping incorrectly
Use the correct angle type:
```cpp
// Good: uses proper angle type
PitchAngle pitch = PitchAngle::from_degrees(45.0f);
// Bad: raw float loses normalization
float pitch = 45.0f;
```
### Projection seems mirrored or inverted
You may be using the wrong engine trait. Each engine has different coordinate conventions:
- **Source/Unity**: Z-up
- **Unreal**: Z-up, different handedness
- **OpenGL**: Y-up
Ensure you're using the trait matching your game.
### Pattern scanning finds multiple matches
This is normal! Patterns may appear multiple times. Solutions:
1. Make the pattern more specific (more bytes, fewer wildcards)
2. Use additional context (nearby code patterns)
3. Verify each match programmatically
### Projectile prediction returns `nullopt`
Common reasons:
1. **Target too fast**: Target velocity exceeds projectile speed
2. **Out of range**: Distance exceeds max flight time
3. **Invalid input**: Check projectile speed > 0
4. **Gravity too strong**: Projectile can't reach target height
### Compilation errors about `std::expected`
If using C++20 (not C++23), you may need a backport library like `tl::expected`:
```cmake
# CMakeLists.txt
find_package(tl-expected CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE tl::expected)
```
Or upgrade to C++23 if possible.
---
## Feature Questions
### Can I use OMath with DirectX/OpenGL/Vulkan?
Yes! OMath matrices and vectors work with all graphics APIs. Use:
- **OpenGL**: `opengl_engine` traits
- **DirectX**: Use appropriate engine trait or OpenGL as base
- **Vulkan**: Use OpenGL traits as starting point
### Does OMath support quaternions?
Not currently. Quaternion support may be added in future versions. For now, use euler angles (ViewAngles) or convert manually.
### Can I extend OMath with custom engine traits?
Yes! Implement the `CameraEngineConcept`:
```cpp
class MyEngineTrait {
public:
static ViewAngles calc_look_at_angle(
const Vector3<float>& origin,
const Vector3<float>& target
);
static Mat4X4 calc_view_matrix(
const ViewAngles& angles,
const Vector3<float>& origin
);
static Mat4X4 calc_projection_matrix(
const FieldOfView& fov,
const ViewPort& viewport,
float near, float far
);
};
// Use with Camera
using MyCamera = Camera<Mat4X4, ViewAngles, MyEngineTrait>;
```
### Does OMath support SIMD for vector operations?
AVX2 support is available for projectile prediction. General vector SIMD may be added in future versions. The library already compiles to efficient code with compiler optimizations enabled.
### Can I use OMath for machine learning?
OMath is optimized for game development and graphics, not ML. For machine learning, consider libraries like Eigen or xtensor which are designed for that domain.
---
## Debugging Questions
### How do I print vectors?
OMath provides `std::formatter` support:
```cpp
#include <format>
#include <iostream>
Vector3<float> v{1, 2, 3};
std::cout << std::format("{}", v) << "\n"; // Prints: [1, 2, 3]
```
### How do I visualize projection problems?
1. Check if `world_to_screen()` succeeds
2. Print camera matrices:
```cpp
auto view = camera.get_view_matrix();
auto proj = camera.get_projection_matrix();
// Print matrix values
```
3. Test with known good points (e.g., origin, simple positions)
4. Verify viewport and FOV values
### How can I debug pattern scanning?
```cpp
PatternView pattern{"48 8B 05 ?? ?? ?? ??"};
// Print pattern details
std::cout << "Pattern length: " << pattern.size() << "\n";
std::cout << "Pattern bytes: ";
for (auto byte : pattern) {
if (byte.has_value()) {
std::cout << std::hex << (int)*byte << " ";
} else {
std::cout << "?? ";
}
}
std::cout << "\n";
```
---
## Contributing
### How can I contribute to OMath?
See [CONTRIBUTING.md](https://github.com/orange-cpp/omath/blob/master/CONTRIBUTING.md) for guidelines. Contributions welcome:
- Bug fixes
- New features
- Documentation improvements
- Test coverage
- Examples
### Where do I report bugs?
[GitHub Issues](https://github.com/orange-cpp/omath/issues)
Please include:
- OMath version
- Compiler and version
- Minimal reproducible example
- Expected vs actual behavior
### How do I request a feature?
Open a GitHub issue with:
- Use case description
- Proposed API (if applicable)
- Why existing features don't meet your needs
---
## License & Legal
### What license does OMath use?
OMath uses a custom "libomath" license. See [LICENSE](https://github.com/orange-cpp/omath/blob/master/LICENSE) for full details.
### Can I use OMath in commercial projects?
Check the LICENSE file for commercial use terms.
### Can I use OMath for game cheating/hacking?
OMath is a math library and can be used for various purposes. However:
- Using it to cheat in online games may violate game ToS
- Creating cheats may be illegal in your jurisdiction
- The developers do not condone cheating in online games
Use responsibly and ethically.
---
## Getting Help
### Where can I get help?
- **Documentation**: [http://libomath.org](http://libomath.org)
- **Discord**: [Join community](https://discord.gg/eDgdaWbqwZ)
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
- **GitHub Issues**: [Report bugs/ask questions](https://github.com/orange-cpp/omath/issues)
### Is there a Discord/community?
Yes! Join our Discord: [https://discord.gg/eDgdaWbqwZ](https://discord.gg/eDgdaWbqwZ)
### Are there video tutorials?
Check our [YouTube channel](https://youtu.be/lM_NJ1yCunw?si=-Qf5yzDcWbaxAXGQ) for demonstrations and tutorials.
---
## Didn't find your answer?
- Search the [documentation](index.md)
- Check [tutorials](tutorials.md)
- Ask on [Discord](https://discord.gg/eDgdaWbqwZ)
- Open a [GitHub issue](https://github.com/orange-cpp/omath/issues)
---
*Last updated: 1 Nov 2025*

306
docs/getting_started.md Normal file
View File

@@ -0,0 +1,306 @@
# Getting Started with OMath
Welcome to OMath! This guide will help you get up and running with the library quickly.
## What is OMath?
OMath is a modern, blazingly fast C++ math library designed for:
- **Game development** and cheat development
- **Graphics programming** (DirectX/OpenGL/Vulkan)
- **3D applications** with support for multiple game engines
- **High-performance computing** with AVX2 optimizations
Key features:
- 100% independent, no legacy C++ code
- Fully `constexpr` template-based design
- Zero additional dependencies (except for unit tests)
- Cross-platform (Windows, macOS, Linux)
- Built-in support for Source, Unity, Unreal, Frostbite, IWEngine, and OpenGL coordinate systems
---
## Installation
Choose one of the following methods to install OMath:
### Using vcpkg (Recommended)
```bash
vcpkg install orange-math
```
Then in your CMakeLists.txt:
```cmake
find_package(omath CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE omath::omath)
```
### Using xrepo
```bash
xrepo install omath
```
Then in your xmake.lua:
```lua
add_requires("omath")
target("your_target")
add_packages("omath")
```
### Building from Source
See the detailed [Installation Guide](install.md) for complete instructions.
---
## Quick Example
Here's a simple example to get you started:
```cpp
#include <omath/omath.hpp>
#include <iostream>
int main() {
using namespace omath;
// Create 3D vectors
Vector3<float> a{1.0f, 2.0f, 3.0f};
Vector3<float> b{4.0f, 5.0f, 6.0f};
// Vector operations
auto sum = a + b; // Vector addition
auto dot_product = a.dot(b); // Dot product: 32.0
auto cross_product = a.cross(b); // Cross product: (-3, 6, -3)
auto length = a.length(); // Length: ~3.74
auto normalized = a.normalized(); // Unit vector
std::cout << "Sum: [" << sum.x << ", " << sum.y << ", " << sum.z << "]\n";
std::cout << "Dot product: " << dot_product << "\n";
std::cout << "Length: " << length << "\n";
return 0;
}
```
---
## Core Concepts
### 1. Vectors
OMath provides 2D, 3D, and 4D vector types:
```cpp
using namespace omath;
Vector2<float> vec2{1.0f, 2.0f};
Vector3<float> vec3{1.0f, 2.0f, 3.0f};
Vector4<float> vec4{1.0f, 2.0f, 3.0f, 4.0f};
```
All vector types support:
- Arithmetic operations (+, -, *, /)
- Dot and cross products (where applicable)
- Length and distance calculations
- Normalization
- Component-wise operations
See: [Vector2](linear_algebra/vector2.md), [Vector3](linear_algebra/vector3.md), [Vector4](linear_algebra/vector4.md)
### 2. Matrices
4x4 matrices for transformations:
```cpp
using namespace omath;
Mat4X4 matrix = Mat4X4::identity();
// Use for transformations, projections, etc.
```
See: [Matrix Documentation](linear_algebra/mat.md)
### 3. Angles
Strong-typed angle system with automatic range management:
```cpp
using namespace omath;
auto angle = Angle<float, 0.0f, 360.0f>::from_degrees(45.0f);
auto radians = angle.as_radians();
// View angles for camera systems
ViewAngles view{
PitchAngle::from_degrees(-10.0f),
YawAngle::from_degrees(90.0f),
RollAngle::from_degrees(0.0f)
};
```
See: [Angle](trigonometry/angle.md), [View Angles](trigonometry/view_angles.md)
### 4. 3D Projection
Built-in camera and projection systems:
```cpp
using namespace omath;
using namespace omath::projection;
ViewPort viewport{1920.0f, 1080.0f};
auto fov = FieldOfView::from_degrees(90.0f);
// Example using Source Engine
using namespace omath::source_engine;
Camera cam(
Vector3<float>{0, 0, 100}, // Position
ViewAngles{}, // Angles
viewport,
fov,
0.1f, // near plane
1000.0f // far plane
);
// Project 3D point to 2D screen
Vector3<float> world_pos{100, 50, 75};
if (auto screen_pos = cam.world_to_screen(world_pos)) {
std::cout << "Screen: " << screen_pos->x << ", " << screen_pos->y << "\n";
}
```
See: [Camera](projection/camera.md)
### 5. Game Engine Support
OMath provides pre-configured traits for major game engines:
```cpp
// Source Engine
#include <omath/engines/source_engine/camera.hpp>
using SourceCamera = omath::source_engine::Camera;
// Unity Engine
#include <omath/engines/unity_engine/camera.hpp>
using UnityCamera = omath::unity_engine::Camera;
// Unreal Engine
#include <omath/engines/unreal_engine/camera.hpp>
using UnrealCamera = omath::unreal_engine::Camera;
// And more: OpenGL, Frostbite, IWEngine
```
Each engine has its own coordinate system conventions automatically handled.
See: Engine-specific docs in [engines/](engines/) folder
---
## Common Use Cases
### World-to-Screen Projection
```cpp
using namespace omath;
using namespace omath::source_engine;
Camera cam = /* initialize camera */;
Vector3<float> enemy_position{100, 200, 50};
if (auto screen = cam.world_to_screen(enemy_position)) {
// Draw ESP box at screen->x, screen->y
std::cout << "Enemy on screen at: " << screen->x << ", " << screen->y << "\n";
} else {
// Enemy not visible (behind camera or outside frustum)
}
```
### Projectile Prediction
```cpp
using namespace omath::projectile_prediction;
Projectile bullet{
Vector3<float>{0, 0, 0}, // shooter position
1000.0f, // muzzle velocity (m/s)
Vector3<float>{0, 0, -9.81f} // gravity
};
Target enemy{
Vector3<float>{100, 200, 50}, // position
Vector3<float>{10, 0, 0} // velocity
};
// Calculate where to aim
ProjPredEngineLegacy engine;
if (auto aim_point = engine.maybe_calculate_aim_point(bullet, enemy)) {
// Aim at *aim_point to hit moving target
}
```
See: [Projectile Prediction](projectile_prediction/projectile_engine.md)
### Collision Detection
```cpp
using namespace omath;
// Ray-plane intersection
Plane ground{
Vector3<float>{0, 0, 0}, // point on plane
Vector3<float>{0, 0, 1} // normal (pointing up)
};
Vector3<float> ray_origin{0, 0, 100};
Vector3<float> ray_direction{0, 0, -1};
if (auto hit = ground.intersects_ray(ray_origin, ray_direction)) {
std::cout << "Hit ground at: " << hit->x << ", " << hit->y << ", " << hit->z << "\n";
}
```
See: [Collision Detection](collision/line_tracer.md)
### Pattern Scanning
```cpp
#include <omath/utility/pattern_scan.hpp>
using namespace omath;
std::vector<uint8_t> memory = /* ... */;
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
if (auto result = pattern_scan(memory, pattern)) {
std::cout << "Pattern found at offset: " << result->offset << "\n";
}
```
See: [Pattern Scanning](utility/pattern_scan.md)
---
## Next Steps
Now that you have the basics, explore these topics:
1. **[API Reference](index.md)** - Complete API documentation
2. **[Examples](../examples/)** - Working code examples
3. **[Engine-Specific Features](engines/)** - Deep dive into game engine support
4. **[Advanced Topics](#)** - Performance optimization, custom traits, etc.
---
## Getting Help
- **Documentation**: [http://libomath.org](http://libomath.org)
- **Discord**: [Join our community](https://discord.gg/eDgdaWbqwZ)
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
- **Issues**: [GitHub Issues](https://github.com/orange-cpp/omath/issues)
---
*Last updated: 1 Nov 2025*

View File

@@ -25,12 +25,135 @@
</a>
</p>
</div>
OMath is a 100% independent, constexpr template blazingly fast math library that doesn't have legacy C++ code.
It provides the latest features, is highly customizable, has all for cheat development, DirectX/OpenGL/Vulkan support, premade support for different game engines, much more constexpr stuff than in other libraries and more...
---
## 🚀 Quick Start
**New to OMath?** Start here:
- **[Getting Started Guide](getting_started.md)** - Installation and first steps
- **[API Overview](api_overview.md)** - High-level API reference
- **[Installation Instructions](install.md)** - Detailed setup guide
**Quick example:**
```cpp
#include <omath/omath.hpp>
using namespace omath;
Vector3<float> a{1, 2, 3};
Vector3<float> b{4, 5, 6};
auto dot = a.dot(b); // 32.0
auto cross = a.cross(b); // (-3, 6, -3)
auto distance = a.distance_to(b); // ~5.196
```
---
## 📚 Documentation Structure
### Core Mathematics
**Linear Algebra**
- [Vector2](linear_algebra/vector2.md) - 2D vectors with full operator support
- [Vector3](linear_algebra/vector3.md) - 3D vectors, dot/cross products, angles
- [Vector4](linear_algebra/vector4.md) - 4D vectors (homogeneous coordinates)
- [Mat4X4](linear_algebra/mat.md) - 4×4 matrices for transformations
- [Triangle](linear_algebra/triangle.md) - Triangle primitive and utilities
**Trigonometry**
- [Angle](trigonometry/angle.md) - Strong-typed angle system with range enforcement
- [Angles](trigonometry/angles.md) - Angle utilities and conversions
- [View Angles](trigonometry/view_angles.md) - Pitch/Yaw/Roll for camera systems
**3D Primitives**
- [Box](3d_primitives/box.md) - Axis-aligned bounding boxes
- [Plane](3d_primitives/plane.md) - Infinite planes and intersections
### Game Development Features
**Projection & Camera**
- [Camera](projection/camera.md) - Generic camera system with engine traits
- [Error Codes](projection/error_codes.md) - Projection error handling
**Collision Detection**
- [Line Tracer](collision/line_tracer.md) - Ray-triangle, ray-plane intersections
**Projectile Prediction**
- [Projectile Engine Interface](projectile_prediction/projectile_engine.md) - Base interface
- [Projectile](projectile_prediction/projectile.md) - Projectile properties
- [Target](projectile_prediction/target.md) - Target state representation
- [Legacy Engine](projectile_prediction/proj_pred_engine_legacy.md) - Standard implementation
- [AVX2 Engine](projectile_prediction/proj_pred_engine_avx2.md) - Optimized implementation
**Pathfinding**
- [A* Algorithm](pathfinding/a_star.md) - A* pathfinding implementation
- [Navigation Mesh](pathfinding/navigation_mesh.md) - Triangle-based navigation
### Game Engine Support
OMath provides built-in support for multiple game engines with proper coordinate system handling:
**Source Engine** (Valve - CS:GO, TF2, etc.)
- [Camera Trait](engines/source_engine/camera_trait.md)
- [Pred Engine Trait](engines/source_engine/pred_engine_trait.md)
- [Constants](engines/source_engine/constants.md)
- [Formulas](engines/source_engine/formulas.md)
**Unity Engine**
- [Camera Trait](engines/unity_engine/camera_trait.md)
- [Pred Engine Trait](engines/unity_engine/pred_engine_trait.md)
- [Constants](engines/unity_engine/constants.md)
- [Formulas](engines/unity_engine/formulas.md)
**Unreal Engine** (Epic Games)
- [Camera Trait](engines/unreal_engine/camera_trait.md)
- [Pred Engine Trait](engines/unreal_engine/pred_engine_trait.md)
- [Constants](engines/unreal_engine/constants.md)
- [Formulas](engines/unreal_engine/formulas.md)
**Frostbite Engine** (EA - Battlefield, etc.)
- [Camera Trait](engines/frostbite/camera_trait.md)
- [Pred Engine Trait](engines/frostbite/pred_engine_trait.md)
- [Constants](engines/frostbite/constants.md)
- [Formulas](engines/frostbite/formulas.md)
**IW Engine** (Infinity Ward - Call of Duty)
- [Camera Trait](engines/iw_engine/camera_trait.md)
- [Pred Engine Trait](engines/iw_engine/pred_engine_trait.md)
- [Constants](engines/iw_engine/constants.md)
- [Formulas](engines/iw_engine/formulas.md)
**OpenGL Engine** (Canonical OpenGL)
- [Camera Trait](engines/opengl_engine/camera_trait.md)
- [Pred Engine Trait](engines/opengl_engine/pred_engine_trait.md)
- [Constants](engines/opengl_engine/constants.md)
- [Formulas](engines/opengl_engine/formulas.md)
### Utilities
**Color**
- [Color](utility/color.md) - RGBA color with conversions
**Pattern Scanning & Memory**
- [Pattern Scan](utility/pattern_scan.md) - Binary pattern search with wildcards
- [PE Pattern Scan](utility/pe_pattern_scan.md) - PE file pattern scanning
**Reverse Engineering**
- [External Rev Object](rev_eng/external_rev_object.md) - External process memory access
- [Internal Rev Object](rev_eng/internal_rev_object.md) - Internal memory access
---
## ✨ Key Features
# Features
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
- **Ease of Use**: Simplified interface for convenient integration into various projects.
@@ -43,7 +166,28 @@ It provides the latest features, is highly customizable, has all for cheat devel
- **Cross platform**: Supports Windows, MacOS and Linux.
- **Algorithms**: Has ability to scan for byte pattern with wildcards in PE files/modules, binary slices, works even with Wine apps.
# Gallery
---
## 📖 Common Use Cases
### World-to-Screen Projection
Project 3D world coordinates to 2D screen space for ESP overlays, UI elements, or visualization.
### Projectile Prediction
Calculate aim points for moving targets considering projectile speed, gravity, and target velocity.
### Collision Detection
Perform ray-casting, line tracing, and intersection tests for hit detection and physics.
### Pattern Scanning
Search for byte patterns in memory for reverse engineering, modding, or tool development.
### Pathfinding
Find optimal paths through 3D spaces using A* algorithm and navigation meshes.
---
## 🎮 Gallery
<br>
@@ -68,6 +212,26 @@ It provides the latest features, is highly customizable, has all for cheat devel
<br>
<br>
---
## 🤝 Community & Support
- **Documentation**: [http://libomath.org](http://libomath.org)
- **GitHub**: [orange-cpp/omath](https://github.com/orange-cpp/omath)
- **Discord**: [Join our community](https://discord.gg/eDgdaWbqwZ)
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
- **Issues**: [Report bugs or request features](https://github.com/orange-cpp/omath/issues)
---
## 💡 Contributing
OMath is open source and welcomes contributions! See [CONTRIBUTING.md](https://github.com/orange-cpp/omath/blob/master/CONTRIBUTING.md) for guidelines.
---
*Last updated: 1 Nov 2025*
<!----------------------------------{ Images }--------------------------------->
[APEX Preview]: images/showcase/apex.png
[BO2 Preview]: images/showcase/cod_bo2.png

525
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,525 @@
# Troubleshooting Guide
Solutions to common problems when using OMath.
---
## Build & Compilation Issues
### Error: C++20 features not available
**Problem:** Compiler doesn't support C++20.
**Solution:**
Upgrade your compiler:
- **GCC**: Version 10 or newer
- **Clang**: Version 11 or newer
- **MSVC**: Visual Studio 2019 16.10 or newer
Set C++20 in CMakeLists.txt:
```cmake
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
```
### Error: `std::expected` not found
**Problem:** Using C++20 without C++23's `std::expected`.
**Solutions:**
1. **Upgrade to C++23** (recommended):
```cmake
set(CMAKE_CXX_STANDARD 23)
```
2. **Use a backport library**:
```cmake
find_package(tl-expected CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE tl::expected)
```
### Error: `omath/omath.hpp` not found
**Problem:** OMath not installed or not in include path.
**Solution:**
Check installation:
```bash
# vcpkg
vcpkg list | grep omath
# Check if files exist
ls /path/to/vcpkg/installed/x64-linux/include/omath
```
In CMakeLists.txt:
```cmake
find_package(omath CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE omath::omath)
```
### Linker errors with AVX2 engine
**Problem:** Undefined references to AVX2 functions.
**Solution:**
Enable AVX2 in your build:
```cmake
if(MSVC)
target_compile_options(your_target PRIVATE /arch:AVX2)
else()
target_compile_options(your_target PRIVATE -mavx2)
endif()
```
Or use the legacy engine instead:
```cpp
// Use this instead of ProjPredEngineAVX2
ProjPredEngineLegacy engine;
```
---
## Runtime Issues
### `world_to_screen()` always returns `nullopt`
**Common causes:**
1. **Point behind camera**
```cpp
// Point is behind the camera
Vector3<float> behind = camera_pos - Vector3<float>{0, 0, 100};
auto result = camera.world_to_screen(behind); // Returns nullopt
```
**Fix:** Only project points in front of camera. Check Z-coordinate in view space.
2. **Invalid near/far planes**
```cpp
// Bad: near >= far
Camera camera(pos, angles, viewport, fov, 100.0f, 1.0f);
// Good: near < far
Camera camera(pos, angles, viewport, fov, 0.1f, 1000.0f);
```
3. **Invalid FOV**
```cpp
// Bad: FOV out of range
auto fov = FieldOfView::from_degrees(0.0f); // Too small
auto fov = FieldOfView::from_degrees(180.0f); // Too large
// Good: FOV in valid range
auto fov = FieldOfView::from_degrees(90.0f);
```
4. **Uninitialized camera**
```cpp
// Make sure camera is properly initialized
camera.update(current_position, current_angles);
```
**Debugging:**
```cpp
Vector3<float> world_pos{100, 100, 100};
// Check projection step by step
std::cout << "World pos: " << world_pos.x << ", "
<< world_pos.y << ", " << world_pos.z << "\n";
auto view_matrix = camera.get_view_matrix();
// Transform to view space manually and check if Z > 0
if (auto screen = camera.world_to_screen(world_pos)) {
std::cout << "Success: " << screen->x << ", " << screen->y << "\n";
} else {
std::cout << "Failed - check if point is behind camera\n";
}
```
### Angles wrapping incorrectly
**Problem:** Angles not normalizing to expected ranges.
**Solution:**
Use proper angle types:
```cpp
// Wrong: using raw floats
float pitch = 95.0f; // Out of valid range!
// Right: using typed angles
auto pitch = PitchAngle::from_degrees(89.0f); // Clamped to valid range
```
For custom ranges:
```cpp
// Define custom angle with wrapping
auto angle = Angle<float, -180.0f, 180.0f, AngleFlags::Normalized>::from_degrees(270.0f);
// Result: -90° (wrapped)
```
### Projection appears mirrored or inverted
**Problem:** Using wrong engine trait for your game.
**Solution:**
Different engines have different coordinate systems:
| Symptom | Likely Issue | Fix |
|---------|-------------|-----|
| Upside down | Y-axis inverted | Try different engine or negate Y |
| Left-right flipped | Wrong handedness | Check engine documentation |
| Rotated 90° | Axis swap | Verify engine coordinate system |
```cpp
// Try different engine traits
using namespace omath::source_engine; // Z-up, left-handed
using namespace omath::unity_engine; // Y-up, left-handed
using namespace omath::unreal_engine; // Z-up, left-handed (different conventions)
using namespace omath::opengl_engine; // Y-up, right-handed
```
If still wrong, manually transform coordinates:
```cpp
// Example: swap Y and Z for Y-up to Z-up conversion
Vector3<float> convert_y_up_to_z_up(const Vector3<float>& pos) {
return Vector3<float>{pos.x, pos.z, pos.y};
}
```
---
## Projectile Prediction Issues
### `maybe_calculate_aim_point()` returns `nullopt`
**Common causes:**
1. **Target moving too fast**
```cpp
Target target;
target.velocity = Vector3<float>{1000, 0, 0}; // Very fast!
Projectile proj;
proj.speed = 500.0f; // Too slow to catch target
// Returns nullopt - projectile can't catch target
```
**Fix:** Check if projectile speed > target speed in the direction of motion.
2. **Zero projectile speed**
```cpp
Projectile proj;
proj.speed = 0.0f; // Invalid!
// Returns nullopt
```
**Fix:** Ensure `proj.speed > 0`.
3. **Invalid positions**
```cpp
// NaN or infinite values
target.position = Vector3<float>{NAN, 0, 0};
// Returns nullopt
```
**Fix:** Validate all input values are finite.
4. **Target out of range**
```cpp
// Target very far away
float distance = shooter_pos.distance_to(target.position);
float max_range = proj.speed * max_flight_time;
if (distance > max_range) {
// Will return nullopt
}
```
**Debugging:**
```cpp
Projectile proj{/* ... */};
Target target{/* ... */};
// Check inputs
assert(proj.speed > 0);
assert(std::isfinite(target.position.length()));
assert(std::isfinite(target.velocity.length()));
// Check if target is reachable
float distance = proj.origin.distance_to(target.position);
float target_speed = target.velocity.length();
std::cout << "Distance: " << distance << "\n";
std::cout << "Projectile speed: " << proj.speed << "\n";
std::cout << "Target speed: " << target_speed << "\n";
if (target_speed >= proj.speed) {
std::cout << "Target may be too fast!\n";
}
```
### Aim point is inaccurate
**Problem:** Calculated aim point doesn't hit target.
**Possible causes:**
1. **Unit mismatch**
```cpp
// All units must match!
proj.speed = 800.0f; // meters per second
target.velocity = Vector3<float>{2, 1, 0}; // Must also be m/s!
// If using different units (e.g., game units vs meters), convert:
float game_units_to_meters = 0.01905f; // Example for Source
target.velocity = game_velocity * game_units_to_meters;
```
2. **Wrong gravity vector**
```cpp
// Source Engine: Z-up
proj.gravity = Vector3<float>{0, 0, -9.81f};
// Unity: Y-up
proj.gravity = Vector3<float>{0, -9.81f, 0};
```
3. **Target velocity not updated**
```cpp
// Update target velocity each frame
target.velocity = current_velocity; // Not last frame's velocity!
```
---
## Pattern Scanning Issues
### Pattern not found when it should be
**Problem:** `pattern_scan()` returns `nullopt` but pattern exists.
**Solutions:**
1. **Pattern syntax error**
```cpp
// Wrong: missing spaces
PatternView pattern{"488B05????????"};
// Right: spaces between bytes
PatternView pattern{"48 8B 05 ?? ?? ?? ??"};
```
2. **Pattern too specific**
```cpp
// May fail if any byte is different
PatternView pattern{"48 8B 05 01 02 03 04 48 85 C0"};
// Better: use wildcards for variable bytes
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
```
3. **Searching wrong memory region**
```cpp
// Make sure you're scanning the right memory
std::vector<uint8_t> code_section = get_code_section();
auto result = pattern_scan(code_section, pattern);
```
4. **Pattern might have multiple matches**
```cpp
// Find all matches instead of just first
size_t offset = 0;
while (offset < memory.size()) {
auto result = pattern_scan(
std::span(memory.begin() + offset, memory.end()),
pattern
);
if (result) {
std::cout << "Match at: " << offset + result->offset << "\n";
offset += result->offset + 1;
} else {
break;
}
}
```
### Pattern found at wrong location
**Problem:** Pattern matches unintended code.
**Solutions:**
1. **Make pattern more specific**
```cpp
// Too generic
PatternView pattern{"48 8B"};
// More specific - include more context
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0 74 ??"};
```
2. **Verify found address**
```cpp
if (auto result = pattern_scan(memory, pattern)) {
// Verify by checking nearby bytes
size_t offset = result->offset;
// Check if instruction makes sense
if (memory[offset] == 0x48 && memory[offset + 1] == 0x8B) {
// Looks good
}
}
```
3. **Use multiple patterns**
```cpp
// Find reference function first
auto ref_pattern = PatternView{"E8 ?? ?? ?? ?? 85 C0"};
auto ref_result = pattern_scan(memory, ref_pattern);
// Then search near that location
// This provides context validation
```
---
## Vector & Math Issues
### `normalized()` returns zero vector
**Problem:** Normalizing a zero-length vector.
**Behavior:**
```cpp
Vector3<float> zero{0, 0, 0};
auto result = zero.normalized(); // Returns {0, 0, 0}
```
This is **intentional** to avoid NaN. Check vector length first:
```cpp
if (v.length() > 0.001f) {
auto normalized = v.normalized();
// Use normalized vector
} else {
// Handle zero-length case
}
```
### `angle_between()` returns error
**Problem:** One or both vectors have zero length.
**Solution:**
```cpp
auto angle_result = v1.angle_between(v2);
if (angle_result) {
float degrees = angle_result->as_degrees();
} else {
// Handle error - one or both vectors have zero length
std::cerr << "Cannot compute angle between zero-length vectors\n";
}
```
### Cross product seems wrong
**Problem:** Unexpected cross product result.
**Check:**
1. **Right-handed system**
```cpp
Vector3<float> x{1, 0, 0};
Vector3<float> y{0, 1, 0};
auto z = x.cross(y); // Should be {0, 0, 1} in right-handed system
```
2. **Order matters**
```cpp
auto cross1 = a.cross(b); // {x1, y1, z1}
auto cross2 = b.cross(a); // {-x1, -y1, -z1} (opposite direction!)
```
---
## Performance Issues
### Code is slower than expected
**Solutions:**
1. **Enable optimizations**
```cmake
# CMakeLists.txt
target_compile_options(your_target PRIVATE
$<$<CONFIG:Release>:-O3>
$<$<CONFIG:Release>:-march=native>
)
```
2. **Use AVX2 engine**
```cpp
// Instead of
ProjPredEngineLegacy engine;
// Use
ProjPredEngineAVX2 engine;
```
3. **Avoid unnecessary operations**
```cpp
// Bad: recompute every frame
for (auto& entity : entities) {
float dist = entity.pos.distance_to(player_pos); // Expensive sqrt!
if (dist < 100.0f) { /* ... */ }
}
// Good: use squared distance
constexpr float max_dist_sq = 100.0f * 100.0f;
for (auto& entity : entities) {
float dist_sq = entity.pos.distance_to_sqr(player_pos); // No sqrt!
if (dist_sq < max_dist_sq) { /* ... */ }
}
```
4. **Cache matrices**
```cpp
// Bad: recompute matrix every call
for (auto& pos : positions) {
auto screen = camera.world_to_screen(pos); // Recomputes matrices!
}
// Good: matrices are cached in camera automatically
camera.update(pos, angles); // Updates matrices once
for (auto& pos : positions) {
auto screen = camera.world_to_screen(pos); // Uses cached matrices
}
```
---
## Getting More Help
If your issue isn't covered here:
1. **Check the docs**: [API Overview](api_overview.md), [Tutorials](tutorials.md)
2. **Search GitHub issues**: [Issues page](https://github.com/orange-cpp/omath/issues)
3. **Ask on Discord**: [Join community](https://discord.gg/eDgdaWbqwZ)
4. **Open a new issue**: Include:
- OMath version
- Compiler and version
- Minimal reproducible example
- What you expected vs what happened
---
*Last updated: 1 Nov 2025*

616
docs/tutorials.md Normal file
View File

@@ -0,0 +1,616 @@
# OMath Tutorials
This page provides step-by-step tutorials for common OMath use cases.
---
## Tutorial 1: Basic Vector Math
Learn the fundamentals of vector operations in OMath.
### Step 1: Include OMath
```cpp
#include <omath/omath.hpp>
#include <iostream>
using namespace omath;
```
### Step 2: Create Vectors
```cpp
// 2D vectors
Vector2<float> v2a{3.0f, 4.0f};
Vector2<float> v2b{1.0f, 2.0f};
// 3D vectors
Vector3<float> v3a{1.0f, 2.0f, 3.0f};
Vector3<float> v3b{4.0f, 5.0f, 6.0f};
// 4D vectors (often used for homogeneous coordinates)
Vector4<float> v4{1.0f, 2.0f, 3.0f, 1.0f};
```
### Step 3: Perform Operations
```cpp
// Addition
auto sum = v3a + v3b; // {5, 7, 9}
// Subtraction
auto diff = v3a - v3b; // {-3, -3, -3}
// Scalar multiplication
auto scaled = v3a * 2.0f; // {2, 4, 6}
// Dot product
float dot = v3a.dot(v3b); // 32.0
// Cross product (3D only)
auto cross = v3a.cross(v3b); // {-3, 6, -3}
// Length
float len = v3a.length(); // ~3.74
// Normalization (safe - returns original if length is zero)
auto normalized = v3a.normalized();
// Distance between vectors
float dist = v3a.distance_to(v3b); // ~5.196
```
### Step 4: Angle Calculations
```cpp
if (auto angle = v3a.angle_between(v3b)) {
std::cout << "Angle in degrees: " << angle->as_degrees() << "\n";
std::cout << "Angle in radians: " << angle->as_radians() << "\n";
} else {
std::cout << "Cannot compute angle (zero-length vector)\n";
}
// Check if perpendicular
if (v3a.is_perpendicular(v3b)) {
std::cout << "Vectors are perpendicular\n";
}
```
**Key takeaways:**
- All vector operations are type-safe and constexpr-friendly
- Safe normalization never produces NaN
- Angle calculations use `std::expected` for error handling
---
## Tutorial 2: World-to-Screen Projection
Project 3D coordinates to 2D screen space for overlays and ESP.
### Step 1: Choose Your Game Engine
```cpp
#include <omath/omath.hpp>
// For Source Engine games (CS:GO, TF2, etc.)
using namespace omath::source_engine;
// Or for other engines:
// using namespace omath::unity_engine;
// using namespace omath::unreal_engine;
// using namespace omath::frostbite_engine;
```
### Step 2: Set Up the Camera
```cpp
using namespace omath;
using namespace omath::projection;
// Define viewport (screen dimensions)
ViewPort viewport{1920.0f, 1080.0f};
// Define field of view
auto fov = FieldOfView::from_degrees(90.0f);
// Camera position and angles
Vector3<float> camera_pos{0.0f, 0.0f, 100.0f};
ViewAngles camera_angles{
PitchAngle::from_degrees(0.0f),
YawAngle::from_degrees(0.0f),
RollAngle::from_degrees(0.0f)
};
// Create camera (using Source Engine in this example)
Camera camera(
camera_pos,
camera_angles,
viewport,
fov,
0.1f, // near plane
1000.0f // far plane
);
```
### Step 3: Project 3D Points
```cpp
// 3D world position (e.g., enemy player position)
Vector3<float> enemy_pos{150.0f, 200.0f, 75.0f};
// Project to screen
if (auto screen = camera.world_to_screen(enemy_pos)) {
std::cout << "Enemy on screen at: "
<< screen->x << ", " << screen->y << "\n";
// Draw ESP box or marker at screen->x, screen->y
// Note: screen coordinates are in viewport space (0-width, 0-height)
} else {
// Enemy is not visible (behind camera or outside frustum)
std::cout << "Enemy not visible\n";
}
```
### Step 4: Update Camera for Each Frame
```cpp
void render_frame() {
// Read current camera data from game
Vector3<float> new_pos = read_camera_position();
ViewAngles new_angles = read_camera_angles();
// Update camera
camera.update(new_pos, new_angles);
// Project all entities
for (const auto& entity : entities) {
if (auto screen = camera.world_to_screen(entity.position)) {
draw_esp_box(screen->x, screen->y);
}
}
}
```
**Key takeaways:**
- Choose the engine trait that matches your target game
- `world_to_screen()` returns `std::optional` - always check the result
- Update camera each frame for accurate projections
- Screen coordinates are in the viewport space you defined
---
## Tutorial 3: Projectile Prediction (Aim-Bot)
Calculate where to aim to hit a moving target.
### Step 1: Define Projectile Properties
```cpp
#include <omath/omath.hpp>
#include <omath/projectile_prediction/proj_pred_engine_legacy.hpp>
using namespace omath;
using namespace omath::projectile_prediction;
// Define your weapon's projectile
Projectile bullet;
bullet.origin = Vector3<float>{0, 0, 0}; // Shooter position
bullet.speed = 800.0f; // Muzzle velocity (m/s or game units/s)
bullet.gravity = Vector3<float>{0, 0, -9.81f}; // Gravity vector
```
### Step 2: Define Target State
```cpp
// Target information (enemy player)
Target enemy;
enemy.position = Vector3<float>{100, 200, 50}; // Current position
enemy.velocity = Vector3<float>{10, 5, 0}; // Current velocity
```
### Step 3: Calculate Aim Point
```cpp
// Create prediction engine
// Use AVX2 version if available for better performance:
// ProjPredEngineAVX2 engine;
ProjPredEngineLegacy engine;
// Calculate where to aim
if (auto aim_point = engine.maybe_calculate_aim_point(bullet, enemy)) {
std::cout << "Aim at: "
<< aim_point->x << ", "
<< aim_point->y << ", "
<< aim_point->z << "\n";
// Calculate angles to aim_point
Vector3<float> aim_direction = (*aim_point - bullet.origin).normalized();
// Convert to view angles (engine-specific)
// ViewAngles angles = calculate_angles_to_direction(aim_direction);
// set_aim_angles(angles);
} else {
// Cannot hit target (too fast, out of range, etc.)
std::cout << "Target cannot be hit\n";
}
```
### Step 4: Handle Different Scenarios
```cpp
// Stationary target
Target stationary;
stationary.position = Vector3<float>{100, 100, 100};
stationary.velocity = Vector3<float>{0, 0, 0};
// aim_point will equal position for stationary targets
// Fast-moving target
Target fast;
fast.position = Vector3<float>{100, 100, 100};
fast.velocity = Vector3<float>{50, 0, 0}; // Moving very fast
// May return nullopt if target is too fast
// Target at different heights
Target aerial;
aerial.position = Vector3<float>{100, 100, 200}; // High up
aerial.velocity = Vector3<float>{5, 5, -10}; // Falling
// Gravity will be factored into the calculation
```
### Step 5: Performance Optimization
```cpp
// For better performance on modern CPUs, use AVX2:
#include <omath/projectile_prediction/proj_pred_engine_avx2.hpp>
ProjPredEngineAVX2 fast_engine; // 2-4x faster than legacy
// Use the same way as legacy engine
if (auto aim = fast_engine.maybe_calculate_aim_point(bullet, enemy)) {
// Process aim point
}
```
**Key takeaways:**
- Always check if aim point exists before using
- Velocity must be in same units as position/speed
- Gravity vector points down (typically negative Z or Y depending on engine)
- Use AVX2 engine when possible for better performance
- Returns `nullopt` when target is unreachable
---
## Tutorial 4: Collision Detection
Perform ray-casting and intersection tests.
### Step 1: Ray-Plane Intersection
```cpp
#include <omath/omath.hpp>
using namespace omath;
// Define a ground plane (Z=0, normal pointing up)
Plane ground{
Vector3<float>{0, 0, 0}, // Point on plane
Vector3<float>{0, 0, 1} // Normal vector (Z-up)
};
// Define a ray (e.g., looking downward from above)
Vector3<float> ray_origin{10, 20, 100};
Vector3<float> ray_direction{0, 0, -1}; // Pointing down
// Test intersection
if (auto hit = ground.intersects_ray(ray_origin, ray_direction)) {
std::cout << "Hit ground at: "
<< hit->x << ", " << hit->y << ", " << hit->z << "\n";
// Expected: (10, 20, 0)
} else {
std::cout << "Ray does not intersect plane\n";
}
```
### Step 2: Distance to Plane
```cpp
// Calculate signed distance from point to plane
Vector3<float> point{10, 20, 50};
float distance = ground.distance_to_point(point);
std::cout << "Distance to ground: " << distance << "\n";
// Expected: 50.0 (50 units above ground)
// Negative distance means point is below the plane
Vector3<float> below{10, 20, -5};
float dist_below = ground.distance_to_point(below);
// Expected: -5.0
```
### Step 3: Axis-Aligned Bounding Box
```cpp
#include <omath/3d_primitives/box.hpp>
// Create a bounding box
Box bbox{
Vector3<float>{0, 0, 0}, // Min corner
Vector3<float>{100, 100, 100} // Max corner
};
// Test if point is inside
Vector3<float> inside{50, 50, 50};
if (bbox.contains(inside)) {
std::cout << "Point is inside box\n";
}
Vector3<float> outside{150, 50, 50};
if (!bbox.contains(outside)) {
std::cout << "Point is outside box\n";
}
// Box-box intersection
Box other{
Vector3<float>{50, 50, 50},
Vector3<float>{150, 150, 150}
};
if (bbox.intersects(other)) {
std::cout << "Boxes overlap\n";
}
```
### Step 4: Line Tracing
```cpp
#include <omath/collision/line_tracer.hpp>
using namespace omath::collision;
// Ray-triangle intersection
Vector3<float> v0{0, 0, 0};
Vector3<float> v1{100, 0, 0};
Vector3<float> v2{0, 100, 0};
Vector3<float> ray_start{25, 25, 100};
Vector3<float> ray_dir{0, 0, -1};
LineTracer tracer;
if (auto hit = tracer.ray_triangle_intersect(ray_start, ray_dir, v0, v1, v2)) {
std::cout << "Hit triangle at: "
<< hit->point.x << ", "
<< hit->point.y << ", "
<< hit->point.z << "\n";
std::cout << "Hit distance: " << hit->distance << "\n";
std::cout << "Surface normal: "
<< hit->normal.x << ", "
<< hit->normal.y << ", "
<< hit->normal.z << "\n";
}
```
**Key takeaways:**
- Plane normals should be unit vectors
- Ray direction should typically be normalized
- Signed distance indicates which side of plane a point is on
- AABB tests are very fast for broad-phase collision detection
- Line tracer provides hit point, distance, and surface normal
---
## Tutorial 5: Pattern Scanning
Search for byte patterns in memory.
### Step 1: Basic Pattern Scanning
```cpp
#include <omath/utility/pattern_scan.hpp>
#include <vector>
using namespace omath;
// Memory to search (e.g., from a loaded module)
std::vector<uint8_t> memory = {
0x48, 0x8B, 0x05, 0xAA, 0xBB, 0xCC, 0xDD,
0x48, 0x85, 0xC0, 0x74, 0x10,
// ... more bytes
};
// Pattern with wildcards (?? = match any byte)
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
// Scan for pattern
if (auto result = pattern_scan(memory, pattern)) {
std::cout << "Pattern found at offset: " << result->offset << "\n";
// Extract wildcard values if needed
// result->wildcards contains the matched bytes at ?? positions
} else {
std::cout << "Pattern not found\n";
}
```
### Step 2: PE File Scanning
```cpp
#include <omath/utility/pe_pattern_scan.hpp>
// Scan a PE file (EXE or DLL)
PEPatternScanner scanner("game.exe");
PatternView pattern{"E8 ?? ?? ?? ?? 85 C0 75 ??"};
if (auto rva = scanner.scan_pattern(pattern)) {
std::cout << "Pattern found at RVA: 0x"
<< std::hex << *rva << std::dec << "\n";
// Convert RVA to absolute address if needed
uintptr_t base_address = get_module_base("game.exe");
uintptr_t absolute = base_address + *rva;
} else {
std::cout << "Pattern not found in PE file\n";
}
```
### Step 3: Multiple Patterns
```cpp
// Search for multiple patterns
std::vector<PatternView> patterns{
PatternView{"48 8B 05 ?? ?? ?? ??"},
PatternView{"E8 ?? ?? ?? ?? 85 C0"},
PatternView{"FF 15 ?? ?? ?? ?? 48 8B"}
};
for (size_t i = 0; i < patterns.size(); ++i) {
if (auto result = pattern_scan(memory, patterns[i])) {
std::cout << "Pattern " << i << " found at: "
<< result->offset << "\n";
}
}
```
### Step 4: Pattern with Masks
```cpp
// Alternative: use mask-based patterns
// Pattern: bytes to match
std::vector<uint8_t> pattern_bytes{0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00};
// Mask: 'x' = must match, '?' = wildcard
std::string mask{"xxx????"};
// Custom scan function
auto scan_with_mask = [&](const std::vector<uint8_t>& data) {
for (size_t i = 0; i < data.size() - pattern_bytes.size(); ++i) {
bool match = true;
for (size_t j = 0; j < pattern_bytes.size(); ++j) {
if (mask[j] == 'x' && data[i + j] != pattern_bytes[j]) {
match = false;
break;
}
}
if (match) return i;
}
return size_t(-1);
};
```
**Key takeaways:**
- Use `??` in pattern strings for wildcards
- PE scanner works with files and modules
- Pattern scanning is useful for finding functions, vtables, or data
- Always validate found addresses before use
- Patterns may have multiple matches - consider context
---
## Tutorial 6: Angles and View Angles
Work with game camera angles properly.
### Step 1: Understanding Angle Types
```cpp
#include <omath/omath.hpp>
using namespace omath;
// Generic angle with custom range
auto angle1 = Angle<float, 0.0f, 360.0f>::from_degrees(45.0f);
auto angle2 = Angle<float, -180.0f, 180.0f>::from_degrees(270.0f);
// Specialized camera angles
auto pitch = PitchAngle::from_degrees(-10.0f); // Looking down
auto yaw = YawAngle::from_degrees(90.0f); // Looking right
auto roll = RollAngle::from_degrees(0.0f); // No tilt
```
### Step 2: Angle Conversions
```cpp
// Create from degrees
auto deg_angle = PitchAngle::from_degrees(45.0f);
// Get as radians
float radians = deg_angle.as_radians();
std::cout << "45° = " << radians << " radians\n";
// Get as degrees
float degrees = deg_angle.as_degrees();
std::cout << "Value: " << degrees << "°\n";
```
### Step 3: View Angles (Camera)
```cpp
// Pitch: vertical rotation (-89° to 89°)
// Yaw: horizontal rotation (-180° to 180°)
// Roll: camera tilt (-180° to 180°)
ViewAngles camera_angles{
PitchAngle::from_degrees(-15.0f), // Looking slightly down
YawAngle::from_degrees(45.0f), // Facing northeast
RollAngle::from_degrees(0.0f) // No tilt
};
// Access individual components
float pitch_val = camera_angles.pitch.as_degrees();
float yaw_val = camera_angles.yaw.as_degrees();
float roll_val = camera_angles.roll.as_degrees();
```
### Step 4: Calculating Look-At Angles
```cpp
using namespace omath::source_engine; // Or your game's engine
Vector3<float> camera_pos{0, 0, 100};
Vector3<float> target_pos{100, 100, 100};
// Calculate angles to look at target
ViewAngles look_at = CameraTrait::calc_look_at_angle(camera_pos, target_pos);
std::cout << "Pitch: " << look_at.pitch.as_degrees() << "°\n";
std::cout << "Yaw: " << look_at.yaw.as_degrees() << "°\n";
std::cout << "Roll: " << look_at.roll.as_degrees() << "°\n";
```
### Step 5: Angle Arithmetic
```cpp
// Angles support arithmetic with automatic normalization
auto angle1 = YawAngle::from_degrees(170.0f);
auto angle2 = YawAngle::from_degrees(20.0f);
// Addition (wraps around)
auto sum = angle1 + angle2; // 190° → normalized to -170°
// Subtraction
auto diff = angle2 - angle1; // -150°
// Scaling
auto scaled = angle1 * 2.0f;
```
**Key takeaways:**
- Use specialized angle types for camera angles (PitchAngle, YawAngle, RollAngle)
- Angles automatically normalize to their valid ranges
- Each game engine may have different angle conventions
- Use engine traits to calculate look-at angles correctly
---
## Next Steps
Now that you've completed these tutorials, explore:
- **[API Overview](api_overview.md)** - Complete API reference
- **[Engine Documentation](engines/)** - Engine-specific features
- **[Examples](../examples/)** - More code examples
- **[Getting Started](getting_started.md)** - Quick start guide
---
*Last updated: 1 Nov 2025*