2015-04-19 20:39:16 +00:00
|
|
|
#ifndef MATH_HPP
|
|
|
|
#define MATH_HPP
|
|
|
|
|
2015-11-27 22:19:54 +00:00
|
|
|
#undef min
|
|
|
|
#undef max
|
2015-10-12 04:40:59 +00:00
|
|
|
#ifndef NOMINMAX
|
|
|
|
#define NOMINMAX 1
|
|
|
|
#endif
|
|
|
|
#ifndef _USE_MATH_DEFINES
|
2015-04-19 20:39:16 +00:00
|
|
|
#define _USE_MATH_DEFINES 1
|
2015-10-12 04:40:59 +00:00
|
|
|
#endif
|
2015-10-12 19:24:53 +00:00
|
|
|
#include <math.h>
|
2015-10-12 09:50:24 +00:00
|
|
|
#include <algorithm>
|
2015-10-12 08:49:33 +00:00
|
|
|
|
2015-10-08 00:21:38 +00:00
|
|
|
namespace Zeus
|
|
|
|
{
|
2015-11-02 18:44:46 +00:00
|
|
|
struct CPUInfo
|
|
|
|
{
|
|
|
|
const char cpuBrand [32] = {0};
|
|
|
|
const char cpuVendor[32] = {0};
|
|
|
|
const bool isIntel = false;
|
|
|
|
const bool SSE1 = false;
|
|
|
|
const bool SSE2 = false;
|
|
|
|
const bool SSE3 = false;
|
|
|
|
const bool SSSE3 = false;
|
|
|
|
const bool SSE41 = false;
|
|
|
|
const bool SSE42 = false;
|
|
|
|
const bool SSE4a = false;
|
|
|
|
const bool AESNI = false;
|
|
|
|
};
|
|
|
|
/**
|
|
|
|
* Detects CPU capabilities and returns true if SSE4.1 or SSE4.2 is available
|
|
|
|
*/
|
|
|
|
void detectCPU();
|
|
|
|
const CPUInfo cpuFeatures();
|
2015-10-25 19:31:41 +00:00
|
|
|
class CVector3f;
|
|
|
|
class CTransform;
|
2015-04-19 20:39:16 +00:00
|
|
|
namespace Math
|
|
|
|
{
|
2015-08-29 01:29:17 +00:00
|
|
|
template<typename T>
|
2015-10-12 08:46:45 +00:00
|
|
|
inline T min(T a, T b) { return a < b ? a : b; }
|
|
|
|
template<typename T>
|
|
|
|
inline T max(T a, T b) { return a > b ? a : b; }
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T clamp(T a, T val, T b) {return max<T>(a, min<T>(b, val));}
|
2015-04-19 20:39:16 +00:00
|
|
|
inline float radToDeg(float rad) {return rad * 180.f / M_PI;}
|
|
|
|
inline float degToRad(float deg) {return deg * M_PI / 180;}
|
2015-08-29 04:49:19 +00:00
|
|
|
|
2015-04-19 20:39:16 +00:00
|
|
|
extern const CVector3f kRadToDegVec;
|
|
|
|
extern const CVector3f kDegToRadVec;
|
2015-10-25 19:31:41 +00:00
|
|
|
CVector3f radToDeg(const CVector3f& rad);
|
|
|
|
CVector3f degToRad(const CVector3f& deg);
|
2015-08-29 04:49:19 +00:00
|
|
|
|
2015-04-19 20:39:16 +00:00
|
|
|
extern const CVector3f kUpVec;
|
|
|
|
CTransform lookAt(const CVector3f& pos, const CVector3f& lookPos, const CVector3f& up=kUpVec);
|
2015-10-25 19:31:41 +00:00
|
|
|
CVector3f baryToWorld(const CVector3f& p0, const CVector3f& p1, const CVector3f& p2, const CVector3f& bary);
|
2015-10-08 00:21:38 +00:00
|
|
|
|
2015-10-12 09:38:34 +00:00
|
|
|
CVector3f getBezierPoint(const CVector3f& a, const CVector3f& b,
|
|
|
|
const CVector3f& c, const CVector3f& d, float t);
|
2015-10-12 08:46:45 +00:00
|
|
|
float getCatmullRomSplinePoint(float a, float b,
|
|
|
|
float c, float d, float t);
|
|
|
|
CVector3f getCatmullRomSplinePoint(const CVector3f& a, const CVector3f& b,
|
|
|
|
const CVector3f& c, const CVector3f& d, float t);
|
2015-10-12 09:38:34 +00:00
|
|
|
CVector3f getRoundCatmullRomSplinePoint(const CVector3f& a, const CVector3f& b,
|
|
|
|
const CVector3f& c, const CVector3f& d, float t);
|
2015-10-12 00:33:42 +00:00
|
|
|
|
2015-10-12 08:46:45 +00:00
|
|
|
inline float slowCosineR(float val) { return float(cos(val)); }
|
|
|
|
inline float slowSineR(float val) { return float(sin(val)); }
|
|
|
|
inline float slowTangentR(float val) { return float(tan(val)); }
|
|
|
|
inline float arcSineR(float val) { return float(asin(val)); }
|
|
|
|
inline float arcTangentR(float val) { return float(atan(val)); }
|
2015-10-25 19:31:41 +00:00
|
|
|
inline float arcCosineR(float val) { return float(acos(val)); }
|
2015-10-12 08:46:45 +00:00
|
|
|
inline float powF(float a, float b) { return float(exp(b * log(a))); }
|
|
|
|
inline float floorF(float val) { return float(floor(val)); }
|
|
|
|
inline float ceilingF(float val)
|
2015-10-12 00:33:42 +00:00
|
|
|
{
|
2015-10-12 08:46:45 +00:00
|
|
|
float tmp = floorF(val);
|
|
|
|
return (tmp == val ? tmp : tmp + 1.0);
|
2015-10-12 00:33:42 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 08:46:45 +00:00
|
|
|
// Since round(double) doesn't exist in some <cmath> implementations
|
|
|
|
// we'll define our own
|
2015-10-12 09:19:19 +00:00
|
|
|
inline double round(double val) { return (val < 0.0 ? ceilingF(val - 0.5) : floorF(val + 0.5)); }
|
2015-10-25 19:31:41 +00:00
|
|
|
inline double powD(float a, float b) { return exp(b * log(a)); }
|
2015-10-12 08:46:45 +00:00
|
|
|
|
|
|
|
double sqrtD(double val);
|
|
|
|
inline double invSqrtD(double val) { return 1.0 / sqrtD(val); }
|
|
|
|
inline float invSqrtF(float val) { return float(1.0 / sqrtD(val)); }
|
|
|
|
inline float sqrtF(float val) { return float(sqrtD(val)); }
|
|
|
|
float fastArcCosR(float val);
|
|
|
|
float fastCosR(float val);
|
|
|
|
float fastSinR(float val);
|
|
|
|
int floorPowerOfTwo(int x);
|
2016-02-12 02:29:35 +00:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline int PopCount(T x)
|
|
|
|
{
|
2016-02-12 02:34:40 +00:00
|
|
|
using U = std::make_unsigned_t<std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, T>>;
|
2016-02-12 02:29:35 +00:00
|
|
|
U cx = U(x);
|
|
|
|
const U m1 = U(0x5555555555555555); //binary: 0101...
|
|
|
|
const U m2 = U(0x3333333333333333); //binary: 00110011..
|
|
|
|
const U m4 = U(0x0f0f0f0f0f0f0f0f); //binary: 4 zeros, 4 ones ...
|
|
|
|
const U h01 = U(0x0101010101010101); //the sum of 256 to the power of 0,1,2,3...
|
|
|
|
|
|
|
|
cx -= (cx >> 1) & m1; //put count of each 2 bits into those 2 bits
|
|
|
|
cx = (cx & m2) + ((cx >> 2) & m2); //put count of each 4 bits into those 4 bits
|
|
|
|
cx = (cx + (cx >> 4)) & m4; //put count of each 8 bits into those 8 bits
|
|
|
|
return (cx * h01) >> ((sizeof(U)-1)*8); //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
|
|
|
|
}
|
2015-10-08 00:21:38 +00:00
|
|
|
}
|
2015-04-19 20:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // MATH_HPP
|