///////////////////////////////////////// // // OpenLieroX // // Auxiliary Software class library // // based on the work of JasonB // enhanced by Dark Charlie and Albert Zeyer // // code under LGPL // ///////////////////////////////////////// // Mathematics Library // Created 20/12/01 // Jason Boettcher // Albert Zeyer #ifndef __MATHLIB_H__ #define __MATHLIB_H__ #include #include "CVec.h" // Constants #define PI 3.14159265358979323846 // Routines float GetRandomNum(); // get a random float from [-1,1] float GetRandomPosNum(); // get a random float from [0,1] int GetRandomInt(int max); // get a random int from [0,max] int Round(float x); /*#ifdef _MSC_VER float cos(float _v) {return cosf(_v); } float sin(float _v) {return sinf(_v); } float tan(float _v) {return tanf(_v); } float atan(float _v) {return atanf(_v); } float sqrt(float _v) {return sqrtf(_v); } #endif*/ float CalculateDistance(CVec p1, CVec p2); float NormalizeVector(CVec *vec); CVec GetRandomVec(); void GetVecsFromAngle(int yaw,CVec *forward, CVec *right); float VectorAngle(CVec vec1, CVec vec2); float VectorLength(CVec vec); float fastSQRT(float x); #define SIGN(x) (((x) > 0)?1:(((x) < 0)?-1:0)) #define SQR(x) ((x)*(x)) #undef MIN #undef MAX template T MIN(T a, T b) { return a < b ? a : b; } template T MAX(T a, T b) { return a > b ? a : b; } inline unsigned long MIN(unsigned long a, unsigned int b) { return a < b ? a : b; } template T CLAMP(const T& num, const T& lower_bound, const T& upper_bound) { return num < lower_bound ? lower_bound : (num > upper_bound ? upper_bound : num); } template int CLAMP_DIRECT(T& num, const T& lower_bound, const T& upper_bound) { if(num < lower_bound) { num = lower_bound; return -1; } else if(num > upper_bound) { num = upper_bound; return 1; } else return 0; } template void REDUCE_CONST(T& v, const T& red_const) { if(v > 0) v = MAX((T)0, v - red_const); else if(v < 0) v = MIN((T)0, v + red_const); } template void RESET_SMALL(T& v, const T& limit) { if((v > 0 && v < limit) || (v < 0 && v > -limit)) v = 0; } template void MOD(T& a, const T& b) { a %= b; if(a < 0) a += b; } template void FMOD(T& a, const T& b) { a -= b * floor(a / b); if(a < 0) a += b; } template class SquareMatrix { public: VectorD2<_T> v1, v2; SquareMatrix(VectorD2<_T> _v1 = VectorD2<_T>(0,0), VectorD2<_T> _v2 = VectorD2<_T>(0,0)) { v1 = _v1; v2 = _v2; } static SquareMatrix Identity() { return SquareMatrix(VectorD2<_T>(1,0), VectorD2<_T>(0,1)); } static SquareMatrix RotateMatrix(float angle) { SquareMatrix m; m.v1.x = cos(angle); m.v1.y = sin(angle); m.v2.x = -m.v1.y; m.v2.y = m.v1.x; return m; } CVec operator()(const VectorD2<_T>& v) const { return CVec(v.x*v1.x + v.y*v2.x, v.x*v1.y + v.y*v2.y); } SquareMatrix operator*(const SquareMatrix& m) const { return SquareMatrix((*this)(m.v1), (*this)(m.v2)); } SquareMatrix operator*(const float m) const { return SquareMatrix(v1*m, v2*m); } SquareMatrix operator*(const int m) const { return SquareMatrix(v1*m, v2*m); } SquareMatrix operator/(const float m) const { return SquareMatrix(v1/m, v2/m); } SquareMatrix operator/(const int m) const { return SquareMatrix(v1/m, v2/m); } _T det() const { return v1.x*v2.y - v1.y*v2.x; } SquareMatrix inverse() const { _T tdet = det(); if(tdet == 0) return SquareMatrix(); else return SquareMatrix(VectorD2<_T>(v2.y,-v1.y),VectorD2<_T>(-v2.x,v1.x))/tdet; } // v1 is the upper-left, v2 the right-bottom bool isInDefinedArea(const VectorD2<_T>& p) const { return v1.x <= p.x && p.x <= v2.x && v1.y <= p.y && p.y <= v2.y; } VectorD2<_T> getCenter() const { return (v1 + v2) / 2; } SquareMatrix getInsersectionWithArea(const SquareMatrix& a) const { return SquareMatrix( VectorD2<_T>( MAX(a.v1.x, v1.x), MAX(a.v1.y, v1.y) ), VectorD2<_T>( MIN(a.v2.x, v2.x), MIN(a.v2.y, v2.y) ) ); } }; class Parabola { public: float a, b, c; // a*x^2 + b*x + c public: Parabola() : a(0), b(0), c(0) {} Parabola(float pa, float pb, float pc) : a(pa), b(pb), c(pc) {} Parabola(const Parabola& p) { a = p.a; b = p.b; c = p.c; } Parabola(CVec p1, CVec p2, CVec p3); Parabola(CVec p1, float angleP1, CVec p2); inline bool operator==(const Parabola& p) const { return (a == p.a && b == p.b && c == p.c); } float getLength(CVec p1, CVec p2); float getLength(float pa, float pb); bool isPointAtParabola(CVec p1) { return (p1.y == (a * p1.x * p1.x ) + (b * p1.x) + c); } }; // Random number generator with save()/restore() methods that will save and restore generator's state // This generator should produce the same numbers on any CPU architecture, if initialized with the same seed. // Ripped from Gnu Math library // I don't want to use Mersenne Twister 'cuz it has a state of 624 ints which should be copied with Save()/Restore() class SyncedRandom { public: SyncedRandom( unsigned long s = getRandomSeed() ) { if (!s) s = 1UL; /* default seed is 1 */ z1 = LCG (s); if (z1 < 2UL) z1 += 2UL; z2 = LCG (z1); if (z2 < 8UL) z2 += 8UL; z3 = LCG (z2); if (z3 < 16UL) z3 += 16UL; z4 = LCG (z3); if (z4 < 128UL) z4 += 128UL; /* Calling RNG ten times to satify recurrence condition */ getInt(); getInt(); getInt(); getInt(); getInt(); getInt(); getInt(); getInt(); getInt(); getInt(); }; // Returns unsigned int in a range 0 : UINT_MAX unsigned long getInt() { unsigned long b1, b2, b3, b4; b1 = ((((z1 << 6UL) & MASK) ^ z1) >> 13UL); z1 = ((((z1 & 4294967294UL) << 18UL) & MASK) ^ b1); b2 = ((((z2 << 2UL) & MASK) ^ z2) >> 27UL); z2 = ((((z2 & 4294967288UL) << 2UL) & MASK) ^ b2); b3 = ((((z3 << 13UL) & MASK) ^ z3) >> 21UL); z3 = ((((z3 & 4294967280UL) << 7UL) & MASK) ^ b3); b4 = ((((z4 << 3UL) & MASK) ^ z4) >> 12UL); z4 = ((((z4 & 4294967168UL) << 13UL) & MASK) ^ b4); return (z1 ^ z2 ^ z3 ^ z4); }; // Returns float in range 0 : 1 (1 non-inclusive) float getFloat() { return getInt() / 4294967296.0f; }; void save() { save_z1 = z1; save_z2 = z2; save_z3 = z3; save_z4 = z4; }; void restore() { z1 = save_z1; z2 = save_z2; z3 = save_z3; z4 = save_z4; }; // Returns random seed based on time() and SDL_GetTicks() functions static unsigned long getRandomSeed(); private: static const unsigned long MASK = 0xffffffffUL; unsigned long LCG(unsigned long n) { return ((69069UL * n) & MASK); }; unsigned long z1, z2, z3, z4; unsigned long save_z1, save_z2, save_z3, save_z4; }; #endif // __MATHLIB_H__