2023-11-07 04:04:22 -05:00
|
|
|
package funkin.util;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Utilities for performing mathematical operations.
|
|
|
|
*/
|
|
|
|
class MathUtil
|
|
|
|
{
|
2024-02-16 22:13:51 -05:00
|
|
|
/**
|
|
|
|
* Euler's constant and the base of the natural logarithm.
|
|
|
|
* Math.E is not a constant in Haxe, so we'll just define it ourselves.
|
|
|
|
*/
|
|
|
|
public static final E:Float = 2.71828182845904523536;
|
2024-02-15 14:17:44 -05:00
|
|
|
|
2023-11-07 04:04:22 -05:00
|
|
|
/**
|
|
|
|
* Perform linear interpolation between the base and the target, based on the current framerate.
|
2024-03-16 22:20:22 -04:00
|
|
|
* @param base The starting value, when `progress <= 0`.
|
|
|
|
* @param target The ending value, when `progress >= 1`.
|
|
|
|
* @param ratio Value used to interpolate between `base` and `target`.
|
|
|
|
*
|
|
|
|
* @return The interpolated value.
|
2023-11-07 04:04:22 -05:00
|
|
|
*/
|
2024-03-23 17:50:48 -04:00
|
|
|
@:deprecated('Use smoothLerp instead')
|
2023-11-07 04:04:22 -05:00
|
|
|
public static function coolLerp(base:Float, target:Float, ratio:Float):Float
|
|
|
|
{
|
|
|
|
return base + cameraLerp(ratio) * (target - base);
|
|
|
|
}
|
|
|
|
|
2024-03-16 22:20:22 -04:00
|
|
|
/**
|
|
|
|
* Perform linear interpolation based on the current framerate.
|
|
|
|
* @param lerp Value used to interpolate between `base` and `target`.
|
|
|
|
*
|
|
|
|
* @return The interpolated value.
|
|
|
|
*/
|
|
|
|
@:deprecated('Use smoothLerp instead')
|
2023-11-07 04:04:22 -05:00
|
|
|
public static function cameraLerp(lerp:Float):Float
|
|
|
|
{
|
|
|
|
return lerp * (FlxG.elapsed / (1 / 60));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the logarithm of a value with a given base.
|
|
|
|
* @param base The base of the logarithm.
|
|
|
|
* @param value The value to get the logarithm of.
|
|
|
|
* @return `log_base(value)`
|
|
|
|
*/
|
2024-03-16 22:20:22 -04:00
|
|
|
public static function logBase(base:Float, value:Float):Float
|
2023-11-07 04:04:22 -05:00
|
|
|
{
|
|
|
|
return Math.log(value) / Math.log(base);
|
|
|
|
}
|
2024-02-15 14:17:44 -05:00
|
|
|
|
|
|
|
/**
|
2024-03-16 22:20:22 -04:00
|
|
|
* Get the base-2 logarithm of a value.
|
|
|
|
* @param x value
|
|
|
|
* @return `2^x`
|
2024-02-15 14:17:44 -05:00
|
|
|
*/
|
2024-03-16 22:20:22 -04:00
|
|
|
public static function exp2(x:Float):Float
|
2024-02-15 14:17:44 -05:00
|
|
|
{
|
|
|
|
return Math.pow(2, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Linearly interpolate between two values.
|
2024-03-16 22:20:22 -04:00
|
|
|
*
|
2024-02-15 14:17:44 -05:00
|
|
|
* @param base The starting value, when `progress <= 0`.
|
|
|
|
* @param target The ending value, when `progress >= 1`.
|
|
|
|
* @param progress Value used to interpolate between `base` and `target`.
|
2024-03-16 22:20:22 -04:00
|
|
|
* @return The interpolated value.
|
2024-02-15 14:17:44 -05:00
|
|
|
*/
|
2024-03-16 22:20:22 -04:00
|
|
|
public static function lerp(base:Float, target:Float, progress:Float):Float
|
2024-02-15 14:17:44 -05:00
|
|
|
{
|
|
|
|
return base + progress * (target - base);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform a framerate-independent linear interpolation between the base value and the target.
|
|
|
|
* @param current The current value.
|
|
|
|
* @param target The target value.
|
|
|
|
* @param elapsed The time elapsed since the last frame.
|
|
|
|
* @param duration The total duration of the interpolation. Nominal duration until remaining distance is less than `precision`.
|
|
|
|
* @param precision The target precision of the interpolation. Defaults to 1% of distance remaining.
|
|
|
|
* @see https://twitter.com/FreyaHolmer/status/1757918211679650262
|
2024-03-16 22:20:22 -04:00
|
|
|
*
|
2024-03-20 23:06:32 -04:00
|
|
|
* @return A value between the current value and the target value.
|
2024-02-15 14:17:44 -05:00
|
|
|
*/
|
|
|
|
public static function smoothLerp(current:Float, target:Float, elapsed:Float, duration:Float, precision:Float = 1 / 100):Float
|
|
|
|
{
|
2024-03-16 22:20:22 -04:00
|
|
|
// An alternative algorithm which uses a separate half-life value:
|
2024-02-15 14:17:44 -05:00
|
|
|
// var halfLife:Float = -duration / logBase(2, precision);
|
|
|
|
// lerp(current, target, 1 - exp2(-elapsed / halfLife));
|
|
|
|
|
2024-03-20 23:06:32 -04:00
|
|
|
if (current == target) return target;
|
|
|
|
|
|
|
|
var result:Float = lerp(current, target, 1 - Math.pow(precision, elapsed / duration));
|
|
|
|
|
|
|
|
// TODO: Is there a better way to ensure a lerp which actually reaches the target?
|
|
|
|
// Research a framerate-independent PID lerp.
|
|
|
|
if (Math.abs(result - target) < (precision * target)) result = target;
|
|
|
|
|
|
|
|
return result;
|
2024-02-15 14:17:44 -05:00
|
|
|
}
|
2023-11-07 04:04:22 -05:00
|
|
|
}
|