2021-04-10 14:22:48 +02:00
# include "math.h"
// Stolen from grumpycoder
2021-04-13 16:52:48 +02:00
// this is from here : https://github.com/grumpycoders/Balau/blob/master/tests/test-Handles.cc#L20-L102
2021-04-10 14:22:48 +02:00
2021-04-13 16:52:48 +02:00
// precalc costable
2021-04-10 14:22:48 +02:00
2021-04-13 16:52:48 +02:00
static int m_cosTable [ 512 ] ;
static const unsigned int DC_2PI = 2048 ;
2021-04-10 14:22:48 +02:00
static const unsigned int DC_PI = 1024 ;
static const unsigned int DC_PI2 = 512 ;
// f(n) = cos(n * 2pi / 2048) <- 2048 is == DC_2PI value
// f(n) = 2 * f(1) * f(n - 1) - f(n - 2)
2021-04-13 16:52:48 +02:00
2021-04-10 14:22:48 +02:00
void generateTable ( void ) {
m_cosTable [ 0 ] = 16777216 ; // 2^24 * cos(0 * 2pi / 2048) => 2^24 * 1 = 2^24 : here, 2^24 defines the precision we want after the decimal point
static const long long C = 16777137 ; // 2^24 * cos(1 * 2pi / 2048) = C = f(1);
m_cosTable [ 1 ] = C ;
for ( int i = 2 ; i < 512 ; i + + ) {
m_cosTable [ i ] = ( ( C * m_cosTable [ i - 1 ] ) > > 23 ) - m_cosTable [ i - 2 ] ;
m_cosTable [ 511 ] = 0 ;
}
} ;
int ncos ( unsigned int t ) {
t % = DC_2PI ;
int r ;
if ( t < DC_PI2 ) {
r = m_cosTable [ t ] ;
} else if ( t < DC_PI ) {
r = - m_cosTable [ DC_PI - 1 - t ] ;
} else if ( t < ( DC_PI + DC_PI2 ) ) {
r = - m_cosTable [ t - DC_PI ] ;
} else {
r = m_cosTable [ DC_2PI - 1 - t ] ;
} ;
return r > > 12 ;
} ;
// sin(x) = cos(x - pi / 2)
2021-04-13 16:52:48 +02:00
2021-04-10 14:22:48 +02:00
int nsin ( unsigned int t ) {
t % = DC_2PI ;
if ( t < DC_PI2 ) {
return ncos ( t + DC_2PI - DC_PI2 ) ;
} ;
return ncos ( t - DC_PI2 ) ;
} ;
// https://github.com/Arsunt/TR2Main/blob/411cacb35914c616cb7960c0e677e00c71c7ee88/3dsystem/phd_math.cpp#L432
long long patan ( long x , long y ) {
long long result ;
int swapBuf ;
int flags = 0 ;
// if either x or y are 0, return 0
if ( x = = 0 & & y = = 0 ) {
return 0 ;
}
if ( x < 0 ) {
flags | = 4 ;
x = - x ;
}
if ( y < 0 ) {
flags | = 2 ;
y = - y ;
}
if ( y > x ) {
flags | = 1 ;
SWAP ( x , y , swapBuf ) ;
}
result = AtanBaseTable [ flags ] + AtanAngleTable [ 0x800 * y / x ] ;
if ( result < 0 ) {
result = - result ;
return result ;
}
} ;
u_int psqrt ( u_int n ) {
u_int result = 0 ;
u_int base = 0x40000000 ;
u_int basedResult ;
for ( ; base ! = 0 ; base > > = 2 ) {
for ( ; base ! = 0 ; base > > = 2 ) {
basedResult = base + result ;
result > > = 1 ;
if ( basedResult > n ) {
break ;
}
n - = basedResult ;
result | = base ;
}
}
return result ;
} ;
// From : https://github.com/grumpycoders/pcsx-redux/blob/7438e9995833db5bc1e14da735bbf9dc78300f0b/src/mips/shell/math.h
2021-04-13 16:52:48 +02:00
2021-04-10 14:22:48 +02:00
int32_t dMul ( int32_t a , int32_t b ) {
long long r = a ;
r * = b ;
return r > > 24 ;
} ;
// standard lerp function
// s = source, an arbitrary number up to 2^24
// d = destination, an arbitrary number up to 2^24
// p = position, a number between 0 and 256, inclusive
// p = 0 means output = s
// p = 256 means output = d
uint32_t lerpU ( uint32_t start , uint32_t dest , unsigned pos ) {
return ( start * ( 256 - pos ) + dest * pos ) > > 8 ;
} ;
int32_t lerpS ( int32_t start , int32_t dest , unsigned pos ) {
return ( start * ( 256 - pos ) + dest * pos ) > > 8 ;
} ;
// start, dest and pos have to be << x, then the result has to be >> x where x defines precision:
// precision = 2^24 - 2^x
// << x : 0 < pos < precision
// https://discord.com/channels/642647820683444236/646765703143227394/811318550978494505
// my angles are between 0 and 2048 (full circle), so 2^11 for the range of angles; with numbers on a 8.24 representation, a 1.0 angle (or 2pi) means it's 2^24, so to "convert" my angles from 8.24 to my internal discrete cos, I only have to shift by 13
int32_t lerpD ( int32_t start , int32_t dest , int32_t pos ) {
return dMul ( start , 16777216 - pos ) + dMul ( dest , pos ) ;
} ;
long long lerpL ( long long start , long long dest , long long pos ) {
return dMul ( ( start < < 12 ) , 16777216 - ( pos < < 12 ) ) + dMul ( ( dest < < 12 ) , ( pos < < 12 ) ) > > 12 ;
} ;
int lerp ( int start , int end , int factor ) {
// lerp interpolated cam movement
// InBetween = Value 1 + ( ( Value2 - Value1 ) * lerpValue ) ;
2021-04-20 11:55:52 +02:00
// lerpValue should be a int between 17 and 256.
2021-04-10 14:22:48 +02:00
2021-04-20 11:55:52 +02:00
return ( ( start ) + ( ( end - start ) * factor ) ) > > 12 ;
2021-04-10 14:22:48 +02:00
} ;
long long easeIn ( long long i ) {
return ( ( i < < 7 ) * ( i < < 7 ) * ( i < < 7 ) / 32 ) > > 19 ;
} ;
int easeOut ( int i ) {
return ( 4096 > > 7 ) - ( ( 4096 - ( i < < 7 ) ) * ( 4096 - ( i < < 7 ) ) ) > > 12 ;
} ;
//~ int easeInOut(int i, int div){
//~ return lerp(easeIn(i, div), easeOut(i) , i);
//~ };
SVECTOR SVlerp ( SVECTOR start , SVECTOR end , int factor ) {
SVECTOR output = { 0 , 0 , 0 , 0 } ;
output . vx = lerp ( start . vx , end . vx , factor ) ;
output . vy = lerp ( start . vy , end . vy , factor ) ;
output . vz = lerp ( start . vz , end . vz , factor ) ;
return output ;
} ;
VECTOR getVectorTo ( VECTOR actor , VECTOR target ) {
2021-04-20 11:55:52 +02:00
// Returns a normalized vector that points from actor to target
2021-04-10 14:22:48 +02:00
VECTOR direction = { subVector ( target , actor ) } ;
VECTOR Ndirection = { 0 , 0 , 0 , 0 } ;
u_int distSq = ( direction . vx * direction . vx ) + ( direction . vz * direction . vz ) ;
direction . pad = psqrt ( distSq ) ;
VectorNormal ( & direction , & Ndirection ) ;
return Ndirection ;
} ;