djcev.com

//

Git Repos / fte_dogmode / qc / math.qc

Last update to this file was on 2024-04-12 at 18:56.

Show math.qc

//==============================================================================
// 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; // available as an engine builtin
float(float x) sign;
float(float value, float minValue, float maxValue) wrap;

float(float a, float b, float mix) lerp;
vector(vector a, vector b, float mix) lerp_vector;
float(float a, float b, float mix) lerp_hermite;
vector(vector a, vector b, float mix) lerp_vector_hermite;

float(float anga, float angb) angledif;
float(vector ang, vector base_ang, vector offset) is_in_angle;

vector(vector ang) normalize_angles;
vector(vector ang) normalize_angles180;

float() crandom;
float(float v) anglemod;

float(float theta) preach_tan;
float(float y, float x) preach_atan2;
float(float theta, vector source, vector dest) preach_iterate_elevation;

//------------------------------------------------------------------------------

//----------------------------------------------------------------------
// 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
//----------------------------------------------------------------------
/*
float(float a, float n) mod =
{
return a - (n * floor(a / n));
};
*/

//----------------------------------------------------------------------
// 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;
};

//----------------------------------------------------------------------
// 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) lerp_vector =
{
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) lerp_hermite =
{
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) lerp_vector_hermite =
{
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 =
{
local float dif;
dif = fabs (anga - angb);
if (dif > 180)
dif = 360 - dif;
return dif;
};

//----------------------------------------------------------------------
float(vector ang, vector base_ang, vector offset) is_in_angle =
{
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) normalize_angles =
{
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;

return ang;
};

//----------------------------------------------------------------------
// normalizes an angle vector to the -180/+179 range
//----------------------------------------------------------------------
vector(vector ang) normalize_angles180 =
{
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;

return ang;
};

//======================================================================
// Below are various math functions copied from elsewhere in the program
// (i.e., the following were not originally in math.qc) -- CEV
//======================================================================

//----------------------------------------------------------------------
// returns -1 to 1 (I think); was in weapons.qc -- CEV
//----------------------------------------------------------------------
float() crandom =
{
return 2 * (random() - 0.5);
};

//----------------------------------------------------------------------
// was in ai.qc -- CEV
//----------------------------------------------------------------------
float(float v) anglemod =
{
while (v >= 360)
v = v - 360;
while (v < 0)
v = v + 360;
return v;
};

//----------------------------------------------------------------------
// the next three functions were in ogre.qc -- CEV
//----------------------------------------------------------------------

//////////////////////////////////////////////////////////////
// start Preach Ogre Marksman tutorial here -- dumptruck_ds //
//////////////////////////////////////////////////////////////

// uses QuakeC builtins to calculate tan of angle
// WARNING: uses makevectors! This overwrites the v_forward... globals
float(float theta) preach_tan =
{
local vector ang = '0 0 0'; // temp used to calculate trig values

// assign theta to the yaw to simplify reasoning
ang_y = theta;
makevectors (ang);
return v_forward_y / v_forward_x;
};

// inverse tan function
// takes two parameters, numerator and denominator
// this copes better with denominator 0 and gets quadrant correct
float(float y, float x) preach_atan2 =
{
// temporary used to calculate trig values
local vector ang;
ang = '0 0 0';
ang_x = x;
ang_y = y;
return vectoyaw (ang);
};

float(float theta, vector source, vector dest) preach_iterate_elevation =
{
// constants in the equation to be solved
local float a, b, c;
// displacement we wish the projectile to travel
local vector ofs;
// horizontal and vertical components of ofs
local float y, z;
// trig values of the angle theta
local float tan_theta;

// calculate how far we are firing
ofs = dest - source;
z = ofs_z;
ofs_z = 0;
y = vlen (ofs);

// find the coefficients of the quadratic in tan(theta)
a = 0.5 * world_gravity * y * y / (GRENADE_SPEED * GRENADE_SPEED);
b = -y;
c = a + z;

// check if the destination is too far to reach
if (b * b < 4 * a * c)
return OGRE_DEFAULT_ELEVATION;

// calculate the tan value of the given theta
tan_theta = preach_tan (theta);

// reuse ang to create the improved firing direction
theta = preach_atan2 (a * tan_theta * tan_theta - c,
2 * a * tan_theta + b);

// constrain the values to stop anything too mad happening
while (theta > 90)
theta = theta - 180;
return theta;
};
// end Preach tutorial

Return to the top of this page or return to the overview of this repo.

Log math.qc

Return to the top of this page or return to the overview of this repo.