spingle/source/mathlib.c

327 lines
8.5 KiB
C
Raw Normal View History

2019-11-24 20:45:15 -08:00
/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2007-2008 Kristian Duske
Copyright (C) 2010-2014 QuakeSpasm developers
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// mathlib.c -- math primitives
2019-12-02 07:07:37 -08:00
#include "q_defs.h"
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
vec3_t vec3_origin = {0, 0, 0};
2019-11-24 20:45:15 -08:00
/*-----------------------------------------------------------------*/
2019-12-02 04:24:20 -08:00
#define DEG2RAD( a ) ( (a) * PI_DIV_180 ) //johnfitz
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
void ProjectPointOnPlane(vec3_t dst, const vec3_t p, const vec3_t normal)
2019-11-24 20:45:15 -08:00
{
float d;
vec3_t n;
float inv_denom;
2019-11-25 17:40:18 -08:00
inv_denom = 1.0F / DotProduct(normal, normal);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
d = DotProduct(normal, p) * inv_denom;
2019-11-24 20:45:15 -08:00
n[0] = normal[0] * inv_denom;
n[1] = normal[1] * inv_denom;
n[2] = normal[2] * inv_denom;
dst[0] = p[0] - d * n[0];
dst[1] = p[1] - d * n[1];
dst[2] = p[2] - d * n[2];
}
/*
** assumes "src" is normalized
*/
2019-11-25 17:40:18 -08:00
void PerpendicularVector(vec3_t dst, const vec3_t src)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t pos;
2019-11-25 16:49:58 -08:00
int32_t i;
2019-11-24 20:45:15 -08:00
float minelem = 1.0F;
vec3_t tempvec;
/*
** find the smallest magnitude axially aligned vector
*/
2019-11-25 17:40:18 -08:00
for(pos = 0, i = 0; i < 3; i++)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(fabs(src[i]) < minelem)
2019-11-24 20:45:15 -08:00
{
pos = i;
2019-11-25 17:40:18 -08:00
minelem = fabs(src[i]);
2019-11-24 20:45:15 -08:00
}
}
tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
tempvec[pos] = 1.0F;
/*
** project the point onto the plane defined by src
*/
2019-11-25 17:40:18 -08:00
ProjectPointOnPlane(dst, tempvec, src);
2019-11-24 20:45:15 -08:00
/*
** normalize the result
*/
2019-11-25 17:40:18 -08:00
VectorNormalize(dst);
2019-11-24 20:45:15 -08:00
}
//johnfitz -- removed RotatePointAroundVector() becuase it's no longer used and my compiler fucked it up anyway
/*-----------------------------------------------------------------*/
2019-11-25 17:40:18 -08:00
float anglemod(float a)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
a = (360.0 / 65536) * ((int32_t)(a * (65536 / 360.0)) & 65535);
2019-11-24 20:45:15 -08:00
return a;
}
/*
==================
BoxOnPlaneSide
Returns 1, 2, or 1 + 2
==================
*/
2019-11-25 17:40:18 -08:00
int32_t BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, mplane_t *p)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float dist1, dist2;
int32_t sides;
2019-11-24 20:45:15 -08:00
// general case
2019-11-25 17:40:18 -08:00
switch(p->signbits)
2019-11-24 20:45:15 -08:00
{
case 0:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
2019-11-24 20:45:15 -08:00
break;
case 1:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
2019-11-24 20:45:15 -08:00
break;
case 2:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
2019-11-24 20:45:15 -08:00
break;
case 3:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
2019-11-24 20:45:15 -08:00
break;
case 4:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
2019-11-24 20:45:15 -08:00
break;
case 5:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2];
2019-11-24 20:45:15 -08:00
break;
case 6:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
2019-11-24 20:45:15 -08:00
break;
case 7:
2019-11-25 17:40:18 -08:00
dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2];
dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2];
2019-11-24 20:45:15 -08:00
break;
default:
2019-11-25 17:40:18 -08:00
dist1 = dist2 = 0; // shut up compiler
Sys_Error("BoxOnPlaneSide: Bad signbits");
2019-11-24 20:45:15 -08:00
break;
}
sides = 0;
2019-11-25 17:40:18 -08:00
if(dist1 >= p->dist)
2019-11-24 20:45:15 -08:00
sides = 1;
2019-11-25 17:40:18 -08:00
if(dist2 < p->dist)
2019-11-24 20:45:15 -08:00
sides |= 2;
2019-12-02 04:24:20 -08:00
#if defined(PARANOID)
2019-11-25 17:40:18 -08:00
if(sides == 0)
Sys_Error("BoxOnPlaneSide: sides==0");
2019-11-24 20:45:15 -08:00
#endif
return sides;
}
2019-11-25 17:40:18 -08:00
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float angle;
float sr, sp, sy, cr, cp, cy;
2019-11-24 20:45:15 -08:00
2019-12-02 04:24:20 -08:00
angle = angles[YAW] * (PI * 2 / 360);
2019-11-24 20:45:15 -08:00
sy = sin(angle);
cy = cos(angle);
2019-12-02 04:24:20 -08:00
angle = angles[PITCH] * (PI * 2 / 360);
2019-11-24 20:45:15 -08:00
sp = sin(angle);
cp = cos(angle);
2019-12-02 04:24:20 -08:00
angle = angles[ROLL] * (PI * 2 / 360);
2019-11-24 20:45:15 -08:00
sr = sin(angle);
cr = cos(angle);
2019-11-25 17:40:18 -08:00
forward[0] = cp * cy;
forward[1] = cp * sy;
2019-11-24 20:45:15 -08:00
forward[2] = -sp;
2019-11-25 17:40:18 -08:00
right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
right[2] = -1 * sr * cp;
up[0] = (cr * sp * cy + -sr * -sy);
up[1] = (cr * sp * sy + -sr * cy);
up[2] = cr * cp;
2019-11-24 20:45:15 -08:00
}
/*
================
R_ConcatRotations
================
*/
2019-11-25 17:40:18 -08:00
void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3])
2019-11-24 20:45:15 -08:00
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
}
/*
================
R_ConcatTransforms
================
*/
2019-11-25 17:40:18 -08:00
void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4])
2019-11-24 20:45:15 -08:00
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
2019-11-25 17:40:18 -08:00
in1[0][2] * in2[2][3] + in1[0][3];
2019-11-24 20:45:15 -08:00
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
2019-11-25 17:40:18 -08:00
in1[1][2] * in2[2][3] + in1[1][3];
2019-11-24 20:45:15 -08:00
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][0];
2019-11-24 20:45:15 -08:00
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][1];
2019-11-24 20:45:15 -08:00
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][2];
2019-11-24 20:45:15 -08:00
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
2019-11-25 17:40:18 -08:00
in1[2][2] * in2[2][3] + in1[2][3];
2019-11-24 20:45:15 -08:00
}
/*
===================
FloorDivMod
Returns mathematically correct (floor-based) quotient and remainder for
numer and denom, both of which should contain no fractional part. The
quotient must fit in 32 bits.
====================
*/
2019-11-25 17:40:18 -08:00
void FloorDivMod(double numer, double denom, int32_t *quotient,
int32_t *rem)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
int32_t q, r;
double x;
2019-11-24 20:45:15 -08:00
2019-12-02 04:24:20 -08:00
#if !defined(PARANOID)
2019-11-25 17:40:18 -08:00
if(denom <= 0.0)
Sys_Error("FloorDivMod: bad denominator %f\n", denom);
2019-11-24 20:45:15 -08:00
// if ((floor(numer) != numer) || (floor(denom) != denom))
// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
// numer, denom);
#endif
2019-11-25 17:40:18 -08:00
if(numer >= 0.0)
2019-11-24 20:45:15 -08:00
{
x = floor(numer / denom);
2019-11-25 16:49:58 -08:00
q = (int32_t)x;
r = (int32_t)floor(numer - (x * denom));
2019-11-24 20:45:15 -08:00
}
else
{
2019-11-25 17:40:18 -08:00
//
// perform operations with positive values, and fix mod to make floor-based
//
2019-11-24 20:45:15 -08:00
x = floor(-numer / denom);
2019-11-25 16:49:58 -08:00
q = -(int32_t)x;
r = (int32_t)floor(-numer - (x * denom));
2019-11-25 17:40:18 -08:00
if(r != 0)
2019-11-24 20:45:15 -08:00
{
q--;
2019-11-25 16:49:58 -08:00
r = (int32_t)denom - r;
2019-11-24 20:45:15 -08:00
}
}
*quotient = q;
*rem = r;
}
/*
===================
GreatestCommonDivisor
====================
*/
2019-11-25 17:40:18 -08:00
int32_t GreatestCommonDivisor(int32_t i1, int32_t i2)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(i1 > i2)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(i2 == 0)
2019-11-24 20:45:15 -08:00
return (i1);
2019-11-25 17:40:18 -08:00
return GreatestCommonDivisor(i2, i1 % i2);
2019-11-24 20:45:15 -08:00
}
else
{
2019-11-25 17:40:18 -08:00
if(i1 == 0)
2019-11-24 20:45:15 -08:00
return (i2);
2019-11-25 17:40:18 -08:00
return GreatestCommonDivisor(i1, i2 % i1);
2019-11-24 20:45:15 -08:00
}
}