diff --git a/include/omath/projection/camera.hpp b/include/omath/projection/camera.hpp index 30da354..e612666 100644 --- a/include/omath/projection/camera.hpp +++ b/include/omath/projection/camera.hpp @@ -32,7 +32,7 @@ namespace omath::projection float m_width; float m_height; - [[nodiscard]] constexpr float aspect_ratio() const + [[nodiscard("You must use aspect ratio")]] constexpr float aspect_ratio() const { return m_width / m_height; } @@ -101,7 +101,7 @@ namespace omath::projection // built by any of the engine traits. Both variants (ZERO_TO_ONE and // NEGATIVE_ONE_TO_ONE) share the same m[0,0]/m[1,1] layout, so this works // regardless of the NDC depth range. - [[nodiscard]] + [[nodiscard("You must use extracted projection params")]] static ProjectionParams extract_projection_params(const Mat4X4Type& proj_matrix) noexcept { // m[1,1] == 1 / tan(fov/2) => fov = 2 * atan(1 / m[1,1]) @@ -112,7 +112,7 @@ namespace omath::projection f / proj_matrix.at(0, 0)}; } - [[nodiscard]] + [[nodiscard("You must use calculated view angles")]] static ViewAnglesType calc_view_angles_from_view_matrix(const Mat4X4Type& view_matrix) noexcept { Vector3 forward_vector = {view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]}; @@ -121,7 +121,7 @@ namespace omath::projection return TraitClass::calc_look_at_angle({}, forward_vector); } - [[nodiscard]] + [[nodiscard("You must use calculated origin")]] static Vector3 calc_origin_from_view_matrix(const Mat4X4Type& view_matrix) noexcept { // The view matrix is R * T(-origin), so the last column stores t = -R * origin. @@ -142,33 +142,33 @@ namespace omath::projection m_view_projection_matrix = std::nullopt; m_view_matrix = std::nullopt; } - [[nodiscard]] + [[nodiscard("You must use calculated look-at angles")]] ViewAnglesType calc_look_at_angles(const Vector3& look_to) const { return TraitClass::calc_look_at_angle(m_origin, look_to); } - [[nodiscard]] + [[nodiscard("You must use forward vector")]] Vector3 get_forward() const noexcept { const auto& view_matrix = get_view_matrix(); return {view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]}; } - [[nodiscard]] + [[nodiscard("You must use right vector")]] Vector3 get_right() const noexcept { const auto& view_matrix = get_view_matrix(); return {view_matrix[0, 0], view_matrix[0, 1], view_matrix[0, 2]}; } - [[nodiscard]] + [[nodiscard("You must use up vector")]] Vector3 get_up() const noexcept { const auto& view_matrix = get_view_matrix(); return {view_matrix[1, 0], view_matrix[1, 1], view_matrix[1, 2]}; } - [[nodiscard]] + [[nodiscard("You must use absolute forward vector")]] Vector3 get_abs_forward() const noexcept { if constexpr (axes.inverted_forward) @@ -176,7 +176,7 @@ namespace omath::projection return get_forward(); } - [[nodiscard]] + [[nodiscard("You must use absolute right vector")]] Vector3 get_abs_right() const noexcept { if constexpr (axes.inverted_right) @@ -184,13 +184,13 @@ namespace omath::projection return get_right(); } - [[nodiscard]] + [[nodiscard("You must use absolute up vector")]] Vector3 get_abs_up() const noexcept { return get_up(); } - [[nodiscard]] const Mat4X4Type& get_view_projection_matrix() const noexcept + [[nodiscard("You must use view-projection matrix")]] const Mat4X4Type& get_view_projection_matrix() const noexcept { if (!m_view_projection_matrix.has_value()) m_view_projection_matrix = get_projection_matrix() * get_view_matrix(); @@ -198,14 +198,14 @@ namespace omath::projection return m_view_projection_matrix.value(); } - [[nodiscard]] const Mat4X4Type& get_view_matrix() const noexcept + [[nodiscard("You must use view matrix")]] const Mat4X4Type& get_view_matrix() const noexcept { if (!m_view_matrix.has_value()) m_view_matrix = TraitClass::calc_view_matrix(m_view_angles, m_origin); return m_view_matrix.value(); } - [[nodiscard]] const Mat4X4Type& get_projection_matrix() const noexcept + [[nodiscard("You must use projection matrix")]] const Mat4X4Type& get_projection_matrix() const noexcept { if (!m_projection_matrix.has_value()) m_projection_matrix = TraitClass::calc_projection_matrix( @@ -255,33 +255,33 @@ namespace omath::projection m_projection_matrix = std::nullopt; } - [[nodiscard]] const FieldOfView& get_field_of_view() const noexcept + [[nodiscard("You must use field of view")]] const FieldOfView& get_field_of_view() const noexcept { return m_field_of_view; } - [[nodiscard]] const NumericType& get_near_plane() const noexcept + [[nodiscard("You must use near plane")]] const NumericType& get_near_plane() const noexcept { return m_near_plane_distance; } - [[nodiscard]] const NumericType& get_far_plane() const noexcept + [[nodiscard("You must use far plane")]] const NumericType& get_far_plane() const noexcept { return m_far_plane_distance; } - [[nodiscard]] const ViewAnglesType& get_view_angles() const noexcept + [[nodiscard("You must use view angles")]] const ViewAnglesType& get_view_angles() const noexcept { return m_view_angles; } - [[nodiscard]] const Vector3& get_origin() const noexcept + [[nodiscard("You must use origin")]] const Vector3& get_origin() const noexcept { return m_origin; } template - [[nodiscard]] std::expected, Error> + [[nodiscard("You must use screen position")]] std::expected, Error> world_to_screen(const Vector3& world_position) const noexcept { const auto normalized_cords = world_to_view_port(world_position); @@ -297,7 +297,7 @@ namespace omath::projection std::unreachable(); } template - [[nodiscard]] std::expected, Error> + [[nodiscard("You must use unclipped screen position")]] std::expected, Error> world_to_screen_unclipped(const Vector3& world_position) const noexcept { const auto normalized_cords = world_to_view_port(world_position, ViewPortClipping::MANUAL); @@ -313,7 +313,7 @@ namespace omath::projection std::unreachable(); } - [[nodiscard]] bool is_culled_by_frustum(const Triangle>& triangle) const noexcept + [[nodiscard("You must use frustum culling result")]] bool is_culled_by_frustum(const Triangle>& triangle) const noexcept { // Transform to clip space (before perspective divide) auto to_clip = [this](const Vector3& point) @@ -380,7 +380,7 @@ namespace omath::projection return false; } - [[nodiscard]] bool is_aabb_culled_by_frustum(const primitives::Aabb& aabb) const noexcept + [[nodiscard("You must use AABB frustum culling result")]] bool is_aabb_culled_by_frustum(const primitives::Aabb& aabb) const noexcept { // For each plane, find the AABB corner most in the direction of the plane normal // (the "positive vertex"). If it's outside, the entire AABB is outside. @@ -397,7 +397,7 @@ namespace omath::projection return false; } - [[nodiscard]] bool is_obb_culled_by_frustum(const primitives::Obb& obb) const noexcept + [[nodiscard("You must use OBB frustum culling result")]] bool is_obb_culled_by_frustum(const primitives::Obb& obb) const noexcept { // For each plane, project the OBB extents onto the plane normal to get the // effective radius, then test the center's signed distance against it. @@ -417,7 +417,7 @@ namespace omath::projection return false; } - [[nodiscard]] std::expected, Error> + [[nodiscard("You must use view port position")]] std::expected, Error> world_to_view_port(const Vector3& world_position, const ViewPortClipping& clipping = ViewPortClipping::AUTO) const noexcept { @@ -446,7 +446,7 @@ namespace omath::projection return Vector3{projected.at(0, 0), projected.at(1, 0), projected.at(2, 0)}; } - [[nodiscard]] + [[nodiscard("You must use world position")]] std::expected, Error> view_port_to_world(const Vector3& ndc) const noexcept { const auto inv_view_proj = get_view_projection_matrix().inverted(); @@ -469,7 +469,7 @@ namespace omath::projection } template - [[nodiscard]] + [[nodiscard("You must use world position")]] std::expected, Error> screen_to_world(const Vector3& screen_pos) const noexcept { @@ -477,7 +477,7 @@ namespace omath::projection } template - [[nodiscard]] + [[nodiscard("You must use world position")]] std::expected, Error> screen_to_world(const Vector2& screen_pos) const noexcept { @@ -513,7 +513,7 @@ namespace omath::projection // Top = r3 - r1 // Near = r3 + r2 ([-1,1]) or r2 ([0,1]) // Far = r3 - r2 - [[nodiscard]] std::array extract_frustum_planes() const noexcept + [[nodiscard("You must use frustum planes")]] std::array extract_frustum_planes() const noexcept { const auto& m = get_view_projection_matrix(); @@ -545,7 +545,7 @@ namespace omath::projection } template - [[nodiscard]] constexpr static bool is_ndc_out_of_bounds(const Type& ndc) noexcept + [[nodiscard("You must use NDC bounds check result")]] constexpr static bool is_ndc_out_of_bounds(const Type& ndc) noexcept { constexpr auto eps = std::numeric_limits::epsilon(); @@ -558,7 +558,7 @@ namespace omath::projection return is_ndc_z_value_out_of_bounds(data[2]); } template - [[nodiscard]] + [[nodiscard("You must use NDC z bounds check result")]] constexpr static bool is_ndc_z_value_out_of_bounds(const ZType& z_ndc) noexcept { constexpr auto eps = std::numeric_limits::epsilon(); @@ -584,7 +584,7 @@ namespace omath::projection v */ - [[nodiscard]] Vector3 + [[nodiscard("You must use screen position")]] Vector3 ndc_to_screen_position_from_top_left_corner(const Vector3& ndc) const noexcept { /* @@ -602,7 +602,7 @@ namespace omath::projection (ndc.y / -NumericType{2} + NumericType{0.5}) * m_view_port.m_height, ndc.z}; } - [[nodiscard]] Vector3 + [[nodiscard("You must use screen position")]] Vector3 ndc_to_screen_position_from_bottom_left_corner(const Vector3& ndc) const noexcept { /* @@ -621,7 +621,7 @@ namespace omath::projection } template - [[nodiscard]] Vector3 screen_to_ndc(const Vector3& screen_pos) const noexcept + [[nodiscard("You must use NDC position")]] Vector3 screen_to_ndc(const Vector3& screen_pos) const noexcept { if constexpr (screen_start == ScreenStart::TOP_LEFT_CORNER) return {screen_pos.x / m_view_port.m_width * NumericType{2} - NumericType{1},