Skip to content

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

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:

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