mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-12 22:53:27 +00:00
Merge pull request #98 from orange-cpp/copilot/sub-pr-96
Comprehensive documentation overhaul with guides, tutorials, and cross-references
This commit is contained in:
69
README.md
69
README.md
@@ -43,18 +43,45 @@ It provides the latest features, is highly customizable, has all for cheat devel
|
||||
</a>
|
||||
</div>
|
||||
|
||||
# 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.
|
||||
- **Projectile Prediction**: Projectile prediction engine with O(N) algo complexity, that can power you projectile aim-bot.
|
||||
- **3D Projection**: No need to find view-projection matrix anymore you can make your own projection pipeline.
|
||||
- **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 and canonical OpenGL**.
|
||||
- **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.
|
||||
## 🚀 Quick Example
|
||||
|
||||
```cpp
|
||||
#include <omath/omath.hpp>
|
||||
|
||||
using namespace omath;
|
||||
|
||||
// 3D vector operations
|
||||
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
|
||||
auto normalized = a.normalized(); // Unit vector
|
||||
|
||||
// World-to-screen projection (Source Engine example)
|
||||
using namespace omath::source_engine;
|
||||
Camera camera(position, angles, viewport, fov, near_plane, far_plane);
|
||||
|
||||
if (auto screen = camera.world_to_screen(world_position)) {
|
||||
// Draw at screen->x, screen->y
|
||||
}
|
||||
```
|
||||
|
||||
**[➡️ See more examples and tutorials][TUTORIALS]**
|
||||
|
||||
# ✨ 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.
|
||||
- **🎮 Projectile Prediction**: Projectile prediction engine with O(N) algo complexity, that can power you projectile aim-bot.
|
||||
- **📐 3D Projection**: No need to find view-projection matrix anymore you can make your own projection pipeline.
|
||||
- **💥 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 and canonical OpenGL**.
|
||||
- **🌍 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.
|
||||
<div align = center>
|
||||
|
||||
# Gallery
|
||||
@@ -84,6 +111,22 @@ It provides the latest features, is highly customizable, has all for cheat devel
|
||||
|
||||
</div>
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- **[Getting Started Guide](https://libomath.org/getting_started/)** - Installation and first steps
|
||||
- **[API Overview](https://libomath.org/api_overview/)** - Complete API reference
|
||||
- **[Tutorials](https://libomath.org/tutorials/)** - Step-by-step guides
|
||||
- **[FAQ](https://libomath.org/faq/)** - Common questions and answers
|
||||
- **[Troubleshooting](https://libomath.org/troubleshooting/)** - Solutions to common issues
|
||||
- **[Best Practices](https://libomath.org/best_practices/)** - Guidelines for effective usage
|
||||
|
||||
## 🤝 Community & Support
|
||||
|
||||
- **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**: See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
|
||||
|
||||
# 💘 Acknowledgments
|
||||
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
|
||||
|
||||
@@ -93,8 +136,10 @@ It provides the latest features, is highly customizable, has all for cheat devel
|
||||
[CS2 Preview]: docs/images/showcase/cs2.jpeg
|
||||
[TF2 Preview]: docs/images/showcase/tf2.jpg
|
||||
<!----------------------------------{ Buttons }--------------------------------->
|
||||
[QUICKSTART]: docs/getting_started.md
|
||||
[INSTALL]: INSTALL.md
|
||||
[DOCUMENTATION]: http://libomath.org
|
||||
[TUTORIALS]: docs/tutorials.md
|
||||
[CONTRIBUTING]: CONTRIBUTING.md
|
||||
[EXAMPLES]: examples
|
||||
[SPONSOR]: https://boosty.to/orangecpp/purchase/3568644?ssource=DIRECT&share=subscription_link
|
||||
|
||||
527
docs/api_overview.md
Normal file
527
docs/api_overview.md
Normal 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
532
docs/best_practices.md
Normal 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*
|
||||
@@ -168,4 +168,14 @@ public:
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 31 Oct 2025*
|
||||
## See Also
|
||||
|
||||
- [Plane Documentation](../3d_primitives/plane.md) - Ray-plane intersection
|
||||
- [Box Documentation](../3d_primitives/box.md) - AABB collision detection
|
||||
- [Triangle Documentation](../linear_algebra/triangle.md) - Triangle primitives
|
||||
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Complete collision tutorial
|
||||
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 1 Nov 2025*
|
||||
|
||||
@@ -105,5 +105,9 @@ This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at,
|
||||
|
||||
## See also
|
||||
|
||||
* Source Engine math helpers in `omath/engines/source_engine/formulas.hpp` (view/projection builders used above).
|
||||
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||
* [Source Engine Formulas](formulas.md) - View/projection matrix builders
|
||||
* [Source Engine Constants](constants.md) - Engine-specific constants
|
||||
* [Source Engine Pred Engine Trait](pred_engine_trait.md) - Projectile prediction for Source Engine
|
||||
* [Generic Camera Documentation](../../projection/camera.md) - Camera base class
|
||||
* [Getting Started Guide](../../getting_started.md) - Quick start with OMath
|
||||
* [Tutorials - World-to-Screen](../../tutorials.md#tutorial-2-world-to-screen-projection) - Projection tutorial
|
||||
|
||||
406
docs/faq.md
Normal file
406
docs/faq.md
Normal 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
306
docs/getting_started.md
Normal 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*
|
||||
168
docs/index.md
168
docs/index.md
@@ -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
|
||||
|
||||
@@ -288,4 +288,13 @@ static Vector2 from_im_vec2(const ImVec2&) noexcept;
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 31 Oct 2025*
|
||||
## See Also
|
||||
|
||||
- [Vector3 Documentation](vector3.md) - 3D vector operations
|
||||
- [Vector4 Documentation](vector4.md) - 4D vector operations
|
||||
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||
- [Tutorials](../tutorials.md) - Step-by-step examples
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 1 Nov 2025*
|
||||
|
||||
@@ -294,4 +294,14 @@ bool is_perpendicular(const Vector3&) const noexcept;
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 31 Oct 2025*
|
||||
## See Also
|
||||
|
||||
- [Vector2 Documentation](vector2.md) - 2D vector operations
|
||||
- [Vector4 Documentation](vector4.md) - 4D vector operations
|
||||
- [Angle Documentation](../trigonometry/angle.md) - Working with angles
|
||||
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||
- [Tutorials](../tutorials.md) - Practical examples including vector math
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 1 Nov 2025*
|
||||
|
||||
@@ -149,4 +149,14 @@ Return `nullopt` if `t*` is absent.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Projectile Documentation](projectile.md) - Projectile properties
|
||||
- [Target Documentation](target.md) - Target state representation
|
||||
- [Legacy Implementation](proj_pred_engine_legacy.md) - Standard projectile prediction engine
|
||||
- [AVX2 Implementation](proj_pred_engine_avx2.md) - Optimized AVX2 engine
|
||||
- [Tutorials - Projectile Prediction](../tutorials.md#tutorial-3-projectile-prediction-aim-bot) - Complete aim-bot tutorial
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 1 Nov 2025*
|
||||
|
||||
@@ -258,4 +258,13 @@ struct LHCTrait {
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Engine-Specific Camera Traits](../engines/) - Camera implementations for different game engines
|
||||
- [View Angles Documentation](../trigonometry/view_angles.md) - Understanding pitch/yaw/roll
|
||||
- [Getting Started Guide](../getting_started.md) - Quick start with projection
|
||||
- [Tutorials - World-to-Screen](../tutorials.md#tutorial-2-world-to-screen-projection) - Complete projection tutorial
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 1 Nov 2025*
|
||||
|
||||
525
docs/troubleshooting.md
Normal file
525
docs/troubleshooting.md
Normal 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
616
docs/tutorials.md
Normal 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*
|
||||
Reference in New Issue
Block a user