mirror of
https://github.com/kevinbentley/Descent3.git
synced 2026-04-04 02:00:04 -04:00
279 lines
5.2 KiB
C++
279 lines
5.2 KiB
C++
/*
|
|
* $Logfile: /DescentIII/Main/fix/fix.cpp $
|
|
* $Revision: 6 $
|
|
* $Date: 4/22/99 8:29p $
|
|
* $Author: Kevin $
|
|
*
|
|
* Fixed-point math functions, including trig & float conversions
|
|
*
|
|
* $Log: /DescentIII/Main/fix/fix.cpp $
|
|
*
|
|
* 6 4/22/99 8:29p Kevin
|
|
* made psrand.h come after stdlib.h
|
|
*
|
|
* 5 4/21/99 11:05a Kevin
|
|
* new ps_rand and ps_srand to replace rand & srand
|
|
*
|
|
* 4 8/26/97 10:15a Jason
|
|
* corrected the FixCeil function
|
|
*
|
|
* 3 8/22/97 12:34p Jason
|
|
* added FixCeil and FixFloor
|
|
*
|
|
* 2 8/21/97 5:57p Samir
|
|
* Added initialization of random number generator.
|
|
*
|
|
* 7 2/27/97 4:47 PM Jeremy
|
|
* moved inline assembly language functions processor for
|
|
* fixmul/fixdiv/fixmuldiv into fixmac.h and fixwin32.h
|
|
*
|
|
* 6 2/12/97 5:35p Jason
|
|
* fixed yet another dumb syntax error...will I ever learn?
|
|
*
|
|
* 5 2/12/97 5:34p Jason
|
|
* fixed dumb syntax error
|
|
*
|
|
* 4 2/12/97 5:27p Jason
|
|
* implemented asin,acos,atan2
|
|
*
|
|
* 3 2/10/97 1:57p Jason
|
|
* changed FloatToFix back to what it originally was
|
|
*
|
|
* 2 2/07/97 5:44p Matt
|
|
* Moved fixed-point math funcs from vecmat to fix
|
|
* Changed trig functions to use small table like D2
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "fix.h"
|
|
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
#include "psrand.h"
|
|
//Tables for trig functions
|
|
float sincos_table[321]; //256 entries + 64 sin-only + 1 for interpolation
|
|
angle asin_table[257]; // 1 quadrants worth, +1 for interpolation
|
|
angle acos_table[257];
|
|
|
|
#define PI 3.141592654
|
|
|
|
//Generate the data for the trig tables
|
|
void InitMathTables ()
|
|
{
|
|
int i;
|
|
float rad,s,c;
|
|
|
|
for (i=0;i<321;i++) {
|
|
rad = (float) ((double) i / 256.0 * 2 * PI);
|
|
sincos_table[i] = (float) sin(rad);
|
|
}
|
|
|
|
for (i=0;i<256;i++) {
|
|
|
|
s=asin((float)i/256.0);
|
|
c=acos((float)i/256.0);
|
|
|
|
s=(s/(PI*2));
|
|
c=(c/(PI*2));
|
|
|
|
asin_table[i] = FloatToFix(s);
|
|
acos_table[i] = FloatToFix(c);
|
|
}
|
|
|
|
asin_table[256]=asin_table[255];
|
|
acos_table[256]=acos_table[255];
|
|
|
|
// Initialize a random seed.
|
|
ps_srand(time(NULL));
|
|
}
|
|
|
|
//Returns the sine of the given angle. Linearly interpolates between two entries in a 256-entry table
|
|
float FixSin(angle a)
|
|
{
|
|
int i,f;
|
|
float s0,s1;
|
|
|
|
i = (a>>8)&0xff;
|
|
f = a&0xff;
|
|
|
|
s0 = sincos_table[i];
|
|
s1 = sincos_table[i+1];
|
|
return (float) (s0 + ((s1 - s0) * (double) f / 256.0));
|
|
}
|
|
|
|
//Returns the cosine of the given angle. Linearly interpolates between two entries in a 256-entry table
|
|
float FixCos(angle a)
|
|
{
|
|
int i,f;
|
|
float c0,c1;
|
|
|
|
i = (a>>8)&0xff;
|
|
f = a&0xff;
|
|
|
|
c0 = sincos_table[i+64];
|
|
c1 = sincos_table[i+64+1];
|
|
return (float) (c0 + ((c1 - c0) * (double) f / 256.0));
|
|
}
|
|
|
|
//Returns the sine of the given angle, but does no interpolation
|
|
float FixSinFast(angle a)
|
|
{
|
|
int i;
|
|
|
|
i = ((a+0x80)>>8)&0xff;
|
|
|
|
return sincos_table[i];
|
|
}
|
|
|
|
//Returns the cosine of the given angle, but does no interpolation
|
|
float FixCosFast(angle a)
|
|
{
|
|
int i;
|
|
|
|
i = ((a+0x80)>>8)&0xff;
|
|
|
|
return sincos_table[i+64];
|
|
}
|
|
|
|
// use this instead of:
|
|
// for: (int)floor(x+0.5f) use FloatRound(x)
|
|
// (int)ceil(x-0.5f) use FloatRound(x)
|
|
// (int)floor(x-0.5f) use FloatRound(x-1.0f)
|
|
// (int)floor(x) use FloatRound(x-0.5f)
|
|
// for values in the range -2048 to 2048
|
|
|
|
// Set a vector to {0,0,0}
|
|
int FloatRound( float x )
|
|
{
|
|
float nf;
|
|
nf = x + 8390656.0f;
|
|
return ((*((int *)&nf)) & 0x7FFFFF)-2048;
|
|
}
|
|
|
|
// A fast way to convert floats to fix
|
|
fix FloatToFixFast( float x )
|
|
{
|
|
|
|
float nf;
|
|
nf = x*65536.0f + 8390656.0f;
|
|
return ((*((int *)&nf)) & 0x7FFFFF)-2048;
|
|
}
|
|
|
|
//Get rid of the "no return value" warnings in the next three functions
|
|
#pragma warning (disable:4035)
|
|
|
|
//compute inverse sine
|
|
angle FixAsin(float v)
|
|
{
|
|
fix vv;
|
|
int i,f,aa;
|
|
|
|
vv = FloatToFix(fabs(v));
|
|
|
|
if (vv >= F1_0) //check for out of range
|
|
return 0x4000;
|
|
|
|
i = (vv>>8)&0xff;
|
|
f = vv&0xff;
|
|
|
|
aa = asin_table[i];
|
|
aa = aa + (((asin_table[i+1] - aa) * f)>>8);
|
|
|
|
if (v < 0)
|
|
aa = F1_0-aa;
|
|
|
|
return aa;
|
|
}
|
|
|
|
//compute inverse cosine
|
|
angle FixAcos(float v)
|
|
{
|
|
fix vv;
|
|
int i,f,aa;
|
|
|
|
vv = FloatToFix(fabs(v));
|
|
|
|
if (vv >= F1_0) //check for out of range
|
|
return 0;
|
|
|
|
i = (vv>>8)&0xff;
|
|
f = vv&0xff;
|
|
|
|
aa = acos_table[i];
|
|
aa = aa + (((acos_table[i+1] - aa) * f)>>8);
|
|
|
|
if (v < 0)
|
|
aa = 0x8000 - aa;
|
|
|
|
return aa;
|
|
}
|
|
|
|
//given cos & sin of an angle, return that angle.
|
|
//parms need not be normalized, that is, the ratio of the parms cos/sin must
|
|
//equal the ratio of the actual cos & sin for the result angle, but the parms
|
|
//need not be the actual cos & sin.
|
|
//NOTE: this is different from the standard C atan2, since it is left-handed.
|
|
angle FixAtan2(float cos,float sin)
|
|
{
|
|
float q,m;
|
|
angle t;
|
|
|
|
//find smaller of two
|
|
|
|
|
|
q=(sin*sin)+(cos*cos);
|
|
|
|
m = sqrt(q);
|
|
|
|
if (m==0)
|
|
return 0;
|
|
|
|
if (fabs(sin) < fabs(cos))
|
|
{
|
|
//sin is smaller, use arcsin
|
|
t = FixAsin(sin/m);
|
|
if (cos<0)
|
|
t = 0x8000 - t;
|
|
|
|
return t;
|
|
}
|
|
else
|
|
{
|
|
t = FixAcos(cos/m);
|
|
if (sin<0)
|
|
t = F1_0-t;
|
|
|
|
return t;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Does a ceiling operation on a fixed number
|
|
fix FixCeil (fix num)
|
|
{
|
|
int int_num;
|
|
fix new_num;
|
|
|
|
int_num=FixToInt (num);
|
|
|
|
if (num & 0xFFFF)
|
|
{
|
|
new_num=IntToFix(int_num+1);
|
|
return new_num;
|
|
}
|
|
|
|
new_num=IntToFix(int_num);
|
|
return (new_num);
|
|
}
|
|
|
|
// Floors a fixed number
|
|
fix FixFloor (fix num)
|
|
{
|
|
int int_num=FixToInt (num);
|
|
|
|
return (IntToFix (int_num));
|
|
}
|
|
|