djcev.com

//

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.