Add approach functions, add an `approach` function to Lua mathlib

Easy increment/decrement :)
This commit is contained in:
yamamama 2026-03-15 14:21:50 -04:00
parent 15079bd993
commit 9a39b24d28
3 changed files with 239 additions and 0 deletions

View file

@ -190,6 +190,16 @@ static int lib_coloropposite(lua_State *L)
return 2;
}
static int lib_approach(lua_State* L)
{
lua_pushinteger(L,
ApproachFixed((fixed_t)luaL_checkinteger(L, 1),
(fixed_t)luaL_checkinteger(L, 2),
(fixed_t)luaL_checkinteger(L, 3),
(fixed_t)luaL_checkinteger(L, 4)));
return 1;
}
static luaL_Reg lib_math[] = {
{"abs", lib_abs},
{"min", lib_min},
@ -225,6 +235,7 @@ static luaL_Reg lib_math[] = {
{"GetSecSpecial", lib_getsecspecial},
{"All7Emeralds", lib_all7emeralds},
{"ColorOpposite", lib_coloropposite},
{"approach", lib_approach},
{NULL, NULL}
};

View file

@ -1129,6 +1129,188 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
#undef M
}
// "Approach" functions taken from or based on the (decompiled) SM64 implementation
// https://github.com/n64decomp/sm64/blob/master/src/engine/math_util.c
/** \brief Returns the INT32 value 'current' after it tries to approach target, going up at most
'inc' and going down at most 'dec'.
*
* If target is close to the max or min of INT32, then it's possible to overflow past it without
stopping.
\param current (INT32) current value
\param target (INT32) target value
\param inc (INT32) value to increment by
\param dec (INT32) value to decrement by
\return (INT32) current value after incrementing/decrementing
*/
INT32 ApproachINT32(INT32 current, INT32 target, INT32 inc, INT32 dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
/** \brief Returns the unsigned INT32 value ``current`` after it tries to approach target, going
up at most ``inc`` and going down at most ``dec``.
*
* If target is close to the max or min of UINT32, then it's possible to overflow past it without
stopping.
\param current (UINT32) current value
\param target (UINT32) target value
\param inc (UINT32) value to increment by
\param dec (UINT32) value to decrement by
\return (UINT32) current value after incrementing/decrementing
*/
UINT32 ApproachUINT32(UINT32 current, UINT32 target, UINT32 inc, UINT32 dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
/** \brief Returns the fixed-point value 'current' after it tries to approach target, going up at
most 'inc' and going down at most 'dec'.
*
* If target is close to the max or min of fixed_t, then it's possible to overflow past it without
stopping.
\param current (fixed_t) current value
\param target (fixed_t) target value
\param inc (fixed_t) value to increment by
\param dec (fixed_t) value to decrement by
\return (fixed_t) current value after incrementing/decrementing
*/
fixed_t ApproachFixed(fixed_t current, fixed_t target, fixed_t inc, fixed_t dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
/** \brief Returns the floating-point value 'current' after it tries to approach target, going up at
most 'inc' and going down at most 'dec'.
\param current (float) current value
\param target (float) target value
\param inc (float) value to increment by
\param dec (float) value to decrement by
\return (float) current value after incrementing/decrementing
*/
float ApproachFloat(float current, float target, float inc, float dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
/** \brief Returns the double-precision floating-point value 'current' after it tries to approach
target, going up at most 'inc' and going down at most 'dec'.
\param current (double) current value
\param target (double) target value
\param inc (double) value to increment by
\param dec (double) value to decrement by
\return (double) current value after incrementing/decrementing
*/
double ApproachDouble(double current, double target, double inc, double dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
#ifdef M_TESTCASE
//#define MULDIV_TEST
#define SQRT_TEST

View file

@ -462,6 +462,52 @@ void FM_MultMatrixEx(const matrix_t *m1, const matrix_t *m2, matrix_t *dest);
void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
//
// Approach functions, see m_fixed.c for details
//
INT32 ApproachINT32(INT32 current, INT32 target, INT32 inc, INT32 dec);
UINT32 ApproachUINT32(UINT32 current, UINT32 target, UINT32 inc, UINT32 dec);
fixed_t ApproachFixed(fixed_t current, fixed_t target, fixed_t inc, fixed_t dec);
float ApproachFloat(float current, float target, float inc, float dec);
double ApproachDouble(double current, double target, double inc, double dec);
/** \brief Returns the INT32 value ``current`` after it tries to approach ``target``, going up
or down at most ``delta``.
*
* If ``target`` is close to the max or min of INT32, then it's possible to overflow past it
without stopping.
\param current (INT32) current value
\param target (INT32) target value
\param delta (INT32) value to increment/decrement by
\return (INT32) current value after incrementing/decrementing
*/
#define ApproachOneWayINT32(current, target, delta) (ApproachINT32(current, target, delta, delta))
/** \brief Returns the unsigned INT32 value ``current`` after it tries to approach ``target``,
going up or down at most ``delta``.
*
* If ``target`` is close to the max or min of UINT32, then it's possible to overflow past it
without stopping.
\param current (UINT32) current value
\param target (UINT32) target value
\param delta (UINT32) value to increment/decrement by
\return (UINT32) current value after incrementing/decrementing
*/
#define ApproachOneWayUINT32(current, target, delta) (ApproachUINT32(current, target, delta, delta))
#define ApproachOneWayFixed(current, target, delta) (ApproachFixed(current, target, delta, delta))
#define ApproachOneWayFloat(current, target, delta) (ApproachFloat(current, target, delta, delta))
#define ApproachOneWayDouble(current, target, delta) (ApproachDouble(current, target, delta, delta))
#ifdef __cplusplus
} // extern "C"
#endif