mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 15:03:27 +00:00
114 lines
4.8 KiB
Markdown
114 lines
4.8 KiB
Markdown
# `omath::source_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||
|
||
> Header: `omath/engines/source_engine/traits/camera_trait.hpp` • Impl: `omath/engines/source_engine/traits/camera_trait.cpp`
|
||
> Namespace: `omath::source_engine`
|
||
> Purpose: provide Source Engine-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 Source Engine formulas `source_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 Source Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||
|
||
---
|
||
|
||
## API
|
||
|
||
```cpp
|
||
namespace omath::source_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::source_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 Source Engine helper `source_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 Source Engine math headers
|
||
using Angs = ViewAngles; // pitch/yaw/roll type
|
||
using SEcam = omath::projection::Camera<Mat4, Angs, omath::source_engine::CameraTrait>;
|
||
|
||
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||
auto fov = omath::projection::FieldOfView::from_degrees(90.f);
|
||
|
||
SEcam cam(
|
||
/*position*/ {100.f, 50.f, 80.f},
|
||
/*angles*/ omath::source_engine::CameraTrait::calc_look_at_angle({100,50,80},{0,0,80}),
|
||
/*viewport*/ vp,
|
||
/*fov*/ fov,
|
||
/*near*/ 0.1f,
|
||
/*far*/ 1000.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).
|
||
* Source Engine uses **Z-up**: pitch angles control vertical look, positive = up.
|
||
|
||
---
|
||
|
||
## See also
|
||
|
||
* [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
|