added types impl

This commit is contained in:
2026-04-25 05:29:21 +03:00
parent 13c7f7eb5a
commit 92582079c5

View File

@@ -51,17 +51,17 @@ namespace omath::projection
template<class T, class MatType, class ViewAnglesType, class NumericType> template<class T, class MatType, class ViewAnglesType, class NumericType>
concept CameraEngineConcept = concept CameraEngineConcept =
requires(const Vector3<NumericType>& cam_origin, const Vector3<NumericType>& look_at, requires(const Vector3<NumericType>& cam_origin, const Vector3<NumericType>& look_at,
const ViewAnglesType& angles, const FieldOfView& fov, const ViewPort& viewport, const ViewAnglesType& angles, const FieldOfView& fov, const ViewPort& viewport, NumericType z_near,
NumericType znear, NumericType zfar, NDCDepthRange ndc_depth_range) { NumericType z_far, NDCDepthRange ndc_depth_range) {
// Presence + return types // Presence + return types
{ T::calc_look_at_angle(cam_origin, look_at) } -> std::same_as<ViewAnglesType>; { 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_view_matrix(angles, cam_origin) } -> std::same_as<MatType>;
{ T::calc_projection_matrix(fov, viewport, znear, zfar, ndc_depth_range) } -> std::same_as<MatType>; { T::calc_projection_matrix(fov, viewport, z_near, z_far, ndc_depth_range) } -> std::same_as<MatType>;
requires std::is_floating_point_v<NumericType>; requires std::is_floating_point_v<NumericType>;
// Enforce noexcept as in the trait declaration // Enforce noexcept as in the trait declaration
requires noexcept(T::calc_look_at_angle(cam_origin, look_at)); requires noexcept(T::calc_look_at_angle(cam_origin, look_at));
requires noexcept(T::calc_view_matrix(angles, cam_origin)); requires noexcept(T::calc_view_matrix(angles, cam_origin));
requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar, ndc_depth_range)); requires noexcept(T::calc_projection_matrix(fov, viewport, z_near, z_far, ndc_depth_range));
}; };
template<class Mat4X4Type, class ViewAnglesType, class TraitClass, template<class Mat4X4Type, class ViewAnglesType, class TraitClass,
@@ -93,7 +93,7 @@ namespace omath::projection
struct ProjectionParams final struct ProjectionParams final
{ {
FieldOfView fov; FieldOfView fov;
float aspect_ratio{}; NumericType aspect_ratio{};
}; };
// Recovers vertical FOV and aspect ratio from a perspective projection matrix // Recovers vertical FOV and aspect ratio from a perspective projection matrix
@@ -106,7 +106,8 @@ namespace omath::projection
// m[1,1] == 1 / tan(fov/2) => fov = 2 * atan(1 / m[1,1]) // m[1,1] == 1 / tan(fov/2) => fov = 2 * atan(1 / m[1,1])
const auto f = proj_matrix.at(1, 1); const auto f = proj_matrix.at(1, 1);
// m[0,0] == m[1,1] / aspect_ratio => aspect = m[1,1] / m[0,0] // m[0,0] == m[1,1] / aspect_ratio => aspect = m[1,1] / m[0,0]
return {FieldOfView::from_radians(2.f * std::atan(1.f / f)), f / proj_matrix.at(0, 0)}; return {FieldOfView::from_radians(NumericType{2} * std::atan(NumericType{1} / f)),
f / proj_matrix.at(0, 0)};
} }
[[nodiscard]] [[nodiscard]]
@@ -423,11 +424,11 @@ namespace omath::projection
// (the "positive vertex"). If it's outside, the entire AABB is outside. // (the "positive vertex"). If it's outside, the entire AABB is outside.
for (const auto& [a, b, c, d] : planes) for (const auto& [a, b, c, d] : planes)
{ {
const auto px = a >= 0.f ? aabb.max.x : aabb.min.x; const auto px = a >= NumericType{0} ? aabb.max.x : aabb.min.x;
const auto py = b >= 0.f ? aabb.max.y : aabb.min.y; const auto py = b >= NumericType{0} ? aabb.max.y : aabb.min.y;
const auto pz = c >= 0.f ? aabb.max.z : aabb.min.z; const auto pz = c >= NumericType{0} ? aabb.max.z : aabb.min.z;
if (a * px + b * py + c * pz + d < 0.f) if (a * px + b * py + c * pz + d < NumericType{0})
return true; return true;
} }
@@ -454,9 +455,10 @@ namespace omath::projection
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
// ReSharper disable once CppTooWideScope // ReSharper disable once CppTooWideScope
constexpr auto z_min = depth_range == NDCDepthRange::ZERO_TO_ONE ? 0.0f : -1.0f; constexpr auto z_min = depth_range == NDCDepthRange::ZERO_TO_ONE ? NumericType{0} : -NumericType{1};
const auto clipped_manually = clipping == ViewPortClipping::MANUAL const auto clipped_manually =
&& (projected.at(2, 0) < z_min - eps || projected.at(2, 0) > 1.0f + eps); clipping == ViewPortClipping::MANUAL
&& (projected.at(2, 0) < z_min - eps || projected.at(2, 0) > NumericType{1} + eps);
if (clipped_manually) if (clipped_manually)
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
@@ -522,9 +524,9 @@ namespace omath::projection
const auto& data = ndc.raw_array(); const auto& data = ndc.raw_array();
// x and y are always in [-1, 1] // x and y are always in [-1, 1]
if (data[0] < -1.0f - eps || data[0] > 1.0f + eps) if (data[0] < -NumericType{1} - eps || data[0] > NumericType{1} + eps)
return true; return true;
if (data[1] < -1.0f - eps || data[1] > 1.0f + eps) if (data[1] < -NumericType{1} - eps || data[1] > NumericType{1} + eps)
return true; return true;
return is_ndc_z_value_out_of_bounds(data[2]); return is_ndc_z_value_out_of_bounds(data[2]);
} }
@@ -534,9 +536,9 @@ namespace omath::projection
{ {
constexpr auto eps = std::numeric_limits<NumericType>::epsilon(); constexpr auto eps = std::numeric_limits<NumericType>::epsilon();
if constexpr (depth_range == NDCDepthRange::NEGATIVE_ONE_TO_ONE) if constexpr (depth_range == NDCDepthRange::NEGATIVE_ONE_TO_ONE)
return z_ndc < -1.0f - eps || z_ndc > 1.0f + eps; return z_ndc < -NumericType{1} - eps || z_ndc > NumericType{1} + eps;
if constexpr (depth_range == NDCDepthRange::ZERO_TO_ONE) if constexpr (depth_range == NDCDepthRange::ZERO_TO_ONE)
return z_ndc < 0.0f - eps || z_ndc > 1.0f + eps; return z_ndc < NumericType{0} - eps || z_ndc > NumericType{1} + eps;
std::unreachable(); std::unreachable();
} }
@@ -569,7 +571,8 @@ namespace omath::projection
| |
*/ */
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}; return {(ndc.x + NumericType{1}) / NumericType{2} * m_view_port.m_width,
(ndc.y / -NumericType{2} + NumericType{0.5}) * m_view_port.m_height, ndc.z};
} }
[[nodiscard]] Vector3<NumericType> [[nodiscard]] Vector3<NumericType>
@@ -586,18 +589,19 @@ namespace omath::projection
| (0, 0) | (0, 0)
+------------------------> +------------------------>
*/ */
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}; return {(ndc.x + NumericType{1}) / NumericType{2} * m_view_port.m_width,
(ndc.y / NumericType{2} + NumericType{0.5}) * m_view_port.m_height, ndc.z};
} }
template<ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER> template<ScreenStart screen_start = ScreenStart::TOP_LEFT_CORNER>
[[nodiscard]] Vector3<NumericType> screen_to_ndc(const Vector3<NumericType>& screen_pos) const noexcept [[nodiscard]] Vector3<NumericType> screen_to_ndc(const Vector3<NumericType>& screen_pos) const noexcept
{ {
if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER) if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER)
return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, 1.f - screen_pos.y / m_view_port.m_height * 2.f, return {screen_pos.x / m_view_port.m_width * NumericType{2} - NumericType{1},
screen_pos.z}; NumericType{1} - screen_pos.y / m_view_port.m_height * NumericType{2}, screen_pos.z};
else if constexpr (screen_start == ScreenStart::BOTTOM_LEFT_CORNER) else if constexpr (screen_start == ScreenStart::BOTTOM_LEFT_CORNER)
return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, return {screen_pos.x / m_view_port.m_width * NumericType{2} - NumericType{1},
(screen_pos.y / m_view_port.m_height - 0.5f) * 2.f, screen_pos.z}; (screen_pos.y / m_view_port.m_height - NumericType{0.5}) * NumericType{2}, screen_pos.z};
else else
std::unreachable(); std::unreachable();
} }