thug/Code/Core/Math/math.h
2016-02-14 08:39:12 +11:00

474 lines
15 KiB
C++

/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/math.h **
** **
** Created: 11/23/99 - mjb **
** **
** Description: Math Library **
** **
*****************************************************************************/
#ifndef __CORE_MATH_MATH_H
#define __CORE_MATH_MATH_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifdef __PLAT_XBOX__
#include <math.h> // Required for fabsf().
#include <core\math\xbox\sse.h>
#endif
#ifdef __PLAT_WN32__
#include <math.h> // Required for fabsf().
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __USER_MATT__
#define DEBUGGING_REPLAY_RND 0
#else
#define DEBUGGING_REPLAY_RND 0
#endif
#if DEBUGGING_REPLAY_RND
#define Rnd( x ) Rnd_DbgVersion( ( x ), __LINE__, __FILE__ )
#else
#define Rnd( x ) Rnd( x )
#endif
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Type Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
void InitialRand(int a);
#if DEBUGGING_REPLAY_RND
int Rnd_DbgVersion(int n, int line, char *file);
void SetRndTestMode( int mode );
bool RndFuckedUp( void );
#else
int Rnd(int n);
#endif
// use for non-deterministic things
// especially for CD-timing reliant stuff that would throw off our random number dealy whopper.
int Rnd2(int n);
float PlusOrMinus(float n);
void InitSinLookupTable();
float Kensinf(float x);
float Kencosf(float x);
float Kenacosf(float x);
float Atan2 (float y, float x); // replaces atan2, much faster
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline int Abs ( int x )
{
return ( x>=0?x:-x);
}
inline float Abs ( float x )
{
return float ( fabsf ( x ));
}
// round down to nearest whole number
inline float Whole ( float x )
{
return (float) ( (int) ( x ));
}
// round to nearest whole number
inline float Round ( float x )
{
return (float) ( (int) ( x + 0.499999f));
}
//////////////////////////////////////////////////////////////////////////////////////////
// Calculate the "Parabolic Lerp" value for a set of parameters
// (Note: made-up name, by Mick)
//
// A lerp (Linear intERPalotion) value is always in the range 0.0 to 1.0
// and is used to move one value (A) towards another (B)
// usually the lerp value is fixed.
//
// A new value C is calculated as C = A + lerp * (B - A)
//
// a "ParaLerp" is a lerp value that varies based on the distance apart of the two values
//
// The purpose of this function is to be able to smoothly change a value
// that really only needs lerping when the values are within a small range
// The result of this equation is a parabolic curve that quickly tends
// towards lerp = 1.0, as x increases
// The valeu "Rate" is the value of x for which lerp half way between Min and 1.0
// Min is the value of lerp when x is 0
inline float ParaLerp(float x, float Rate = 1.0f, float Minimum = 0.0f)
{
float lerp = Minimum + (1 - 1 / (1 + x / Rate) ) * (1 - Minimum);
return lerp;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float ClampMin ( float v, float min )
{
if ( v < min )
{
return min;
}
else
{
return v;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float ClampMax ( float v, float max )
{
if ( v > max )
{
return max;
}
else
{
return v;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Clamp ( float v, float min, float max )
{
return ClampMin ( ClampMax ( v, max ), min );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Lerp ( float a, float b, float value )
{
return a + ( b - a ) * value;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float LinearMap ( float a, float b, float value, float value_min, float value_max )
{
return Lerp(a, b, (value - value_min) / (value_max - value_min));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothStep ( float value )
{
// interpolates from zero to one with a zero derivative at the end-points
return -2.0f * value * value * ( value - (3.0f / 2.0f) );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothInterp ( float a, float b, float value )
{
return Lerp(a, b, SmoothStep(value));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothMap ( float a, float b, float value, float value_min, float value_max )
{
return Lerp(a, b, SmoothStep((value - value_min) / (value_max - value_min)));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Max ( float a, float b )
{
return ( a > b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Min ( float a, float b )
{
return ( a < b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Sgn ( float x )
{
if ( x < 0.f )
{
return -1.0f;
}
else
{
return 1.0f;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Sqr ( float x )
{
return ( x * x );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Swap ( float& a, float& b )
{
float t = a;
a = b;
b = t;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Equal ( const float a, const float b, const float perc )
{
return ( Abs ( a - b ) <= (( Abs ( a ) + Abs ( b )) * perc ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline sint Max ( sint a, sint b )
{
return ( a > b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline sint Min ( sint a, sint b )
{
return ( a < b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Max3 ( float a, float b, float c )
{
return Max(a, Max(b,c));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Min3 ( float a, float b, float c )
{
return Min(a, Min(b,c));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Determinant ( float a, float b, float c, float d )
{
return ( a * d ) - ( b * c );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Determinant3 ( float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3 )
{
return a1 * (b2 * c3 - b3 * c2) -
b1 * (a2 * c3 - a3 * c2) +
c1 * (a2 * b3 - a3 * b2);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline int WeightedRnd ( float min_val, float max_val )
{
// This random function uses the West distribution
// to return values that favor the midpoint.
// For example, WeightedRnd( 10, 20 ) returns:
// Bucket[10] = 2.12 percent
// Bucket[11] = 5.72 percent
// Bucket[12] = 9.44 percent
// Bucket[13] = 13.87 percent
// Bucket[14] = 18.16 percent
// Bucket[15] = 15.70 percent
// Bucket[16] = 14.52 percent
// Bucket[17] = 10.16 percent
// Bucket[18] = 6.05 percent
// Bucket[19] = 2.26 percent
// Bucket[20] = 2.00 percent
float range = ( max_val - min_val ) / 2;
float midpoint = min_val + range;
float random_val = range - (float)sqrtf((float)Rnd( (int)(range * range) ) );
// negate it half of the time
if ( Rnd(2) )
{
random_val = -random_val;
}
return (int)( random_val + midpoint );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Trig
const float EPSILON = 0.000001f;
const float PI = 3.141592654f;
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float DegToRad ( float degrees )
{
return degrees * ( PI / 180.0f);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float RadToDeg ( float radians )
{
return radians * ( 180.0f / PI );
}
int RunFilter( int target, int current, int delta );
float FRunFilter( float target, float current, float delta );
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Mth
#endif // __CORE_MATH_MATH_H