| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Util/Functions.h>
- #include <cmath>
- #include <cstdlib>
- namespace anki {
- /// @addtogroup math
- /// @{
- /// Just PI.
- constexpr F32 kPi = 3.14159265358979323846f;
- /// Floating point epsilon.
- constexpr F32 kEpsilonf = 1.0e-6f;
- template<typename T>
- inline T sin(const T rad)
- {
- return std::sin(rad);
- }
- template<typename T>
- inline T cos(const T rad)
- {
- return std::cos(rad);
- }
- template<typename T>
- inline T tan(const T rad)
- {
- return std::tan(rad);
- }
- template<typename T>
- inline T acos(const T x)
- {
- ANKI_ASSERT(x >= T(-1) && x <= T(1));
- return std::acos(x);
- }
- template<typename T>
- inline T asin(const T x)
- {
- return std::asin(x);
- }
- template<typename T>
- inline T atan(const T x)
- {
- return std::atan(x);
- }
- template<typename T>
- inline T atan2(const T x, const T y)
- {
- return std::atan2(x, y);
- }
- void sinCos(const F32 a, F32& sina, F32& cosa);
- void sinCos(const F64 a, F64& sina, F64& cosa);
- template<typename T>
- inline T sqrt(const T x) requires(std::is_floating_point<T>::value)
- {
- return std::sqrt(x);
- }
- template<typename T>
- inline T sqrt(const T x) requires(std::is_integral<T>::value)
- {
- return T(std::sqrt(F64(x)));
- }
- template<typename T>
- inline T fract(const T x)
- {
- return x - std::floor(x);
- }
- template<typename T>
- inline T mod(const T x, const T y)
- {
- return x - y * std::floor(x / y);
- }
- /// Like GLSL's mix.
- template<typename T, typename Y>
- inline T mix(T x, T y, Y factor)
- {
- return x * (T(1) - factor) + y * factor;
- }
- /// Like GLSL's modf
- template<typename T>
- inline T modf(T x, T& intPart)
- {
- return std::modf(x, &intPart);
- }
- /// The same as abs/fabs. For ints.
- template<typename T>
- inline constexpr T absolute(const T f) requires(std::is_integral<T>::value&& std::is_signed<T>::value)
- {
- return (f < T(0)) ? -f : f;
- }
- /// The same as abs/fabs. For floats.
- template<typename T>
- inline constexpr T absolute(const T f) requires(std::is_floating_point<T>::value&& std::is_same_v<T, double>)
- {
- return fabs(f);
- }
- /// The same as abs/fabs. For floats.
- template<typename T>
- inline constexpr T absolute(const T f) requires(std::is_floating_point<T>::value&& std::is_same_v<T, float>)
- {
- return fabsf(f);
- }
- template<typename T>
- inline constexpr T pow(const T x, const T exp)
- {
- return T(std::pow(x, exp));
- }
- template<typename T>
- inline constexpr T log2(const T x)
- {
- return T(std::log2(x));
- }
- template<typename T>
- inline constexpr Bool isZero(const T f, const T e = kEpsilonf) requires(std::is_floating_point<T>::value)
- {
- return absolute<T>(f) < e;
- }
- template<typename T>
- inline constexpr Bool isZero(const T f) requires(std::is_integral<T>::value)
- {
- return f == 0;
- }
- template<typename T>
- inline constexpr T toRad(const T degrees) requires(std::is_floating_point<T>::value)
- {
- return degrees * (kPi / T(180));
- }
- template<typename T>
- inline constexpr T toDegrees(const T rad)
- {
- return rad * (T(180) / kPi);
- }
- template<typename T>
- inline constexpr T saturate(T v)
- {
- return clamp<T>(v, T(0), T(1));
- }
- /// Returns 1 or -1 based on the sign
- template<typename T>
- inline constexpr T sign(T v)
- {
- return (v > T(0)) ? T(1) : T(-1);
- }
- /// Same as smoothstep in glsl
- template<typename T>
- inline constexpr T smoothstep(T edge0, T edge1, T value)
- {
- value = clamp((value - edge0) / (edge1 - edge0), T(0), T(1));
- return value * value * (T(3) - T(2) * value);
- }
- /// Linear interpolation between values
- /// @param[in] from Starting value
- /// @param[in] to Ending value
- /// @param[in] u The percentage from the from "from" value. Values from [0.0, 1.0]
- template<typename T>
- inline constexpr T linearInterpolate(const T& from, const T& to, F32 u)
- {
- return from * T(1.0f - u) + to * T(u);
- }
- /// Cosine interpolation
- /// @param[in] from Starting value
- /// @param[in] to Ending value
- /// @param[in] u The percentage from the from "from" value. Values from [0.0, 1.0]
- template<typename T>
- inline T cosInterpolate(const T& from, const T& to, F32 u)
- {
- const F32 u2 = (1.0f - cos<F32>(u * kPi)) / 2.0f;
- return from * T(1.0f - u2) + to * T(u2);
- }
- /// Cubic interpolation
- /// @param[in] a Point a
- /// @param[in] b Point b
- /// @param[in] c Point c
- /// @param[in] d Point d
- /// @param[in] u The percentage from the from b point to d point. Value from [0.0, 1.0]
- template<typename T>
- inline constexpr T cubicInterpolate(const T& a, const T& b, const T& c, const T& d, F32 u)
- {
- const F32 u2 = u * u;
- const T a0 = d - c - a + b;
- const T a1 = a - b - a0;
- const T a2 = c - a;
- const T a3 = b;
- return (a0 * u * u2 + a1 * u2 + a2 * u + a3);
- }
- /// Pack 4 color components to R10G10B10A2 SNORM format.
- inline U32 packColorToR10G10B10A2SNorm(F32 r, F32 g, F32 b, F32 a)
- {
- union SignedR10G10B10A10
- {
- struct
- {
- I32 m_x : 10;
- I32 m_y : 10;
- I32 m_z : 10;
- I32 m_w : 2;
- } m_unpacked;
- U32 m_packed;
- };
- #if ANKI_COMPILER_GCC_COMPATIBLE
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wconversion"
- #endif
- SignedR10G10B10A10 out;
- out.m_unpacked.m_x = I32(round(r * 511.0f));
- out.m_unpacked.m_y = I32(round(g * 511.0f));
- out.m_unpacked.m_z = I32(round(b * 511.0f));
- out.m_unpacked.m_w = I32(round(a * 1.0f));
- #if ANKI_COMPILER_GCC_COMPATIBLE
- # pragma GCC diagnostic pop
- #endif
- return out.m_packed;
- }
- template<typename TVec4>
- inline U32 packSnorm4x8(const TVec4& v)
- {
- union
- {
- I8 in[4];
- U32 out;
- } u;
- const TVec4 result = (v.clamp(-1.0f, 1.0f) * 127.0f).round();
- u.in[0] = I8(result[0]);
- u.in[1] = I8(result[1]);
- u.in[2] = I8(result[2]);
- u.in[3] = I8(result[3]);
- return u.out;
- }
- /// Compute the abs triangle area.
- template<typename TVec>
- inline F32 computeTriangleArea(const TVec& a, const TVec& b, const TVec& c)
- {
- const TVec ab = b - a;
- const TVec ac = c - a;
- const F32 area = ab.cross(ac).getLength() / 2.0f;
- return absolute(area);
- }
- /// @}
- } // end namespace anki
|