quakec/source/server/utilities/math.qc

234 lines
No EOL
4.3 KiB
C++

/*
* math.qc
*
* Author: Joshua Skelton joshua.skelton@gmail.com
*
* A collection of helpful math functions.
*/
// Forward declarations
float(float value, float minValue, float maxValue) clamp;
float(float a, float b) mod;
float(float x) sign;
float(float value, float minValue, float maxValue) wrap;
/*
* clamp
*
* Limits the given value to the given range.
*
* value: A number
*
* minValue: The minimum value of the range
*
* maxValue: The maximum value of the range
*
* Returns: A number within the given range.
*/
float(float value, float minValue, float maxValue) clamp = {
if (value < minValue) {
return minValue;
}
else if (value > maxValue) {
return maxValue;
}
return value;
};
/*
* mod
*
* Returns the remainder after the division of a by n
*
* a: The dividend
*
* b: The divisor
*
* Returns: The remainder of a divided by n
*/
#ifndef FTE
float(float a, float n) mod = {
return a - (n * floor(a / n));
};
#endif // FTE
/*
* sign
*
* Returns an indication of the sign of the given number.
*
* x: A number
*
* Returns: -1 if x < 0, 0 if x == 0, 1 if x > 0.
*/
float(float x) sign = {
if (x > 0) {
return 1;
}
else if (x < 0) {
return -1;
}
return 0;
};
float exp(float x) {
float result = 1;
float term = 1;
for (float i = 1; i < 50; i++) {
term *= x / i;
result += term;
}
return result;
}
/*
* wrap
*
* Limits the given value to the given range and will wrap the value to the
* the other end of the range if exceeded.
*
* value: A number
*
* minValue: The minimum value of the range
*
* maxValue: The maximum value of the range
*
* Returns: A number within the given range.
*/
float(float value, float minValue, float maxValue) wrap = {
local float range = maxValue - minValue;
return mod(value - minValue, range + 1) + minValue;
};
float(float a, float b, float mix) lerp =
{
if (mix <= 0) return a;
if (mix >= 1) return b;
return (b * mix + a * ( 1 - mix ) );
}
vector(vector a, vector b, float mix) lerpVector =
{
if (mix <= 0) return a;
if (mix >= 1) return b;
return (b * mix + a * ( 1 - mix ) );
}
// for a relaxing lerp: hermite lerp.
float(float a, float b, float mix) lerpHermite =
{
if (mix <= 0) return a;
if (mix >= 1) return b;
local float h01;
h01 = mix * mix;
h01 *= 3 - 2 * mix;
return (b * h01 + a * ( 1 - h01 ) );
}
vector(vector a, vector b, float mix) lerpVectorHermite =
{
if (mix <= 0) return a;
if (mix >= 1) return b;
local float h01;
h01 = mix * mix;
h01 *= 3 - 2 * mix;
return (b * h01 + a * ( 1 - h01 ) );
}
float(float anga, float angb) angledif =
{
float dif;
dif = fabs(anga - angb);
if (dif > 180)
dif = 360 - dif;
return dif;
}
float(vector ang, vector base_ang, vector offset) isInAngle = {
if (angledif(ang_x, base_ang_x) > offset_x || angledif(ang_y, base_ang_y) > offset_y)
return FALSE;
else
return TRUE;
};
// normalizes an angle vector to the 0/+359 range
vector(vector ang) normalizeAngles = {
ang_x = ang_x - floor(ang_x/360) * 360;
ang_y = ang_y - floor(ang_y/360) * 360;
ang_z = ang_z - floor(ang_z/360) * 360;
/*
while (ang_x > 360)
ang_x = ang_x - 360;
while (ang_x < 0)
ang_x = ang_x + 360;
while (ang_y > 360)
ang_y = ang_y - 360;
while (ang_y < 0)
ang_y = ang_y + 360;
while (ang_z > 360)
ang_z = ang_z - 360;
while (ang_z < 0)
ang_z = ang_z + 360;
*/
return ang;
};
// normalizes an angle vector to the -180/+179 range
vector(vector ang) normalizeAngles180 = {
ang_x = ((ang_x+180) - floor((ang_x+180)/360) * 360) - 180;
ang_y = ((ang_y+180) - floor((ang_y+180)/360) * 360) - 180;
ang_z = ((ang_z+180) - floor((ang_z+180)/360) * 360) - 180;
/*
while (ang_x > 180)
ang_x = ang_x - 360;
while (ang_x < -180)
ang_x = ang_x + 360;
while (ang_y > 180)
ang_y = ang_y - 360;
while (ang_y < -180)
ang_y = ang_y + 360;
while (ang_z > 180)
ang_z = ang_z - 360;
while (ang_z < -180)
ang_z = ang_z + 360;
*/
return ang;
};
float(float val) abs = {
if (val < 0) {
val *= -1;
}
return val;
};