Conversation
There was a problem hiding this comment.
Pull request overview
Adds configurable NDC depth range support ([-1, 1] vs [0, 1]) across matrix constructors, the generic projection::Camera, and all engine camera traits, with expanded unit tests to validate Z mapping for both conventions.
Changes:
- Introduce
NDCDepthRangeand extend perspective/ortho matrix builders to support[0, 1]depth. - Propagate the depth-range choice through
projection::Camera(template parameter) and engineCameraTrait/calc_perspective_projection_matrixAPIs. - Add/extend unit tests to validate near/far/mid Z mapping for both depth conventions across engines.
Reviewed changes
Copilot reviewed 39 out of 39 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/general/unit_test_mat.cpp | Adds unit tests covering [0,1] and [-1,1] Z mapping for perspective/ortho matrices. |
| tests/engines/unit_test_traits_engines.cpp | Extends trait tests to validate both depth ranges across engines and verifies Z mapping behavior. |
| source/engines/unreal_engine/traits/camera_trait.cpp | Threads NDCDepthRange through Unreal camera trait projection computation. |
| source/engines/unreal_engine/formulas.cpp | Adds [0,1]-depth option to Unreal projection matrix formula. |
| source/engines/unity_engine/traits/camera_trait.cpp | Threads NDCDepthRange through Unity camera trait projection computation. |
| source/engines/unity_engine/formulas.cpp | Adds [0,1]-depth option to Unity projection matrix formula. |
| source/engines/source_engine/traits/camera_trait.cpp | Threads NDCDepthRange through Source camera trait projection computation. |
| source/engines/source_engine/formulas.cpp | Adds [0,1]-depth option to Source projection matrix formula. |
| source/engines/opengl_engine/traits/camera_trait.cpp | Threads NDCDepthRange through OpenGL camera trait projection computation. |
| source/engines/opengl_engine/formulas.cpp | Adds [0,1]-depth option to OpenGL projection matrix formula. |
| source/engines/iw_engine/traits/camera_trait.cpp | Threads NDCDepthRange through IW camera trait projection computation. |
| source/engines/iw_engine/formulas.cpp | Adds [0,1]-depth option to IW projection matrix formula. |
| source/engines/frostbite_engine/traits/camera_trait.cpp | Threads NDCDepthRange through Frostbite camera trait projection computation. |
| source/engines/frostbite_engine/formulas.cpp | Adds [0,1]-depth option to Frostbite projection matrix formula. |
| source/engines/cry_engine/traits/camera_trait.cpp | Threads NDCDepthRange through CryEngine camera trait projection computation. |
| source/engines/cry_engine/formulas.cpp | Adds [0,1]-depth option to CryEngine projection matrix formula. |
| include/omath/projection/camera.hpp | Adds depth-range template param; updates clipping/frustum checks to respect Z convention. |
| include/omath/linear_algebra/mat.hpp | Introduces NDCDepthRange; updates mat perspective/ortho builders for depth-range selection. |
| include/omath/engines/unreal_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/unreal_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/unreal_engine/camera.hpp | Sets Unreal Camera alias to use [0,1] depth by default. |
| include/omath/engines/unity_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/unity_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/unity_engine/camera.hpp | Sets Unity Camera alias to use [0,1] depth by default. |
| include/omath/engines/source_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/source_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/source_engine/camera.hpp | Sets Source Camera alias to use [0,1] depth by default. |
| include/omath/engines/opengl_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/opengl_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/opengl_engine/camera.hpp | Keeps OpenGL Camera alias at [-1,1] depth explicitly. |
| include/omath/engines/iw_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/iw_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/iw_engine/camera.hpp | Sets IW Camera alias to use [0,1] depth by default. |
| include/omath/engines/frostbite_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/frostbite_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/frostbite_engine/camera.hpp | Sets Frostbite Camera alias to use [0,1] depth by default. |
| include/omath/engines/cry_engine/traits/camera_trait.hpp | Updates trait signature to accept NDCDepthRange. |
| include/omath/engines/cry_engine/formulas.hpp | Updates projection formula signature to accept NDCDepthRange with a default. |
| include/omath/engines/cry_engine/camera.hpp | Sets CryEngine Camera alias to use [0,1] depth by default. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far, | ||
| ndc_depth_range); | ||
| } | ||
| } // namespace omath::unity_engine No newline at end of file |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unity_engine but the file namespace is omath::cry_engine). Update the comment to match the actual namespace to avoid confusion during maintenance/searching.
| } // namespace omath::unity_engine | |
| } // namespace omath::cry_engine |
|
|
||
| return mat_perspective_left_handed(field_of_view, aspect_ratio, near, far); | ||
| } | ||
| } // namespace omath::unity_engine |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unity_engine but the file namespace is omath::frostbite_engine). Please update it so it matches the actual namespace.
| } // namespace omath::unity_engine | |
| } // namespace omath::frostbite_engine |
| float near, float far, NDCDepthRange ndc_depth_range) noexcept; | ||
| }; | ||
|
|
||
| } // namespace omath::unreal_engine No newline at end of file |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unreal_engine but the header declares namespace omath::frostbite_engine). Please update the comment to match the actual namespace.
| } // namespace omath::unreal_engine | |
| } // namespace omath::frostbite_engine |
| namespace omath::unreal_engine | ||
| { | ||
| using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>; | ||
| using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>; |
There was a problem hiding this comment.
This changes the default NDC depth convention for omath::unreal_engine::Camera to ZERO_TO_ONE. Since this is a public alias, it’s a behavioral/API change for any existing users relying on the previous default depth range; if both conventions are supported now, consider providing separate aliases (e.g. CameraZO/CameraNO) or documenting the change prominently.
| using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>; | |
| // Unreal Engine uses a [0, 1] depth range in NDC. Provide explicit camera aliases | |
| // for both supported conventions to avoid ambiguity: | |
| // | |
| // - CameraZO : NDCDepthRange::ZERO_TO_ONE (Unreal-style depth range) | |
| // - CameraNO : NDCDepthRange::NEGATIVE_ONE_TO_ONE (OpenGL-style depth range) | |
| // | |
| // NOTE: The generic `Camera` alias below currently maps to `CameraZO`, i.e. it uses | |
| // NDCDepthRange::ZERO_TO_ONE. In earlier versions, `Camera` used a different default | |
| // depth range (typically NEGATIVE_ONE_TO_ONE). Prefer using `CameraZO` or `CameraNO` | |
| // explicitly if your code depends on a particular NDC depth convention. | |
| using CameraZO = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>; | |
| using CameraNO = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::NEGATIVE_ONE_TO_ONE>; | |
| // Backward-compatible alias: keep `Camera` pointing to the ZERO_TO_ONE variant. | |
| using Camera = CameraZO; |
| return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far, | ||
| ndc_depth_range); | ||
| } | ||
| } // namespace omath::unity_engine No newline at end of file |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unity_engine but the file namespace is omath::frostbite_engine). Update the comment to match the actual namespace to avoid confusion during maintenance/searching.
| } // namespace omath::unity_engine | |
| } // namespace omath::frostbite_engine |
|
|
||
| return mat_perspective_left_handed(field_of_view, aspect_ratio, near, far); | ||
| } | ||
| } // namespace omath::unity_engine |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unity_engine but the file namespace is omath::cry_engine). Please update it so it matches the actual namespace.
| } // namespace omath::unity_engine | |
| } // namespace omath::cry_engine |
| { | ||
| using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>; | ||
| using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>; | ||
| } // namespace omath::unity_engine No newline at end of file |
There was a problem hiding this comment.
The closing namespace comment is incorrect (it says omath::unity_engine but the header declares namespace omath::frostbite_engine). Please update the comment to match the actual namespace.
| } // namespace omath::unity_engine | |
| } // namespace omath::frostbite_engine |
| EXPECT_NEAR(far_pt.at(2, 0), 1.0f, 1e-3f); | ||
| } | ||
|
|
||
| TEST(UnitTestMatStandalone, MatPerspectiveZeroToOneEquanity) |
There was a problem hiding this comment.
Typo in the test name: "Equanity" should be "Equality" (this affects test discovery/filtering readability).
| template<class T, class MatType, class ViewAnglesType> | ||
| concept CameraEngineConcept = | ||
| requires(const Vector3<float>& cam_origin, const Vector3<float>& look_at, const ViewAnglesType& angles, | ||
| const FieldOfView& fov, const ViewPort& viewport, float znear, float zfar) { | ||
| const FieldOfView& fov, const ViewPort& viewport, float znear, float zfar, | ||
| NDCDepthRange ndc_depth_range) { | ||
| // Presence + return types | ||
| { T::calc_look_at_angle(cam_origin, look_at) } -> std::same_as<ViewAnglesType>; | ||
| { T::calc_view_matrix(angles, cam_origin) } -> std::same_as<MatType>; | ||
| { T::calc_projection_matrix(fov, viewport, znear, zfar) } -> std::same_as<MatType>; | ||
| { T::calc_projection_matrix(fov, viewport, znear, zfar, ndc_depth_range) } -> std::same_as<MatType>; | ||
|
|
||
| // Enforce noexcept as in the trait declaration | ||
| requires noexcept(T::calc_look_at_angle(cam_origin, look_at)); | ||
| requires noexcept(T::calc_view_matrix(angles, cam_origin)); | ||
| requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar)); | ||
| requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar, ndc_depth_range)); |
There was a problem hiding this comment.
Requiring ndc_depth_range in the concept forces all CameraTrait::calc_projection_matrix call sites (including user code) to add an extra argument. If backward compatibility is a goal, consider giving ndc_depth_range a default value (e.g. NEGATIVE_ONE_TO_ONE) in the trait declarations so existing 4-arg calls still compile while Camera can continue passing depth_range explicitly.
No description provided.