// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "GeometryBase.h" #include "HAL/Platform.h" #include "EngineDefines.h" #include #include /** * Math constants and utility functions, templated on float/double type */ template struct TMathUtilConstants; template<> struct TMathUtilConstants { /** Machine Epsilon - float approx 1e-7, double approx 2e-16 */ static constexpr float Epsilon = FLT_EPSILON; /** Zero tolerance for math operations (eg like parallel tests) - float 1e-6, double 1e-8 */ static constexpr float ZeroTolerance = 1e-06f; /** largest possible number for type */ static constexpr float MaxReal = FLT_MAX; /** a very large value, but not too close to the max possible for the type */ static constexpr float SafeLargeValue = UE_LARGE_WORLD_MAX; /** 3.14159... */ static constexpr float Pi = 3.1415926535897932384626433832795f; static constexpr float FourPi = 4.0f * Pi; static constexpr float TwoPi = 2.0f*Pi; static constexpr float HalfPi = 0.5f*Pi; /** 1.0 / Pi */ static constexpr float InvPi = 1.0f / Pi; /** 1.0 / (2*Pi) */ static constexpr float InvTwoPi = 1.0f / TwoPi; /** pi / 180 */ static constexpr float DegToRad = Pi / 180.0f; /** 180 / pi */ static constexpr float RadToDeg = 180.0f / Pi; //static constexpr float LN_2; //static constexpr float LN_10; //static constexpr float INV_LN_2; //static constexpr float INV_LN_10; static constexpr float Sqrt2 = 1.4142135623730950488016887242097f; static constexpr float InvSqrt2 = 1.0f / Sqrt2; static constexpr float Sqrt3 = 1.7320508075688772935274463415059f; static constexpr float InvSqrt3 = 1.0f / Sqrt3; }; template<> struct TMathUtilConstants { /** Machine Epsilon - float approx 1e-7, double approx 2e-16 */ static constexpr double Epsilon = DBL_EPSILON; /** Zero tolerance for math operations (eg like parallel tests) - float 1e-6, double 1e-8 */ static constexpr double ZeroTolerance = 1e-08; /** largest possible number for type */ static constexpr double MaxReal = DBL_MAX; /** a very large value, but not too close to the max possible for the type */ static constexpr double SafeLargeValue = (double)FLT_MAX; /** 3.14159... */ static constexpr double Pi = 3.1415926535897932384626433832795; static constexpr double FourPi = 4.0 * Pi; static constexpr double TwoPi = 2.0 * Pi; static constexpr double HalfPi = 0.5 * Pi; /** 1.0 / Pi */ static constexpr double InvPi = 1.0 / Pi; /** 1.0 / (2*Pi) */ static constexpr double InvTwoPi = 1.0 / TwoPi; /** pi / 180 */ static constexpr double DegToRad = Pi / 180.0; /** 180 / pi */ static constexpr double RadToDeg = 180.0 / Pi; //static constexpr double LN_2; //static constexpr double LN_10; //static constexpr double INV_LN_2; //static constexpr double INV_LN_10; static constexpr double Sqrt2 = 1.4142135623730950488016887242097; static constexpr double InvSqrt2 = 1.0 / Sqrt2; static constexpr double Sqrt3 = 1.7320508075688772935274463415059; static constexpr double InvSqrt3 = 1.0 / Sqrt3; }; // we use TMathUtil so we need to define these nonsense constants template<> struct TMathUtilConstants { static constexpr int32 Epsilon = 0; static constexpr int32 ZeroTolerance = 0; static constexpr int32 MaxReal = MAX_int32; static constexpr int32 SafeLargeValue = MAX_int32/2; static constexpr int32 Pi = 3; static constexpr int32 FourPi = 4 * Pi; static constexpr int32 TwoPi = 2 * Pi; static constexpr int32 HalfPi = 1; static constexpr int32 InvPi = 1; static constexpr int32 InvTwoPi = 1; static constexpr int32 DegToRad = 1; static constexpr int32 RadToDeg = 1; static constexpr int32 Sqrt2 = 1; static constexpr int32 InvSqrt2 = 1; static constexpr int32 Sqrt3 = 2; static constexpr int32 InvSqrt3 = 1; }; // we use TMathUtil so we need to define these nonsense constants template<> struct TMathUtilConstants { static constexpr int64 Epsilon = 0; static constexpr int64 ZeroTolerance = 0; static constexpr int64 MaxReal = MAX_int64; static constexpr int64 SafeLargeValue = MAX_int64/2; static constexpr int64 Pi = 3; static constexpr int64 FourPi = 4 * Pi; static constexpr int64 TwoPi = 2 * Pi; static constexpr int64 HalfPi = 1; static constexpr int64 InvPi = 1; static constexpr int64 InvTwoPi = 1; static constexpr int64 DegToRad = 1; static constexpr int64 RadToDeg = 1; static constexpr int64 Sqrt2 = 1; static constexpr int64 InvSqrt2 = 1; static constexpr int64 Sqrt3 = 2; static constexpr int64 InvSqrt3 = 1; }; template class TMathUtil : public TMathUtilConstants { public: static inline bool IsNaN(const RealType Value); static inline bool IsFinite(const RealType Value); static inline RealType Abs(const RealType Value); static inline RealType Clamp(const RealType Value, const RealType ClampMin, const RealType ClampMax); static inline RealType Sign(const RealType Value); static inline int32 SignAsInt(const RealType Value); static inline RealType SignNonZero(const RealType Value); static inline RealType Max(const RealType A, const RealType B); static inline RealType Max3(const RealType A, const RealType B, const RealType C); static inline int32 Max3Index(const RealType A, const RealType B, const RealType C); static inline RealType Min(const RealType A, const RealType B); static inline RealType Min3(const RealType A, const RealType B, const RealType C); static inline int32 Min3Index(const RealType A, const RealType B, const RealType C); /** compute min and max of a,b,c with max 3 comparisons (sometimes 2) */ static inline void MinMax(RealType A, RealType B, RealType C, RealType& MinOut, RealType& MaxOut); /** Uses a quadratic blend to smooth the min transition when A and B are less than BlendExtent apart. */ static inline RealType SmoothMin(RealType A, RealType B, RealType BlendExtent); /** Uses a quadratic blend to smooth the max transition when A and B are less than BlendExtent apart. */ static inline RealType SmoothMax(RealType A, RealType B, RealType BlendExtent); static inline RealType Sqrt(const RealType Value); /** Compute cube root */ static inline RealType Cbrt(const RealType Value); static inline RealType Tan(const RealType Value); static inline RealType Atan2(const RealType ValueY, const RealType ValueX); static inline RealType Sin(const RealType Value); static inline RealType Cos(const RealType Value); static inline RealType ACos(const RealType Value); static inline RealType Floor(const RealType Value); static inline RealType Ceil(const RealType Value); static inline RealType Round(const RealType Value); static inline RealType Pow(const RealType Value, const RealType Power); static inline RealType Exp(const RealType Power); static inline RealType Log(const RealType Value); static inline RealType Lerp(const RealType A, const RealType B, RealType Alpha); /** * @return result of Atan2 shifted to [0,2pi] (normal ATan2 returns in range [-pi,pi]) */ static inline RealType Atan2Positive(const RealType Y, const RealType X); private: TMathUtil() = delete; }; typedef TMathUtil FMathf; typedef TMathUtil FMathd; template bool TMathUtil::IsNaN(const RealType Value) { return std::isnan(Value); } template bool TMathUtil::IsFinite(const RealType Value) { return std::isfinite(Value); } template RealType TMathUtil::Abs(const RealType Value) { return (Value >= (RealType)0) ? Value : -Value; } template RealType TMathUtil::Clamp(const RealType Value, const RealType ClampMin, const RealType ClampMax) { return (Value < ClampMin) ? ClampMin : ((Value > ClampMax) ? ClampMax : Value); } template int32 TMathUtil::SignAsInt(const RealType Value) { return (Value > (RealType)0) ? 1 : ((Value < (RealType)0) ? -1 : 0); } template RealType TMathUtil::Sign(const RealType Value) { return (RealType)SignAsInt(Value); } template RealType TMathUtil::SignNonZero(const RealType Value) { return (Value < (RealType)0) ? (RealType)-1 : (RealType)1; } template RealType TMathUtil::Max(const RealType A, const RealType B) { return (A >= B) ? A : B; } template RealType TMathUtil::Max3(const RealType A, const RealType B, const RealType C) { return Max(Max(A, B), C); } template int32 TMathUtil::Max3Index(const RealType A, const RealType B, const RealType C) { if (A >= B) { return (A >= C) ? 0 : 2; } else { return (B >= C) ? 1 : 2; } } template RealType TMathUtil::Min(const RealType A, const RealType B) { return (A <= B) ? A : B; } template RealType TMathUtil::Min3(const RealType A, const RealType B, const RealType C) { return Min(Min(A, B), C); } template int32 TMathUtil::Min3Index(const RealType A, const RealType B, const RealType C) { if (A <= B) { return (A <= C) ? 0 : 2; } else { return (B <= C) ? 1 : 2; } } // compute min and max of a,b,c with max 3 comparisons (sometimes 2) template void TMathUtil::MinMax(RealType A, RealType B, RealType C, RealType& MinOut, RealType& MaxOut) { if (A < B) { if (A < C) { MinOut = A; MaxOut = TMathUtil::Max(B, C); } else { MinOut = C; MaxOut = B; } } else { if (A > C) { MaxOut = A; MinOut = TMathUtil::Min(B, C); } else { MinOut = B; MaxOut = C; } } } template RealType TMathUtil::SmoothMin(RealType A, RealType B, RealType BlendExtent) { if (BlendExtent == 0) { return Min(A, B); } double H = (BlendExtent + B - A) / 2; return Min(B - H * Clamp(H / BlendExtent, 0.0, 1.0), A); } template RealType TMathUtil::SmoothMax(RealType A, RealType B, RealType BlendExtent) { if (BlendExtent == 0) { return Max(A, B); } double H = (BlendExtent + A - B) / 2; return Max(B + H * Clamp(H / BlendExtent, 0.0, 1.0), A); } template RealType TMathUtil::Sqrt(const RealType Value) { return sqrt(Value); } template RealType TMathUtil::Cbrt(const RealType Value) { return cbrt(Value); } template RealType TMathUtil::Tan(const RealType Value) { return tan(Value); } template RealType TMathUtil::Atan2(const RealType ValueY, const RealType ValueX) { return atan2(ValueY, ValueX); } template RealType TMathUtil::Sin(const RealType Value) { return sin(Value); } template RealType TMathUtil::Cos(const RealType Value) { return cos(Value); } template RealType TMathUtil::ACos(const RealType Value) { return acos(Value); } template RealType TMathUtil::Floor(const RealType Value) { return floor(Value); } template RealType TMathUtil::Ceil(const RealType Value) { return ceil(Value); } template RealType TMathUtil::Round(const RealType Value) { return round(Value); } template RealType TMathUtil::Pow(const RealType Value, const RealType Power) { return pow(Value, Power); } template RealType TMathUtil::Exp(const RealType Power) { return exp(Power); } template RealType TMathUtil::Log(const RealType Power) { return log(Power); } template RealType TMathUtil::Lerp(const RealType A, const RealType B, RealType Alpha) { Alpha = Clamp(Alpha, (RealType)0, (RealType)1); return ((RealType)1 - Alpha)*A + (Alpha)*B; } template RealType TMathUtil::Atan2Positive(const RealType Y, const RealType X) { // @todo this is a float atan2 !! RealType Theta = TMathUtil::Atan2(Y, X); if (Theta < 0) { return ((RealType)2 * TMathUtil::Pi) + Theta; } return Theta; }