Files
TCPlayerbotCore/dep/include/g3dlite/G3D/g3dmath.h
T

521 lines
11 KiB
C++
Raw Normal View History

2008-10-02 16:23:55 -05:00
/**
@file g3dmath.h
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Math util class.
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
@maintainer Morgan McGuire, [email protected]
@cite highestBit by Jukka Liimatta
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
@created 2001-06-02
@edited 2006-01-16
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Copyright 2000-2006, Morgan McGuire.
All rights reserved.
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#ifndef G3DMATH_H
#define G3DMATH_H
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#ifdef _MSC_VER
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
# pragma warning (push)
# pragma warning (disable : 4127)
// disable: "C++ exception handler used"
# pragma warning (disable : 4530)
#endif
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "G3D/platform.h"
#include <ctype.h>
#include <string>
#include <float.h>
#include <limits>
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/*These defines enable functionality introduced with the 1999 ISO C
**standard. They must be defined before the inclusion of math.h to
2009-02-09 08:16:34 -05:00
**engage them. If optimisation is enabled, these functions will be
2008-10-02 16:23:55 -05:00
**inlined. With optimisation switched off, you have to link in the
**maths library using -lm.
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#define _ISOC9X_SOURCE1
#define _ISOC99_SOURCE1
#define __USE_ISOC9X1
#define __USE_ISOC991
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include <math.h>
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "G3D/debug.h"
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#undef min
#undef max
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
namespace G3D {
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#if defined(_MSC_VER)
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#if !defined(_WIN64)
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Win32 implementation of the C99 fast rounding routines.
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
@cite routines are
Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
Permission to use, copy, modify, distribute, and sell this file for any
purpose is hereby granted without fee, provided that the above copyright
2008-10-02 16:23:55 -05:00
and this permission notice appear in all copies. No representations are
2009-02-09 08:16:34 -05:00
made about the suitability of this software for any purpose. It is
2008-10-02 16:23:55 -05:00
provided "as is" without express or implied warranty.
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
__inline long int lrint (double flt) {
int intgr;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
_asm {
fld flt
fistp intgr
};
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
return intgr;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
__inline long int lrintf(float flt) {
int intgr;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
_asm {
fld flt
fistp intgr
};
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
return intgr;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#else
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
__inline long int lrint (double flt) {
return (long int)floor(flt+0.5f);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
__inline long int lrintf(float flt) {
return (long int)floorf(flt+0.5f);
}
#endif
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#endif
const double fuzzyEpsilon = 0.00001;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Returns a reference to a static double.
This value should not be tested against directly, instead
G3D::isNan() and G3D::isFinite() will return reliable results. */
inline const double& inf() {
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// We already have <limits> included but
// not using it in older gcc for safe compilations
2009-02-09 08:16:34 -05:00
#if (__GNUC__ == 2)
2008-10-02 16:23:55 -05:00
static const double i = 1.0/sin(0.0);
#else
// double is a standard type and should have infinity
static const double i = std::numeric_limits<double>::infinity();
#endif
2009-02-09 08:16:34 -05:00
return i;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Returns a reference to a static double.
This value should not be tested against directly, instead
G3D::isNan() and G3D::isFinite() will return reliable results. */
inline const double& nan() {
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// We already have <limits> included but
// not using it in older gcc for safe compilations
#if (__GNUC__ == 2)
static const double n = 0.0/sin(0.0);
#else
// double is a standard type and should have quiet NaN
static const double n = std::numeric_limits<double>::quiet_NaN();
#endif
2009-02-09 08:16:34 -05:00
return n;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Returns a reference to a static double. Use instead of G3D_PI. */
inline const double& pi() {
static const double p = 3.1415926535898;
return p;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Returns a reference to a static double. Use instead of G3D_HALF_PI. */
inline const double& halfPi() {
static const double p = 1.5707963267949;
return p;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Returns a reference to a static double. Use instead of G3D_TWO_PI. */
inline const double& twoPi() {
static const double p = 6.283185;
return p;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** @def G3D_PI
@deprecated Use G3D::pi() instead. */
#define G3D_PI (3.1415926535898)
/** @def G3D_HALF_PI
@deprecated Use G3D::halfPi() instead. */
#define G3D_HALF_PI (1.5707963267949)
/** @def G3D_TWO_PI
@deprecated Use G3D::twoPi() instead. */
#define G3D_TWO_PI (6.283185)
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
typedef signed char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#ifdef _MSC_EXTENSIONS
2009-02-09 08:16:34 -05:00
typedef __int64 int64;
2008-10-02 16:23:55 -05:00
typedef unsigned __int64 uint64;
#else
2009-02-09 08:16:34 -05:00
typedef long long int64;
2008-10-02 16:23:55 -05:00
typedef unsigned long long uint64;
#endif
typedef unsigned int uint;
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
typedef float float32;
typedef double float64;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
int iAbs(int iValue);
int iCeil(double fValue);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Clamps the value to the range [low, hi] (inclusive)
*/
int iClamp(int val, int low, int hi);
double clamp(double val, double low, double hi);
float clamp(float val, float low, float hi);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns a + (b - a) * f;
*/
inline double lerp(double a, double b, double f) {
return a + (b - a) * f;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
inline float lerp(float a, float b, float f) {
return a + (b - a) * f;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Wraps the value to the range [0, hi) (exclusive
on the high end). This is like the clock arithmetic
produced by % (modulo) except the result is guaranteed
to be positive.
*/
int iWrap(int val, int hi);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
int iFloor(double fValue);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
int iSign(int iValue);
int iSign(double fValue);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
inline int iSign(float f) {
return iSign((double)f);
}
2009-02-09 08:16:34 -05:00
/**
2008-10-02 16:23:55 -05:00
Fast round to integer using the lrint routine.
Typically 6x faster than casting to integer.
*/
inline int iRound(double fValue) {
return lrint(fValue);
}
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
/**
2008-10-02 16:23:55 -05:00
Fast round to integer using the lrint routine.
Typically 6x faster than casting to integer.
*/
inline int iRound(float f) {
return lrintf(f);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns a random number uniformly at random between low and hi
(inclusive).
*/
int iRandom(int low, int hi);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
double abs (double fValue);
double aCos (double fValue);
double aSin (double fValue);
double aTan (double fValue);
double aTan2 (double fY, double fX);
double sign (double fValue);
double square (double fValue);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns true if the argument is a finite real number.
*/
bool isFinite(double x);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns true if the argument is NaN (not a number).
You can't use x == nan to test this because all
comparisons against nan return false.
*/
bool isNaN(double x);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Computes x % 3.
*/
int iMod3(int x);
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
/**
2008-10-02 16:23:55 -05:00
[0, 1]
@deprecated use uniformRandom()
*/
double unitRandom ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Uniform random number between low and hi, inclusive.
@deprecated use uniformRandom()
*/
double random(double low, double hi);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
[-1, 1]
@deprecated use uniformRandom()
*/
double symmetricRandom ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Uniform random number between low and hi, inclusive. [low, hi]
*/
float uniformRandom(float low = 0.0f, float hi = 1.0f);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
2009-02-09 08:16:34 -05:00
Normally distributed random number.
2008-10-02 16:23:55 -05:00
*/
float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline double min(double x, double y) {
return std::_cpp_min(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline float min(float x, float y) {
return std::_cpp_min(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline int min(int x, int y) {
return std::_cpp_min(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline double max(double x, double y) {
return std::_cpp_max(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline float max(float x, float y) {
return std::_cpp_max(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** VC6 lacks std::min and std::max */
inline int max(int x, int y) {
return std::_cpp_max(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#else
template <class T>
inline T min(const T& x, const T& y) {
return std::min<T>(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
template <class T>
inline T max(const T& x, const T& y) {
return std::max<T>(x, y);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#endif
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
int iMin(int x, int y);
int iMax(int x, int y);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
double square(double x);
double sumSquares(double x, double y);
double sumSquares(double x, double y, double z);
double distance(double x, double y);
double distance(double x, double y, double z);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returnes the 0-based index of the highest 1 bit from
the left. -1 means the number was 0.
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
@cite Based on code by [email protected]
2009-02-09 08:16:34 -05:00
*/
2008-10-02 16:23:55 -05:00
int highestBit(uint32 x);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply
fuzzyEq(a, c), although that will be the case on some
occasions.
*/
bool fuzzyEq(double a, double b);
2009-10-17 15:51:44 -07:00
2009-02-09 08:16:34 -05:00
/** True if a is definitely not equal to b.
Guaranteed false if a == b.
2008-10-02 16:23:55 -05:00
Possibly false when a != b.*/
bool fuzzyNe(double a, double b);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Is a strictly greater than b? (Guaranteed false if a <= b).
(Possibly false if a > b) */
bool fuzzyGt(double a, double b);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Is a near or greater than b? */
bool fuzzyGe(double a, double b);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Is a strictly less than b? (Guaranteed false if a >= b)*/
bool fuzzyLt(double a, double b);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** Is a near or less than b? */
bool fuzzyLe(double a, double b);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Computes 1 / sqrt(x).
*/
inline float rsq(float x) {
return 1.0f / sqrtf(x);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Uses SSE to implement rsq.
@cite Nick [email protected]
*/
inline float SSErsq(float x) {
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#if defined(SSE) && defined(G3D_WIN32) && !defined(_WIN64)
__asm {
movss xmm0, x
rsqrtss xmm0, xmm0
movss x, xmm0
}
return x;
#else
return 1.0f / sqrt(x);
#endif
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Return the next power of 2 higher than the input
2009-02-09 08:16:34 -05:00
If the input is already a power of 2, the output will be the same
2008-10-02 16:23:55 -05:00
as the input.
*/
int ceilPow2(unsigned int in);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
* True if num is a power of two.
*/
bool isPow2(int num);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
bool isOdd(int num);
bool isEven(int num);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
double toRadians(double deg);
double toDegrees(double rad);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns true if x is not exactly equal to 0.0f.
*/
inline bool any(float x) {
return x != 0;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Returns true if x is not exactly equal to 0.0f.
*/
inline bool all(float x) {
return x != 0;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
v / v (for DirectX/Cg support)
*/
inline float normalize(float v) {
return v / v;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
a * b (for DirectX/Cg support)
*/
inline float dot(float a, float b) {
return a * b;
}
/**
a * b (for DirectX/Cg support)
*/
inline float mul(float a, float b) {
return a * b;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
2^x
*/
inline double exp2(double x) {
return pow(2.0, x);
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
inline double rsqrt(double x) {
return 1.0 / sqrt(x);
}
/**
sin(x)/x
*/
inline double sinc(double x) {
double r = sin(x) / x;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if (isNaN(r)) {
return 1.0;
} else {
return r;
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/**
Computes a floating point modulo; the result is t wrapped to the range [lo, hi).
*/
inline double wrap(double t, double lo, double hi) {
if ((t >= lo) && (t < hi)) {
return t;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
debugAssert(hi > lo);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
double interval = hi - lo;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
return t - interval * iFloor((t - lo) / interval);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
inline double wrap(double t, double hi) {
return wrap(t, 0, hi);
}
} // namespace
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#ifdef _MSC_VER
# pragma warning (pop)
#endif
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "g3dmath.inl"
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#endif
2009-10-17 15:51:44 -07:00