diff --git a/include/omath/engines/cry_engine/traits/camera_trait.hpp b/include/omath/engines/cry_engine/traits/camera_trait.hpp index 0aee139..58e2927 100644 --- a/include/omath/engines/cry_engine/traits/camera_trait.hpp +++ b/include/omath/engines/cry_engine/traits/camera_trait.hpp @@ -16,13 +16,8 @@ namespace omath::cry_engine const Vector3& look_at) noexcept { const auto direction = (look_at - cam_origin).normalized(); -#ifdef OMATH_USE_GCEM - return {PitchAngle::from_radians(gcem::asin(direction.z)), - YawAngle::from_radians(-gcem::atan2(direction.x, direction.y)), RollAngle::from_radians(0.f)}; -#else - return {PitchAngle::from_radians(std::asin(direction.z)), - YawAngle::from_radians(-std::atan2(direction.x, direction.y)), RollAngle::from_radians(0.f)}; -#endif + return {PitchAngle::from_radians(internal::asin(direction.z)), + YawAngle::from_radians(-internal::atan2(direction.x, direction.y)), RollAngle::from_radians(0.f)}; } [[nodiscard]] diff --git a/include/omath/internal/optional_constexpr_math.hpp b/include/omath/internal/optional_constexpr_math.hpp index ecc49dd..ebd3fa9 100644 --- a/include/omath/internal/optional_constexpr_math.hpp +++ b/include/omath/internal/optional_constexpr_math.hpp @@ -3,10 +3,147 @@ // #pragma once +#include +#include #ifdef OMATH_USE_GCEM #include #define OMATH_CONSTEXPR constexpr #else #define OMATH_CONSTEXPR -#endif \ No newline at end of file +#endif + +namespace omath::internal +{ + template + [[nodiscard]] + OMATH_CONSTEXPR Type sin(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::sin(value); +#endif + return std::sin(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type cos(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::cos(value); +#endif + return std::cos(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type tan(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::tan(value); +#endif + return std::tan(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type atan(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::atan(value); +#endif + return std::atan(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type atan2(const Type& y, const Type& x) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::atan2(y, x); +#endif + return std::atan2(y, x); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type asin(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::asin(value); +#endif + return std::asin(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type acos(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::acos(value); +#endif + return std::acos(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type sqrt(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::sqrt(value); +#endif + return std::sqrt(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type hypot(const Type& x, const Type& y) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::hypot(x, y); +#endif + return std::hypot(x, y); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type hypot(const Type& x, const Type& y, const Type& z) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::sqrt(x * x + y * y + z * z); +#endif + return std::hypot(x, y, z); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type abs(const Type& value) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::abs(value); +#endif + return std::abs(value); + } + + template + [[nodiscard]] + OMATH_CONSTEXPR Type fmod(const Type& dividend, const Type& divisor) noexcept + { +#ifdef OMATH_USE_GCEM + if (std::is_constant_evaluated()) + return gcem::fmod(dividend, divisor); +#endif + return std::fmod(dividend, divisor); + } +} // namespace omath::internal diff --git a/include/omath/linear_algebra/mat.hpp b/include/omath/linear_algebra/mat.hpp index f0f8bb4..012c3e6 100644 --- a/include/omath/linear_algebra/mat.hpp +++ b/include/omath/linear_algebra/mat.hpp @@ -2,6 +2,7 @@ // Created by vlad on 9/29/2024. // #pragma once +#include "omath/internal/optional_constexpr_math.hpp" #include "vector3.hpp" #include #include @@ -634,11 +635,7 @@ namespace omath OMATH_CONSTEXPR Vector3 mat_extract_scale(const Mat<4, 4, Type, St>& mat) noexcept { auto column_length = [](const Type x, const Type y, const Type z) { -#ifdef OMATH_USE_GCEM - return static_cast(gcem::sqrt(x * x + y * y + z * z)); -#else - return static_cast(std::sqrt(x * x + y * y + z * z)); -#endif + return static_cast(internal::sqrt(x * x + y * y + z * z)); }; const auto scale_x = column_length(mat.at(0, 0), mat.at(1, 0), mat.at(2, 0)); @@ -648,15 +645,9 @@ namespace omath constexpr auto epsilon = std::numeric_limits::epsilon(); return { -#ifdef OMATH_USE_GCEM - gcem::abs(scale_x) < epsilon ? Type{1} : scale_x, - gcem::abs(scale_y) < epsilon ? Type{1} : scale_y, - gcem::abs(scale_z) < epsilon ? Type{1} : scale_z, -#else - std::abs(scale_x) < epsilon ? Type{1} : scale_x, - std::abs(scale_y) < epsilon ? Type{1} : scale_y, - std::abs(scale_z) < epsilon ? Type{1} : scale_z, -#endif + internal::abs(scale_x) < epsilon ? Type{1} : scale_x, + internal::abs(scale_y) < epsilon ? Type{1} : scale_y, + internal::abs(scale_z) < epsilon ? Type{1} : scale_z, }; } @@ -673,15 +664,9 @@ namespace omath const auto m22 = mat.at(2, 2) / scale.z; return { -#ifdef OMATH_USE_GCEM - angles::radians_to_degrees(gcem::atan2(m21, m22)), - angles::radians_to_degrees(gcem::asin(std::clamp(-m20, Type{-1}, Type{1}))), - angles::radians_to_degrees(gcem::atan2(m10, m00)), -#else - angles::radians_to_degrees(std::atan2(m21, m22)), - angles::radians_to_degrees(std::asin(std::clamp(-m20, Type{-1}, Type{1}))), - angles::radians_to_degrees(std::atan2(m10, m00)), -#endif + angles::radians_to_degrees(internal::atan2(m21, m22)), + angles::radians_to_degrees(internal::asin(std::clamp(-m20, Type{-1}, Type{1}))), + angles::radians_to_degrees(internal::atan2(m10, m00)), }; } @@ -744,11 +729,7 @@ namespace omath Mat<4, 4, Type, St> mat_perspective_left_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio, const Type near, const Type far) noexcept { -#ifdef OMATH_USE_GCEM - const auto fov_half_tan = gcem::tan(angles::degrees_to_radians(field_of_view) / Type{2}); -#else - const auto fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / Type{2}); -#endif + const auto fov_half_tan = internal::tan(angles::degrees_to_radians(field_of_view) / Type{2}); if constexpr (DepthRange == NDCDepthRange::ZERO_TO_ONE) return {{Type{1} / (aspect_ratio * fov_half_tan), Type{0}, Type{0}, Type{0}}, {Type{0}, Type{1} / fov_half_tan, Type{0}, Type{0}}, @@ -769,11 +750,7 @@ namespace omath Mat<4, 4, Type, St> mat_perspective_right_handed_vertical_fov(const Type field_of_view, const Type aspect_ratio, const Type near, const Type far) noexcept { -#ifdef OMATH_USE_GCEM - const auto fov_half_tan = gcem::tan(angles::degrees_to_radians(field_of_view) / Type{2}); -#else - const auto fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / Type{2}); -#endif + const auto fov_half_tan = internal::tan(angles::degrees_to_radians(field_of_view) / Type{2}); if constexpr (DepthRange == NDCDepthRange::ZERO_TO_ONE) return {{Type{1} / (aspect_ratio * fov_half_tan), Type{0}, Type{0}, Type{0}}, @@ -799,11 +776,7 @@ namespace omath const Type aspect_ratio, const Type near, const Type far) noexcept { -#ifdef OMATH_USE_GCEM - const auto inv_tan_half_hfov = Type{1} / gcem::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); -#else - const auto inv_tan_half_hfov = Type{1} / std::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); -#endif + const auto inv_tan_half_hfov = Type{1} / internal::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); const auto x_axis = inv_tan_half_hfov; const auto y_axis = inv_tan_half_hfov * aspect_ratio; @@ -828,11 +801,7 @@ namespace omath const Type aspect_ratio, const Type near, const Type far) noexcept { -#ifdef OMATH_USE_GCEM - const auto inv_tan_half_hfov = Type{1} / gcem::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); -#else - const auto inv_tan_half_hfov = Type{1} / std::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); -#endif + const auto inv_tan_half_hfov = Type{1} / internal::tan(angles::degrees_to_radians(horizontal_fov) / Type{2}); const auto x_axis = inv_tan_half_hfov; const auto y_axis = inv_tan_half_hfov * aspect_ratio; diff --git a/include/omath/linear_algebra/triangle.hpp b/include/omath/linear_algebra/triangle.hpp index 8e051be..3111389 100644 --- a/include/omath/linear_algebra/triangle.hpp +++ b/include/omath/linear_algebra/triangle.hpp @@ -69,11 +69,7 @@ namespace omath const auto side_b = side_b_length(); const auto hypot_value = hypot(); -#ifdef OMATH_USE_GCEM - return gcem::abs(side_a * side_a + side_b * side_b - hypot_value * hypot_value) <= 0.0001f; -#else - return std::abs(side_a * side_a + side_b * side_b - hypot_value * hypot_value) <= 0.0001f; -#endif + return internal::abs(side_a * side_a + side_b * side_b - hypot_value * hypot_value) <= 0.0001f; } [[nodiscard]] constexpr Vector side_b_vector() const diff --git a/include/omath/linear_algebra/vector2.hpp b/include/omath/linear_algebra/vector2.hpp index 74ef70b..d94924f 100644 --- a/include/omath/linear_algebra/vector2.hpp +++ b/include/omath/linear_algebra/vector2.hpp @@ -119,11 +119,7 @@ namespace omath [[nodiscard("You must use distance")]] OMATH_CONSTEXPR Type distance_to(const Vector2& other) const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::sqrt(distance_to_sqr(other)); -#else - return std::sqrt(distance_to_sqr(other)); -#endif + return internal::sqrt(distance_to_sqr(other)); } [[nodiscard("You must use squared distance")]] @@ -141,11 +137,7 @@ namespace omath #ifndef _MSC_VER [[nodiscard("You must use length")]] constexpr Type length() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::hypot(this->x, this->y); -#else - return std::hypot(this->x, this->y); -#endif + return internal::hypot(this->x, this->y); } [[nodiscard("You must use normalized vector")]] constexpr Vector2 normalized() const noexcept @@ -157,11 +149,7 @@ namespace omath [[nodiscard("You must use length")]] OMATH_CONSTEXPR Type length() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::hypot(x, y); -#else - return std::hypot(x, y); -#endif + return internal::hypot(x, y); } [[nodiscard("You must use normalized vector")]] diff --git a/include/omath/linear_algebra/vector3.hpp b/include/omath/linear_algebra/vector3.hpp index c36deb1..4a178a4 100644 --- a/include/omath/linear_algebra/vector3.hpp +++ b/include/omath/linear_algebra/vector3.hpp @@ -4,6 +4,7 @@ #pragma once +#include "omath/internal/optional_constexpr_math.hpp" #include "omath/linear_algebra/vector2.hpp" #include "omath/trigonometry/angle.hpp" #include @@ -142,11 +143,7 @@ namespace omath #ifndef _MSC_VER [[nodiscard("You must use length")]] constexpr Type length() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::sqrt(this->x * this->x + this->y * this->y + z * z); -#else - return std::hypot(this->x, this->y, z); -#endif + return internal::hypot(this->x, this->y, z); } [[nodiscard("You must use 2D length")]] constexpr Type length_2d() const noexcept @@ -167,11 +164,7 @@ namespace omath [[nodiscard("You must use length")]] OMATH_CONSTEXPR Type length() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::sqrt(this->x * this->x + this->y * this->y + this->z * this->z); -#else - return std::hypot(this->x, this->y, z); -#endif + return internal::hypot(this->x, this->y, this->z); } [[nodiscard("You must use normalized vector")]] @@ -269,11 +262,7 @@ namespace omath if (bottom == static_cast(0)) return std::unexpected(Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE); -#ifdef OMATH_USE_GCEM - return Angle::from_radians(gcem::acos(dot(other) / bottom)); -#else - return Angle::from_radians(std::acos(dot(other) / bottom)); -#endif + return Angle::from_radians(internal::acos(dot(other) / bottom)); } [[nodiscard("You must use perpendicularity check result")]] diff --git a/include/omath/trigonometry/angle.hpp b/include/omath/trigonometry/angle.hpp index 146a309..37980dd 100644 --- a/include/omath/trigonometry/angle.hpp +++ b/include/omath/trigonometry/angle.hpp @@ -73,45 +73,25 @@ namespace omath [[nodiscard]] OMATH_CONSTEXPR Type sin() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::sin(as_radians()); -#else - return std::sin(as_radians()); - -#endif + return internal::sin(as_radians()); } [[nodiscard]] OMATH_CONSTEXPR Type cos() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::cos(as_radians()); -#else - return std::cos(as_radians()); - -#endif + return internal::cos(as_radians()); } [[nodiscard]] OMATH_CONSTEXPR Type tan() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::tan(as_radians()); -#else - return std::tan(as_radians()); - -#endif + return internal::tan(as_radians()); } [[nodiscard]] OMATH_CONSTEXPR Type atan() const noexcept { -#ifdef OMATH_USE_GCEM - return gcem::atan(as_radians()); -#else - return std::atan(as_radians()); - -#endif + return internal::atan(as_radians()); } [[nodiscard]] diff --git a/include/omath/trigonometry/angles.hpp b/include/omath/trigonometry/angles.hpp index 10c2789..1e08cfb 100644 --- a/include/omath/trigonometry/angles.hpp +++ b/include/omath/trigonometry/angles.hpp @@ -25,23 +25,25 @@ namespace omath::angles template requires std::is_floating_point_v - [[nodiscard]] Type horizontal_fov_to_vertical(const Type& horizontal_fov, const Type& aspect) noexcept + [[nodiscard]] OMATH_CONSTEXPR Type horizontal_fov_to_vertical(const Type& horizontal_fov, + const Type& aspect) noexcept { const auto fov_rad = degrees_to_radians(horizontal_fov); - const auto vert_fov = static_cast(2) * std::atan(std::tan(fov_rad / static_cast(2)) / aspect); + const auto vert_fov = static_cast(2) * internal::atan(internal::tan(fov_rad / static_cast(2)) / aspect); return radians_to_degrees(vert_fov); } template requires std::is_floating_point_v - [[nodiscard]] Type vertical_fov_to_horizontal(const Type& vertical_fov, const Type& aspect) noexcept + [[nodiscard]] OMATH_CONSTEXPR Type vertical_fov_to_horizontal(const Type& vertical_fov, + const Type& aspect) noexcept { const auto fov_as_radians = degrees_to_radians(vertical_fov); const auto horizontal_fov = - static_cast(2) * std::atan(std::tan(fov_as_radians / static_cast(2)) * aspect); + static_cast(2) * internal::atan(internal::tan(fov_as_radians / static_cast(2)) * aspect); return radians_to_degrees(horizontal_fov); } @@ -55,11 +57,7 @@ namespace omath::angles const Type range = max - min; -#ifdef OMATH_USE_GCEM - Type wrapped_angle = gcem::fmod(angle - min, range); -#else - Type wrapped_angle = std::fmod(angle - min, range); -#endif + Type wrapped_angle = internal::fmod(angle - min, range); if (wrapped_angle < 0) wrapped_angle += range; diff --git a/include/omath/trigonometry/view_angles.hpp b/include/omath/trigonometry/view_angles.hpp index 2a11f96..87f90ff 100644 --- a/include/omath/trigonometry/view_angles.hpp +++ b/include/omath/trigonometry/view_angles.hpp @@ -18,7 +18,7 @@ namespace omath RollType roll; [[nodiscard]] - Vector3 as_vector3() const + constexpr Vector3 as_vector3() const { return {pitch.as_degrees(), yaw.as_degrees(), roll.as_degrees()}; }