2017-10-02 23:24:00 +02:00
|
|
|
using System;
|
2018-03-01 08:51:35 +01:00
|
|
|
#if REAL_T_IS_DOUBLE
|
|
|
|
using real_t = System.Double;
|
|
|
|
#else
|
|
|
|
using real_t = System.Single;
|
|
|
|
#endif
|
|
|
|
|
2017-10-02 23:24:00 +02:00
|
|
|
namespace Godot
|
|
|
|
{
|
2018-04-07 13:54:07 +02:00
|
|
|
public static partial class Mathf
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-07 13:54:07 +02:00
|
|
|
// Define constants with Decimal precision and cast down to double or float.
|
2018-03-01 08:51:35 +01:00
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959
|
|
|
|
public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979
|
|
|
|
public const real_t Inf = real_t.PositiveInfinity;
|
|
|
|
public const real_t NaN = real_t.NaN;
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433
|
|
|
|
private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2019-10-29 14:44:41 +01:00
|
|
|
public static int Abs(int s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
return Math.Abs(s);
|
|
|
|
}
|
|
|
|
|
2019-10-29 14:44:41 +01:00
|
|
|
public static real_t Abs(real_t s)
|
2018-04-07 13:54:07 +02:00
|
|
|
{
|
|
|
|
return Math.Abs(s);
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Acos(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Acos(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Asin(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Asin(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Atan(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Atan(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-05-26 09:15:56 +02:00
|
|
|
public static real_t Atan2(real_t y, real_t x)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2019-05-26 09:15:56 +02:00
|
|
|
return (real_t)Math.Atan2(y, x);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static Vector2 Cartesian2Polar(real_t x, real_t y)
|
|
|
|
{
|
|
|
|
return new Vector2(Sqrt(x * x + y * y), Atan2(y, x));
|
|
|
|
}
|
2017-10-13 01:15:45 +02:00
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Ceil(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Ceiling(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static int Clamp(int value, int min, int max)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-07 13:54:07 +02:00
|
|
|
return value < min ? min : value > max ? max : value;
|
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static real_t Clamp(real_t value, real_t min, real_t max)
|
|
|
|
{
|
|
|
|
return value < min ? min : value > max ? max : value;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Cos(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Cos(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Cosh(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Cosh(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Deg2Rad(real_t deg)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
return deg * Deg2RadConst;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Ease(real_t s, real_t curve)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
if (s < 0f)
|
|
|
|
{
|
|
|
|
s = 0f;
|
|
|
|
}
|
|
|
|
else if (s > 1.0f)
|
|
|
|
{
|
|
|
|
s = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curve > 0f)
|
|
|
|
{
|
|
|
|
if (curve < 1.0f)
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
return 1.0f - Pow(1.0f - s, 1.0f / curve);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 23:32:19 +01:00
|
|
|
return Pow(s, curve);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
2018-04-08 05:28:24 +02:00
|
|
|
|
|
|
|
if (curve < 0f)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
if (s < 0.5f)
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
return Pow(s * 2.0f, -curve) * 0.5f;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 23:32:19 +01:00
|
|
|
return (1.0f - Pow(1.0f - (s - 0.5f) * 2.0f, -curve)) * 0.5f + 0.5f;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0f;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Exp(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Exp(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Floor(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Floor(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static real_t InverseLerp(real_t from, real_t to, real_t weight)
|
|
|
|
{
|
2018-06-25 00:52:17 +02:00
|
|
|
return (weight - from) / (to - from);
|
2018-04-07 13:54:07 +02:00
|
|
|
}
|
|
|
|
|
2019-04-02 00:13:38 +02:00
|
|
|
public static bool IsEqualApprox(real_t a, real_t b)
|
|
|
|
{
|
2019-09-01 19:57:04 +02:00
|
|
|
// Check for exact equality first, required to handle "infinity" values.
|
2019-10-29 14:44:41 +01:00
|
|
|
if (a == b)
|
|
|
|
{
|
2019-09-01 19:57:04 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Then check for approximate equality.
|
2019-04-02 00:13:38 +02:00
|
|
|
real_t tolerance = Epsilon * Abs(a);
|
2019-10-29 14:44:41 +01:00
|
|
|
if (tolerance < Epsilon)
|
|
|
|
{
|
2019-04-02 00:13:38 +02:00
|
|
|
tolerance = Epsilon;
|
|
|
|
}
|
|
|
|
return Abs(a - b) < tolerance;
|
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static bool IsInf(real_t s)
|
|
|
|
{
|
|
|
|
return real_t.IsInfinity(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool IsNaN(real_t s)
|
|
|
|
{
|
|
|
|
return real_t.IsNaN(s);
|
|
|
|
}
|
|
|
|
|
2019-04-02 00:13:38 +02:00
|
|
|
public static bool IsZeroApprox(real_t s)
|
|
|
|
{
|
|
|
|
return Abs(s) < Epsilon;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Lerp(real_t from, real_t to, real_t weight)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-06-25 00:52:17 +02:00
|
|
|
return from + (to - from) * weight;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-10-29 14:44:41 +01:00
|
|
|
public static real_t LerpAngle(real_t from, real_t to, real_t weight)
|
|
|
|
{
|
2019-07-14 06:30:45 +02:00
|
|
|
real_t difference = (to - from) % Mathf.Tau;
|
|
|
|
real_t distance = ((2 * difference) % Mathf.Tau) - difference;
|
|
|
|
return from + distance * weight;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Log(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Log(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 23:32:19 +01:00
|
|
|
public static int Max(int a, int b)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return a > b ? a : b;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Max(real_t a, real_t b)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return a > b ? a : b;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 23:32:19 +01:00
|
|
|
public static int Min(int a, int b)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return a < b ? a : b;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Min(real_t a, real_t b)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return a < b ? a : b;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-04-07 23:40:56 +02:00
|
|
|
public static real_t MoveToward(real_t from, real_t to, real_t delta)
|
|
|
|
{
|
|
|
|
return Abs(to - from) <= delta ? to : from + Sign(to - from) * delta;
|
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static int NearestPo2(int value)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-07 13:54:07 +02:00
|
|
|
value--;
|
|
|
|
value |= value >> 1;
|
|
|
|
value |= value >> 2;
|
|
|
|
value |= value >> 4;
|
|
|
|
value |= value >> 8;
|
|
|
|
value |= value >> 16;
|
|
|
|
value++;
|
|
|
|
return value;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static Vector2 Polar2Cartesian(real_t r, real_t th)
|
|
|
|
{
|
|
|
|
return new Vector2(r * Cos(th), r * Sin(th));
|
|
|
|
}
|
2017-10-13 01:15:45 +02:00
|
|
|
|
2018-06-10 10:36:49 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
|
|
|
|
/// </summary>
|
2019-10-29 14:44:41 +01:00
|
|
|
public static int PosMod(int a, int b)
|
2018-06-10 10:36:49 +02:00
|
|
|
{
|
2019-10-29 14:44:41 +01:00
|
|
|
int c = a % b;
|
2018-11-20 11:14:07 +01:00
|
|
|
if ((c < 0 && b > 0) || (c > 0 && b < 0))
|
2018-06-10 10:36:49 +02:00
|
|
|
{
|
|
|
|
c += b;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
|
|
|
|
/// </summary>
|
2019-10-29 14:44:41 +01:00
|
|
|
public static real_t PosMod(real_t a, real_t b)
|
2018-06-10 10:36:49 +02:00
|
|
|
{
|
2019-10-29 14:44:41 +01:00
|
|
|
real_t c = a % b;
|
2018-11-20 11:14:07 +01:00
|
|
|
if ((c < 0 && b > 0) || (c > 0 && b < 0))
|
2018-06-10 10:36:49 +02:00
|
|
|
{
|
|
|
|
c += b;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Pow(real_t x, real_t y)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Pow(x, y);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Rad2Deg(real_t rad)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
return rad * Rad2DegConst;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Round(real_t s)
|
|
|
|
{
|
|
|
|
return (real_t)Math.Round(s);
|
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static int Sign(int s)
|
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return s < 0 ? -1 : 1;
|
2018-04-07 13:54:07 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Sign(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-04-08 05:39:35 +02:00
|
|
|
return s < 0f ? -1f : 1f;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Sin(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Sin(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Sinh(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Sinh(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-03-19 12:39:43 +01:00
|
|
|
public static real_t SmoothStep(real_t from, real_t to, real_t weight)
|
|
|
|
{
|
|
|
|
if (IsEqualApprox(from, to))
|
|
|
|
{
|
|
|
|
return from;
|
|
|
|
}
|
|
|
|
real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
|
|
|
|
return x * x * (3 - 2 * x);
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Sqrt(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Sqrt(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2019-10-29 14:44:41 +01:00
|
|
|
public static int StepDecimals(real_t step)
|
|
|
|
{
|
|
|
|
double[] sd = new double[] {
|
|
|
|
0.9999,
|
|
|
|
0.09999,
|
|
|
|
0.009999,
|
|
|
|
0.0009999,
|
|
|
|
0.00009999,
|
|
|
|
0.000009999,
|
|
|
|
0.0000009999,
|
|
|
|
0.00000009999,
|
|
|
|
0.000000009999,
|
|
|
|
};
|
|
|
|
double abs = Mathf.Abs(step);
|
|
|
|
double decs = abs - (int)abs; // Strip away integer part
|
|
|
|
for (int i = 0; i < sd.Length; i++)
|
|
|
|
{
|
|
|
|
if (decs >= sd[i])
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Stepify(real_t s, real_t step)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
|
|
|
if (step != 0f)
|
|
|
|
{
|
2017-11-21 23:32:19 +01:00
|
|
|
s = Floor(s / step + 0.5f) * step;
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Tan(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Tan(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
|
2018-03-01 08:51:35 +01:00
|
|
|
public static real_t Tanh(real_t s)
|
2017-10-02 23:24:00 +02:00
|
|
|
{
|
2018-03-01 08:51:35 +01:00
|
|
|
return (real_t)Math.Tanh(s);
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
2018-03-26 13:33:09 +02:00
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static int Wrap(int value, int min, int max)
|
2018-03-26 13:33:09 +02:00
|
|
|
{
|
2019-08-05 05:31:26 +02:00
|
|
|
int range = max - min;
|
|
|
|
return range == 0 ? min : min + ((value - min) % range + range) % range;
|
2018-03-26 13:33:09 +02:00
|
|
|
}
|
|
|
|
|
2018-04-07 13:54:07 +02:00
|
|
|
public static real_t Wrap(real_t value, real_t min, real_t max)
|
2018-03-26 13:33:09 +02:00
|
|
|
{
|
2019-08-05 05:31:26 +02:00
|
|
|
real_t range = max - min;
|
|
|
|
return IsZeroApprox(range) ? min : min + ((value - min) % range + range) % range;
|
2018-03-26 13:33:09 +02:00
|
|
|
}
|
2017-10-02 23:24:00 +02:00
|
|
|
}
|
|
|
|
}
|