forked from FWGS/Paranoia2
282 lines
12 KiB
C++
282 lines
12 KiB
C++
//=======================================================================
|
|
// Copyright (C) Shambler Team 2005
|
|
// mathlib.h - shared mathlib header
|
|
//=======================================================================
|
|
#ifndef MATHLIB_H
|
|
#define MATHLIB_H
|
|
|
|
#ifndef M_PI
|
|
#define M_PI (float)3.14159265358979323846 // matches value in gcc v2 math.h
|
|
#endif
|
|
|
|
#ifndef M_PI2
|
|
#define M_PI2 (float)6.28318530717958647692
|
|
#endif
|
|
|
|
#ifndef byte
|
|
typedef unsigned char byte;
|
|
#endif // byte
|
|
|
|
#ifndef vec_t
|
|
typedef float vec_t;
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <vector.h>
|
|
#include "matrix.h"
|
|
|
|
// NOTE: PhysX mathlib is conflicted with standard min\max
|
|
#define Q_min( a, b ) (((a) < (b)) ? (a) : (b))
|
|
#define Q_max( a, b ) (((a) > (b)) ? (a) : (b))
|
|
#define Q_recip( a ) ((float)(1.0f / (float)(a)))
|
|
#define Q_floor( a ) ((float)(long)(a))
|
|
#define Q_ceil( a ) ((float)(long)((a) + 1))
|
|
#define Q_round( x, y ) (floor( x / y + 0.5 ) * y )
|
|
#define Q_square( a ) ((a) * (a))
|
|
#define Q_sign( x ) ( x >= 0 ? 1.0 : -1.0 )
|
|
#define Q_abs( x ) ((x)<0?-(x):x)
|
|
|
|
#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
|
|
#define saturate( val ) ((val) >= 0 ? ((val) < 1 ? (val) : 1) : 0)
|
|
#define IS_NAN(x) (((*(int *)&x) & (255<<23)) == (255<<23))
|
|
|
|
// some Physic Engine declarations
|
|
#define METERS_PER_INCH 0.0254f
|
|
#define METER2INCH( x ) (float)( x * ( 1.0f / METERS_PER_INCH ))
|
|
#define INCH2METER( x ) (float)( x * ( METERS_PER_INCH / 1.0f ))
|
|
|
|
// Keeps clutter down a bit, when using a float as a bit-vector
|
|
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
|
|
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
|
|
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
|
|
|
|
#define CHARSIGNBITSET( c ) (((const uint)(c)) >> 7)
|
|
#define CHARSIGNBITNOTSET( c ) ((~((const uint)(c))) >> 7)
|
|
|
|
#define SHORTSIGNBITSET( s ) (((const uint)(s)) >> 15)
|
|
#define SHORTSIGNBITNOTSET( s ) ((~((const uint)(s))) >> 15)
|
|
|
|
#define INTSIGNBITSET( i ) (((const uint)(i)) >> 31)
|
|
#define INTSIGNBITNOTSET( i ) ((~((const uint)(i))) >> 31)
|
|
|
|
#define FLOATSIGNBITSET( f ) ((*(const uint *)&(f)) >> 31)
|
|
#define FLOATSIGNBITNOTSET( f ) ((~(*(const uint *)&(f))) >> 31)
|
|
|
|
#define KNEEMAX_EPSILON 0.9998f // (0.9998 is about 1 degree)
|
|
|
|
// Used to represent sides of things like planes.
|
|
#define SIDE_FRONT 0
|
|
#define SIDE_BACK 1
|
|
#define SIDE_ON 2
|
|
|
|
#define PLANE_X 0 // 0 - 2 are axial planes
|
|
#define PLANE_Y 1 // 3 needs alternate calc
|
|
#define PLANE_Z 2
|
|
#define PLANE_LAST_AXIAL 2
|
|
#define PLANE_NONAXIAL 3
|
|
|
|
#define PLANE_NORMAL_EPSILON 1e-5
|
|
#define PLANE_DIR_EPSILON 1e-4
|
|
#define PLANE_DIST_EPSILON 4e-2
|
|
|
|
#define SMALL_FLOAT 1e-12
|
|
|
|
inline float Q_fabs( float f ) { int tmp = *( int *)&f; tmp &= 0x7FFFFFFF; return *( float *)&tmp; }
|
|
inline float anglemod( float a ) { return (360.0f / 65536) * ((int)(a * (65536 / 360.0f)) & 65535); }
|
|
void TransformAABB( const matrix4x4& world, const Vector &mins, const Vector &maxs, Vector &absmin, Vector &absmax );
|
|
void TransformAABBLocal( const matrix4x4& world, const Vector &mins, const Vector &maxs, Vector &outmins, Vector &outmaxs );
|
|
void CalcClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut );
|
|
float CalcSqrDistanceToAABB( const Vector &mins, const Vector &maxs, const Vector &point );
|
|
void RotatePointAroundVector( Vector &dst, const Vector &dir, const Vector &point, float degrees );
|
|
bool PlanesGetIntersectionPoint( const struct mplane_s *plane1, const struct mplane_s *plane2, const struct mplane_s *plane3, Vector &out );
|
|
bool IsSphereIntersectingCone( const Vector &sphereCenter, float sphereRadius, const Vector &coneOrigin, const Vector &coneNormal, float coneSine, float coneCosine );
|
|
void PlaneFromPoints( const Vector &p0, const Vector &p1, const Vector &p2, struct mplane_s *plane );
|
|
Vector PlaneIntersect( struct mplane_s *plane, const Vector& p0, const Vector& p1 );
|
|
void VectorAngles( const Vector &forward, Vector &angles );
|
|
void VectorAngles2( const Vector &forward, Vector &angles );
|
|
void MakeAxial( float normal[3] );
|
|
|
|
// return the smallest power of two >= x.
|
|
// returns 0 if x == 0 or x > 0x80000000 (ie numbers that would be negative if x was signed)
|
|
// NOTE: the old code took an int, and if you pass in an int of 0x80000000 casted to a uint,
|
|
// you'll get 0x80000000, which is correct for uints, instead of 0, which was correct for ints
|
|
_forceinline uint SmallestPowerOfTwoGreaterOrEqual( uint x )
|
|
{
|
|
x -= 1;
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
return x + 1;
|
|
}
|
|
|
|
// Remap a value in the range [A,B] to [C,D].
|
|
inline float RemapVal( float val, float A, float B, float C, float D)
|
|
{
|
|
if( A == B ) return val >= B ? D : C;
|
|
return C + (D - C) * (val - A) / (B - A);
|
|
}
|
|
|
|
inline float RemapValClamped( float val, float A, float B, float C, float D)
|
|
{
|
|
if( A == B ) return val >= B ? D : C;
|
|
float cVal = (val - A) / (B - A);
|
|
cVal = bound( 0.0f, cVal, 1.0f );
|
|
|
|
return C + (D - C) * cVal;
|
|
}
|
|
|
|
// Returns A + (B-A)*flPercent.
|
|
// float Lerp( float flPercent, float A, float B );
|
|
template <class T>
|
|
_forceinline T Lerp( float flPercent, T const &A, T const &B )
|
|
{
|
|
return A + (B - A) * flPercent;
|
|
}
|
|
|
|
int PlaneTypeForNormal( const Vector &normal );
|
|
int SignbitsForPlane( const Vector &normal );
|
|
int NearestPOW( int value, bool roundDown );
|
|
void SetPlane( struct mplane_s *plane, const Vector &vecNormal, float flDist, int type = -1 );
|
|
|
|
//
|
|
// bounds operations
|
|
//
|
|
void ClearBounds( Vector &mins, Vector &maxs );
|
|
void ClearBounds( Vector2D &mins, Vector2D &maxs );
|
|
bool BoundsIsCleared( const Vector &mins, const Vector &maxs );
|
|
bool BoundsIsNull( const Vector &mins, const Vector &maxs );
|
|
void ExpandBounds( Vector &mins, Vector &maxs, float offset );
|
|
void AddPointToBounds( const Vector &v, Vector &mins, Vector &maxs, float limit = 0.0f );
|
|
void AddPointToBounds( const Vector2D &v, Vector2D &mins, Vector2D &maxs );
|
|
bool BoundsIntersect( const Vector &mins1, const Vector &maxs1, const Vector &mins2, const Vector &maxs2 );
|
|
bool BoundsIntersect( const Vector2D &mins1, const Vector2D &maxs1, const Vector2D &mins2, const Vector2D &maxs2 );
|
|
bool BoundsAndSphereIntersect( const Vector &mins, const Vector &maxs, const Vector &origin, float radius );
|
|
bool BoundsAndSphereIntersect( const Vector2D &mins, const Vector2D &maxs, const Vector2D &origin, float radius );
|
|
void UTIL_MoveBounds( const Vector &start, const Vector &mins, const Vector &maxs, const Vector &end, Vector &outmins, Vector &outmaxs );
|
|
float RadiusFromBounds( const Vector &mins, const Vector &maxs );
|
|
void PerpendicularVector( Vector &dst, const Vector &src );
|
|
|
|
//
|
|
// quaternion operations
|
|
//
|
|
void AngleQuaternion( const Vector &angles, Vector4D &quat );
|
|
void AngleQuaternion( const Radian &angles, Vector4D &quat );
|
|
void AxisAngleQuaternion( const Vector &axis, float angle, Vector4D &q );
|
|
void QuaternionAngle( const Vector4D &quat, Vector &angles );
|
|
void QuaternionAngle( const Vector4D &quat, Radian &angles );
|
|
void QuaternionAlign( const Vector4D &p, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionSlerp( const Vector4D &p, const Vector4D &q, float t, Vector4D &qt );
|
|
void QuaternionSlerp( const Radian &r0, const Radian &r1, float t, Radian &r2 );
|
|
void QuaternionBlend( const Vector4D &p, const Vector4D &q, float t, Vector4D &qt );
|
|
void QuaternionSlerpNoAlign( const Vector4D &p, const Vector4D &q, float t, Vector4D &qt );
|
|
void QuaternionBlendNoAlign( const Vector4D &p, const Vector4D &q, float t, Vector4D &qt );
|
|
void QuaternionMultiply( const Vector4D &q1, const Vector4D &q2, Vector4D &out );
|
|
void QuaternionVectorTransform( const Vector4D &q, const Vector &v, Vector &out );
|
|
void QuaternionConcatTransforms( const Vector4D &q1, const Vector &v1, const Vector4D &q2, const Vector &v2, Vector4D &q, Vector &v );
|
|
void QuaternionSM( float s, const Vector4D &p, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionMA( const Vector4D &p, float s, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionAccumulate( const Vector4D &p, float s, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionMult( const Vector4D &p, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionAdd( const Vector4D &p, const Vector4D &q, Vector4D &qt );
|
|
void QuaternionScale( const Vector4D &p, float t, Vector4D &q );
|
|
|
|
//
|
|
// lerping stuff
|
|
//
|
|
void InterpolateOrigin( const Vector& start, const Vector& end, Vector& output, float frac, bool back = false );
|
|
void InterpolateAngles( const Vector& start, const Vector& end, Vector& output, float frac, bool back = false );
|
|
void NormalizeAngles( Vector &angles );
|
|
|
|
//
|
|
// FOV computing
|
|
//
|
|
float V_CalcFov( float &fov_x, float width, float height );
|
|
void V_AdjustFov( float &fov_x, float &fov_y, float width, float height, bool lock_x );
|
|
|
|
struct mplane_s;
|
|
|
|
void VectorMatrix( Vector &forward, Vector &right, Vector &up );
|
|
float ColorNormalize( const Vector &in, Vector &out );
|
|
// solve for "x" where "a x^2 + b x + c = 0", return true if solution exists
|
|
bool SolveQuadratic( float a, float b, float c, float &root1, float &root2 );
|
|
// solves for "a, b, c" where "a x^2 + b x + c = y", return true if solution exists
|
|
bool SolveInverseQuadratic( float x1, float y1, float x2, float y2, float x3, float y3, float &a, float &b, float &c );
|
|
bool PlaneFromPoints( const Vector triangle[3], struct mplane_s *plane );
|
|
bool ComparePlanes( struct mplane_s *plane, const Vector &normal, float dist );
|
|
bool VectorCompareEpsilon( const Vector &vec1, const Vector &vec2, float epsilon );
|
|
bool RadianCompareEpsilon( const Radian &vec1, const Radian &vec2, float epsilon );
|
|
unsigned int VertexHashKey( const vec3_t point, unsigned int hashSize );
|
|
void CategorizePlane( struct mplane_s *plane );
|
|
void SnapPlaneToGrid( struct mplane_s *plane );
|
|
void SnapVectorToGrid( Vector &normal );
|
|
bool VectorIsOnAxis( const Vector &v );
|
|
|
|
void CalcTBN( const Vector &p0, const Vector &p1, const Vector &p2, const Vector2D &t0, const Vector2D &t1, const Vector2D& t2, Vector &s, Vector &t, bool areaweight = false );
|
|
|
|
int BoxOnPlaneSide( const Vector &emins, const Vector &emaxs, const struct mplane_s *plane );
|
|
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) (((p)->type < 3)?(((p)->dist <= (emins)[(p)->type])? 1 : (((p)->dist >= (emaxs)[(p)->type])? 2 : 3)):BoxOnPlaneSide( (emins), (emaxs), (p)))
|
|
|
|
#define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal))
|
|
#define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
|
|
#define VectorDistance(a, b) (sqrt( VectorDistance2( a, b )))
|
|
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
|
|
Vector VectorYawRotate( const Vector &in, float flYaw );
|
|
|
|
// FIXME: get rid of this
|
|
#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
|
|
#define VectorMax(a) ( Q_max((a)[0], Q_max((a)[1], (a)[2])) )
|
|
|
|
#define TriangleNormal(a,b,c,n) \
|
|
( \
|
|
(n)[0] = ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]), \
|
|
(n)[1] = ((a)[2] - (b)[2]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[2] - (b)[2]), \
|
|
(n)[2] = ((a)[0] - (b)[0]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[0] - (b)[0]) \
|
|
)
|
|
|
|
/*
|
|
=================
|
|
rsqrt
|
|
=================
|
|
*/
|
|
inline float rsqrt( float number )
|
|
{
|
|
if( number == 0.0f )
|
|
return 0.0f;
|
|
|
|
int x = number * 0.5f;
|
|
int i = *(int *)&number; // evil floating point bit level hacking
|
|
i = 0x5f3759df - (i >> 1); // what the fuck?
|
|
int y = *(float *)&i;
|
|
y = y * (1.5f - (x * y * y)); // first iteration
|
|
|
|
return y;
|
|
}
|
|
|
|
// hermite basis function for smooth interpolation
|
|
// Similar to Gain() above, but very cheap to call
|
|
// value should be between 0 & 1 inclusive
|
|
inline float SimpleSpline( float value )
|
|
{
|
|
float valueSquared = value * value;
|
|
|
|
// Nice little ease-in, ease-out spline-like curve
|
|
return (3 * valueSquared - 2 * valueSquared * value);
|
|
}
|
|
|
|
unsigned short FloatToHalf( float v );
|
|
float HalfToFloat( unsigned short h );
|
|
signed char FloatToChar( float v );
|
|
|
|
float ColorToFloat( const Vector &color );
|
|
float NormalToFloat( const Vector &normal );
|
|
float OriginToFloat( const Vector &pos, const Vector ¢er );
|
|
float PackColor( const Vector &color );
|
|
float PackNormal( const Vector &normal );
|
|
|
|
extern float g_hullcolor[8][3];
|
|
extern int g_boxpnt[6][4];
|
|
|
|
#endif//MATHLIB_H
|