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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions docs/engines/iw_engine/camera_trait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# `omath::iw_engine::CameraTrait` — plug-in trait for `projection::Camera`

> Header: `omath/engines/iw_engine/traits/camera_trait.hpp` • Impl: `omath/engines/iw_engine/traits/camera_trait.cpp`
> Namespace: `omath::iw_engine`
> Purpose: provide IW Engine (Call of Duty)-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).

---

## Summary

`CameraTrait` exposes three `static` functions:

* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.z)` and **yaw** as `atan2(dir.y, dir.x)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
* `calc_view_matrix(angles, origin)` – delegates to IW Engine formulas `iw_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).

The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the IW Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).

---

## API

```cpp
namespace omath::iw_engine {

class CameraTrait final {
public:
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
static ViewAngles
calc_look_at_angle(const Vector3<float>& cam_origin,
const Vector3<float>& look_at) noexcept;

// Build view matrix for given angles and origin.
static Mat4X4
calc_view_matrix(const ViewAngles& angles,
const Vector3<float>& cam_origin) noexcept;

// Build perspective projection from FOV (deg), viewport, near/far.
static Mat4X4
calc_projection_matrix(const projection::FieldOfView& fov,
const projection::ViewPort& view_port,
float near, float far) noexcept;
};

} // namespace omath::iw_engine
```

Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.

---

## Behavior & conventions

* **Angles from look-at** (Z-up coordinate system):

```
dir = normalize(look_at - origin)
pitch = asin(dir.z) // +Z is up
yaw = atan2(dir.y, dir.x) // horizontal rotation
roll = 0
```

Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.

* **View matrix**: built by the IW Engine helper `iw_engine::calc_view_matrix(angles, origin)` to match the engine's handedness and axis conventions.

* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.

---

## Using with `projection::Camera`

Create a camera whose math is driven by this trait:

```cpp
using Mat4 = Mat4X4; // from IW Engine math headers
using Angs = ViewAngles; // pitch/yaw/roll type
using IWcam = omath::projection::Camera<Mat4, Angs, omath::iw_engine::CameraTrait>;

omath::projection::ViewPort vp{1920.f, 1080.f};
auto fov = omath::projection::FieldOfView::from_degrees(65.f);

IWcam cam(
/*position*/ {500.f, 200.f, 100.f},
/*angles*/ omath::iw_engine::CameraTrait::calc_look_at_angle({500,200,100},{0,0,100}),
/*viewport*/ vp,
/*fov*/ fov,
/*near*/ 0.1f,
/*far*/ 5000.f
);
```

This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.

---

## Notes & tips

* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
* IW Engine uses **Z-up**: pitch angles control vertical look, positive = up.

---

## See also

* IW Engine math helpers in `omath/engines/iw_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).
77 changes: 77 additions & 0 deletions docs/engines/iw_engine/constants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# `omath::iw_engine` — types & constants

> Header: `omath/engines/iw_engine/constants.hpp`
> Namespace: `omath::iw_engine`
> Purpose: define IW Engine (Call of Duty) coordinate system, matrix types, and angle ranges

---

## Summary

The **IW Engine** (Infinity Ward Engine, used in Call of Duty series) uses a **Z-up, right-handed** coordinate system:

* **Up** = `{0, 0, 1}` (Z-axis)
* **Right** = `{0, -1, 0}` (negative Y-axis)
* **Forward** = `{1, 0, 0}` (X-axis)

Matrices are **row-major**. Angles are **clamped pitch** (±89°) and **normalized yaw/roll** (±180°).

---

## Constants

```cpp
namespace omath::iw_engine {
constexpr Vector3<float> k_abs_up = {0, 0, 1};
constexpr Vector3<float> k_abs_right = {0, -1, 0};
constexpr Vector3<float> k_abs_forward = {1, 0, 0};
}
```

These basis vectors define the engine's **world coordinate frame**.

---

## Matrix types

```cpp
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
```

**Row-major** storage means rows are contiguous in memory. Suitable for CPU-side transforms and typical C++ math libraries.

