Git Repos / fte_dogmode / qc / math.qc
Last update to this file was on 2024-06-26 at 03:47.
Show math.qc
//==============================================================================
// math.qc
// Author: Joshua Skelton joshua.skelton@gmail.com
// A collection of helpful math functions.
//==============================================================================
//======================================================================
// forward declarations
//======================================================================
#if defined(CSQC) || defined (SSQC)
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;
#endif
#if defined(CSQC) || defined (SSQC)
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;
#endif
#if defined(CSQC) || defined (SSQC)
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;
#endif
#ifdef SSQC
float(float theta) preach_tan;
float(float y, float x) preach_atan2;
float(float theta, float spd, vector source, vector dest)
preach_iterate_elevation;
#endif
//------------------------------------------------------------------------------
#if defined(CSQC) || defined (SSQC)
//----------------------------------------------------------------------
// 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;
};
#endif
#if defined(CSQC) || defined (SSQC)
//----------------------------------------------------------------------
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));
};
#endif
#if defined(CSQC) || defined (SSQC)
//----------------------------------------------------------------------
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;
};
#endif
//----------------------------------------------------------------------
// the next three functions were in ogre.qc -- CEV
//----------------------------------------------------------------------
//////////////////////////////////////////////////////////////
// start Preach Ogre Marksman tutorial here -- dumptruck_ds //
//////////////////////////////////////////////////////////////
#ifdef SSQC
// 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, float spd, 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 / (spd * spd);
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;
};
#endif
// end Preach tutorial
Return to the top of this page or return to the overview of this repo.
Log math.qc
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2024-06-26 | pmove fixes, GL now a faux tribolt, wall climbing | cev | +5 | -3 |
2024-06-15 | Major update, committing as-is, will have bugs | cev | +16 | -2 |
2024-04-12 | Moveable gibs, heads, some bugfixes | cev | +1 | -1 |
2024-04-05 | Player footsteps, shareware monsters, misc? | cev | +1 | -7 |
2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +36 | -10 |
2024-02-18 | Client/player, projectiles, entrypoints refactor | cev | +19 | -11 |
2024-01-31 | Class based monster refactor & start projectiles | cev | +95 | -4 |
2023-12-09 | Start OO / class-based refactor, work on items | cev | +3 | -3 |
2023-11-27 | Code reorg, minor movement changes, misc | cev | +144 | -166 |
2023-10-13 | New movement code based on SV_RunClientCommand | cev | +209 | -209 |
2023-10-13 | Rename "qc-server" dir to "qc" | cev | +209 |
Return to the top of this page or return to the overview of this repo.