@@ -54,6 +54,12 @@ namespace omath::projection
5454 friend UnitTestProjection_Projection_Test;
5555#endif
5656 public:
57+ enum class ScreenStart
58+ {
59+ TOP_LEFT_CORNER,
60+ BOTTOM_LEFT_CORNER,
61+ };
62+
5763 ~Camera () = default ;
5864 Camera (const Vector3<float >& position, const ViewAnglesType& view_angles, const ViewPort& view_port,
5965 const FieldOfView& fov, const float near, const float far) noexcept
@@ -146,15 +152,22 @@ namespace omath::projection
146152 return m_origin;
147153 }
148154
155+
156+ template <ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER>
149157 [[nodiscard]] std::expected<Vector3<float >, Error>
150158 world_to_screen (const Vector3<float >& world_position) const noexcept
151159 {
152- auto normalized_cords = world_to_view_port (world_position);
160+ const auto normalized_cords = world_to_view_port (world_position);
153161
154162 if (!normalized_cords.has_value ())
155163 return std::unexpected{normalized_cords.error ()};
156164
157- return ndc_to_screen_position (*normalized_cords);
165+ if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER)
166+ return ndc_to_screen_position_from_top_left_corner (*normalized_cords);
167+ else if constexpr (screen_start == ScreenStart::BOTTOM_LEFT_CORNER)
168+ return ndc_to_screen_position_from_bottom_left_corner (*normalized_cords);
169+ else
170+ std::unreachable ();
158171 }
159172
160173 [[nodiscard]] std::expected<Vector3<float >, Error>
@@ -225,7 +238,27 @@ namespace omath::projection
225238 return std::ranges::any_of (ndc.raw_array (), [](const auto & val) { return val < -1 || val > 1 ; });
226239 }
227240
228- [[nodiscard]] Vector3<float > ndc_to_screen_position (const Vector3<float >& ndc) const noexcept
241+ [[nodiscard]] Vector3<float >
242+ ndc_to_screen_position_from_top_left_corner (const Vector3<float >& ndc) const noexcept
243+ {
244+ /*
245+ ^
246+ | y
247+ 1 |
248+ |
249+ |
250+ -1 ---------0--------- 1 --> x
251+ |
252+ |
253+ -1 |
254+ v
255+ */
256+
257+ return {(ndc.x + 1 .f ) / 2 .f * m_view_port.m_width , (ndc.y / -2 .f + 0 .5f ) * m_view_port.m_height , ndc.z };
258+ }
259+
260+ [[nodiscard]] Vector3<float >
261+ ndc_to_screen_position_from_bottom_left_corner (const Vector3<float >& ndc) const noexcept
229262 {
230263 /*
231264 ^
@@ -239,7 +272,8 @@ namespace omath::projection
239272 -1 |
240273 v
241274 */
242- return {(ndc.x + 1 .f ) / 2 .f * m_view_port.m_width , (1 .f - ndc.y ) / 2 .f * m_view_port.m_height , ndc.z };
275+
276+ return {(ndc.x + 1 .f ) / 2 .f * m_view_port.m_width , (ndc.y / 2 .f + 0 .5f ) * m_view_port.m_height , ndc.z };
243277 }
244278
245279 [[nodiscard]] Vector3<float > screen_to_ndc (const Vector3<float >& screen_pos) const noexcept
0 commit comments