---

## Angle types

```cpp
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;

using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
```

* **PitchAngle**: clamped to **[-89°, +89°]** (looking down vs. up)
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)

`ViewAngles` bundles all three into a single type for camera/view transforms.

---

## Coordinate system notes

* **Z-up**: gravity points along `-Z`, height increases with `+Z`
* **Right-handed**: cross product `forward × right = up` holds
* This matches **IW Engine** (Call of Duty series: Modern Warfare, Black Ops, etc.) conventions

---

## See also

* `omath/engines/iw_engine/formulas.hpp` — view/projection matrix builders
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
135 changes: 135 additions & 0 deletions docs/engines/iw_engine/formulas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# `omath::iw_engine` — formulas & matrix helpers

> Header: `omath/engines/iw_engine/formulas.hpp`
> Namespace: `omath::iw_engine`
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for IW Engine (Call of Duty)

---

## Summary

This header provides **IW Engine**-specific math for:

* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
* **Rotation matrices** from Euler angles
* **View matrices** (camera transforms)
* **Perspective projection** matrices

All functions respect IW Engine's **Z-up, right-handed** coordinate system.

---

## API

```cpp
namespace omath::iw_engine {

// Compute forward direction from pitch/yaw/roll
[[nodiscard]]
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;

// Compute right direction from pitch/yaw/roll
[[nodiscard]]
Vector3<float> right_vector(const ViewAngles& angles) noexcept;

// Compute up direction from pitch/yaw/roll
[[nodiscard]]
Vector3<float> up_vector(const ViewAngles& angles) noexcept;

// Build 3x3 rotation matrix from angles
[[nodiscard]]
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;

// Build view matrix (camera space transform)
[[nodiscard]]
Mat4X4 calc_view_matrix(const ViewAngles& angles,
const Vector3<float>& cam_origin) noexcept;

// Build perspective projection matrix
[[nodiscard]]
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
float aspect_ratio,
float near, float far) noexcept;

} // namespace omath::iw_engine
```

---

## Direction vectors

Given camera angles (pitch/yaw/roll):

* `forward_vector(angles)` → unit vector pointing where the camera looks
* `right_vector(angles)` → unit vector pointing to the camera's right
* `up_vector(angles)` → unit vector pointing upward relative to the camera

These are used for movement, aim direction, and building coordinate frames.

---

## Rotation & view matrices

* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles
* `calc_view_matrix(angles, origin)` → camera view matrix

The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).

---

## Perspective projection

```cpp
Mat4X4 proj = calc_perspective_projection_matrix(
fov_degrees, // vertical field of view (e.g., 65)
aspect_ratio, // width / height (e.g., 16/9)
near_plane, // e.g., 0.1
far_plane // e.g., 5000.0
);
```

Produces a **perspective projection matrix** suitable for 3D rendering pipelines. Combined with the view matrix, this implements the standard camera transform chain.

---

## Usage example

```cpp
using namespace omath::iw_engine;

// Camera setup
ViewAngles angles = {
PitchAngle::from_degrees(-10.0f),
YawAngle::from_degrees(90.0f),
RollAngle::from_degrees(0.0f)
};
Vector3<float> cam_pos{500.0f, 200.0f, 100.0f};

// Compute direction
auto forward = forward_vector(angles);
auto right = right_vector(angles);
auto up = up_vector(angles);

// Build matrices
auto view_mat = calc_view_matrix(angles, cam_pos);
auto proj_mat = calc_perspective_projection_matrix(65.0f, 16.0f/9.0f, 0.1f, 5000.0f);

// Use view_mat and proj_mat for rendering...
```

---

## Conventions

* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
* **Pitch**: positive = looking up, negative = looking down
* **Yaw**: increases counter-clockwise from the +X axis
* **Coordinate system**: Z-up, X-forward, Y-right (negative in code convention)

---

## See also

* `omath/engines/iw_engine/constants.hpp` — coordinate frame & angle types
* `omath/engines/iw_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
Loading