# `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& cam_origin, const Vector3& look_at) noexcept; // Build view matrix for given angles and origin. static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3& 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`, `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; 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 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).