2176 lines
69 KiB
C
2176 lines
69 KiB
C
/********************************************************************************
|
|
Copyright (C) 2001-2012 Hugh Bailey <obs.jim@gmail.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
********************************************************************************/
|
|
|
|
|
|
#pragma once
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
#pragma intrinsic(fabs)
|
|
|
|
|
|
#ifdef USE_SSE
|
|
#include <xmmintrin.h>
|
|
#endif
|
|
|
|
|
|
#undef M_PI
|
|
#undef M_INFINITE
|
|
#undef RAD
|
|
#undef DEG
|
|
#undef EPSILON
|
|
|
|
//defines
|
|
#define M_PI 3.1415926535897932384626433832795f
|
|
#define RAD(val) ((val)*0.0174532925199432957692369076848f)
|
|
#define DEG(val) ((val)*57.295779513082320876798154814105f)
|
|
#define LARGE_EPSILON 1e-2f
|
|
#define EPSILON 1e-4f
|
|
#define TINY_EPSILON 1e-5f
|
|
#define M_INFINITE 3.4e38f
|
|
|
|
|
|
|
|
struct Vect;
|
|
struct Vect4;
|
|
struct Euler;
|
|
struct Quat;
|
|
struct AxisAngle;
|
|
struct Plane;
|
|
struct Matrix;
|
|
struct Float16;
|
|
|
|
|
|
union XLARGE_INT
|
|
{
|
|
struct {DWORD lowVal; LONG highVal;};
|
|
INT64 largeVal;
|
|
};
|
|
|
|
union XLARGE_UINT
|
|
{
|
|
struct {DWORD lowUVal; DWORD highVal;};
|
|
UINT64 largeVal;
|
|
};
|
|
|
|
|
|
|
|
/*=========================================================
|
|
Optimized math functions
|
|
==========================================================*/
|
|
|
|
inline float fSinCosRecurse (float fRet, float fRad, const float fRad2, float fRadPow, float fFact, const int nPrec, int nCur)
|
|
{
|
|
fRadPow *= -fRad2;
|
|
fFact *= nCur++;
|
|
fFact *= nCur++;
|
|
|
|
fRet += fRadPow / fFact;
|
|
|
|
if(nCur < nPrec)
|
|
return fSinCosRecurse(fRet, fRad, fRad2, fRadPow, fFact, nPrec, nCur);
|
|
else
|
|
return fRet;
|
|
}
|
|
|
|
inline float fSin (float fRad, int nPrec=4)
|
|
{
|
|
while(fRad > M_PI) fRad -= (M_PI*2.0f);
|
|
while(fRad < -M_PI) fRad += (M_PI*2.0f);
|
|
|
|
const float fRad2 = (fRad*fRad);
|
|
float fRet = fRad;
|
|
|
|
return fSinCosRecurse(fRet, fRad, fRad2, fRad, 1.0f, (nPrec << 1) + 1, 2);
|
|
}
|
|
|
|
inline float fCos (float fRad, int nPrec=4)
|
|
{
|
|
while(fRad > M_PI) fRad -= (M_PI*2.0f);
|
|
while(fRad < -M_PI) fRad += (M_PI*2.0f);
|
|
|
|
const float fRad2 = (fRad*fRad);
|
|
float fRet = 1.0f;
|
|
|
|
return fSinCosRecurse(fRet, fRad, fRad2, 1.0f, 1.0f, (nPrec << 1) + 1, 1);
|
|
}
|
|
|
|
inline BOOL CloseFloat(float f1, float f2, float precision=LARGE_EPSILON)
|
|
{
|
|
return fabsf(f1-f2) <= precision;
|
|
}
|
|
|
|
|
|
/*=========================================================
|
|
2-D Vector
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Vect2
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
};
|
|
float ptr[2];
|
|
};
|
|
|
|
|
|
inline Vect2() {}
|
|
inline Vect2(const Vect2 &v) : x(v.x), y(v.y) {}
|
|
explicit inline Vect2(float a) : x(a), y(a) {}
|
|
inline Vect2(float a, float b) : x(a), y(b) {}
|
|
explicit inline Vect2(const Vect &v);
|
|
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Vect2 operator+(const Vect2 &v) const {return Vect2(x+v.x, y+v.y);}
|
|
inline Vect2 operator-(const Vect2 &v) const {return Vect2(x-v.x, y-v.y);}
|
|
inline Vect2 operator*(const Vect2 &v) const {return Vect2(x*v.x, y*v.y);}
|
|
inline Vect2 operator/(const Vect2 &v) const {return Vect2(x/v.x, y/v.y);}
|
|
|
|
inline Vect2 operator+(float f) const {return Vect2( x+f, y+f);}
|
|
inline Vect2 operator-(float f) const {return Vect2( x-f, y-f);}
|
|
inline Vect2 operator*(float f) const {return Vect2( x*f, y*f);}
|
|
inline Vect2 operator/(float f) const {return Vect2( x/f, y/f);}
|
|
|
|
inline float operator|(const Vect2 &v) const {return (x*v.x)+(y*v.y);}
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Vect2& operator+=(const Vect2 &v) {return (*this)=(*this)+v;}
|
|
inline Vect2& operator-=(const Vect2 &v) {return (*this)=(*this)-v;}
|
|
inline Vect2& operator*=(const Vect2 &v) {return (*this)=(*this)*v;}
|
|
inline Vect2& operator/=(const Vect2 &v) {return (*this)=(*this)/v;}
|
|
|
|
inline Vect2& operator+=(float f) {return (*this)=(*this)+f;}
|
|
inline Vect2& operator-=(float f) {return (*this)=(*this)-f;}
|
|
inline Vect2& operator*=(float f) {return (*this)=(*this)*f;}
|
|
inline Vect2& operator/=(float f) {return (*this)=(*this)/f;}
|
|
|
|
inline Vect2& operator=(const Vect &v);
|
|
inline Vect2& operator=(const Vect2 &v) {x=v.x; y=v.y; return *this;}
|
|
inline Vect2& operator=(float val) {x=val; y=val; return *this;}
|
|
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Vect2 &v) const {return (v.x==x)&&(v.y==y);}
|
|
inline BOOL operator!=(const Vect2 &v) const {return (v.x!=x)||(v.y!=y);}
|
|
|
|
inline Vect2 operator-() const {return Vect2(-x, -y);}
|
|
|
|
|
|
////////////////////////
|
|
//Type casting
|
|
inline operator float*() {return ptr;}
|
|
|
|
|
|
////////////////////////
|
|
//Other
|
|
inline Vect2& Set(float a, float b) {x=a; y=b; return *this;}
|
|
|
|
inline float Len() const {return (float)sqrt((double)(x*x)+(y*y));}
|
|
|
|
inline float Dist(const Vect2 &v) const
|
|
{
|
|
//only do this stuff once
|
|
float a=(x-v.x),b=(y-v.y);
|
|
return (float)sqrt((double)(a*a)+(b*b));
|
|
}
|
|
|
|
inline Vect2& ClampMin(float val) {if(x < val) x = val; if(y < val) y = val; return *this;}
|
|
inline Vect2& ClampMin(const Vect2 &v) {if(x < v.x) x = v.x; if(y < v.y) y = v.y; return *this;}
|
|
|
|
inline Vect2& ClampMax(float val) {if(x > val) x = val; if(y > val) y = val; return *this;}
|
|
inline Vect2& ClampMax(const Vect2 &v) {if(x > v.x) x = v.x; if(y > v.y) y = v.y; return *this;}
|
|
|
|
static inline Vect2 Max(const Vect2 &v, float val) {return Vect2(MAX(v.x, val), MAX(v.y, val));}
|
|
static inline Vect2 Max(const Vect2 &v1, const Vect2 &v2) {return Vect2(MAX(v1.x, v2.x), MAX(v1.y, v2.y));}
|
|
|
|
static inline Vect2 Min(const Vect2 &v, float val) {return Vect2(MIN(v.x, val), MIN(v.y, val));}
|
|
static inline Vect2 Min(const Vect2 &v1, const Vect2 &v2) {return Vect2(MIN(v1.x, v2.x), MIN(v1.y, v2.y));}
|
|
|
|
inline Vect2& Abs() {x=fabs(x); y=fabs(y); return *this;}
|
|
inline Vect2 GetAbs() const {return Vect2(*this).Abs();}
|
|
|
|
inline Vect2& Floor() {x=floorf(x); y=floorf(y); return *this;}
|
|
inline Vect2 GetFloor() const {return Vect2(*this).Floor();}
|
|
|
|
inline Vect2& Ceil() {x=ceilf(x); y=ceilf(y); return *this;}
|
|
inline Vect2 GetCeil() const {return Vect2(*this).Ceil();}
|
|
|
|
inline BOOL CloseTo(const Vect2 &v, float epsilon=EPSILON) const
|
|
{
|
|
return CloseFloat(x, v.x, epsilon) && CloseFloat(y, v.y, epsilon);
|
|
}
|
|
|
|
inline Vect2& Norm()
|
|
{
|
|
float len=Len();
|
|
|
|
if(len != 0)
|
|
{
|
|
len = 1 / len;
|
|
x *= len; y *= len;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect2 GetNorm()
|
|
{
|
|
return Vect2(*this).Norm();
|
|
}
|
|
|
|
inline float Dot(const Vect2 &v) const
|
|
{
|
|
return v|(*this);
|
|
}
|
|
|
|
inline Vect2& Cross()
|
|
{
|
|
return (*this) = GetCross();
|
|
}
|
|
|
|
inline Vect2 GetCross() const
|
|
{
|
|
return Vect2(y, -x);
|
|
}
|
|
|
|
inline Vect2& SwapVals() {float newY = x; x = y; y = newY; return *this;}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Vect2 &v)
|
|
{
|
|
return s << v.x << v.y;
|
|
}
|
|
};
|
|
|
|
typedef Vect2 UVCoord;
|
|
|
|
inline Vect2 operator/(float f, const Vect2 &v) {return Vect2(f/v.x, f/v.y);}
|
|
inline Vect2 operator*(float f, const Vect2 &v) {return Vect2(f*v.x, f*v.y);}
|
|
|
|
|
|
struct CompactVect
|
|
{
|
|
float x, y, z;
|
|
|
|
inline CompactVect() {}
|
|
inline CompactVect(const Vect &v);
|
|
|
|
inline CompactVect& operator=(const Vect &v);
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
3-D Vector (128bit aligned)
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Vect
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
};
|
|
#ifdef USE_SSE
|
|
__m128 m;
|
|
#endif
|
|
float ptr[4];
|
|
};
|
|
|
|
explicit inline Vect(const Vect4 &v4);
|
|
|
|
#ifdef USE_SSE
|
|
inline Vect() {w = 0.0f;}
|
|
explicit inline Vect(const Vect2 &v2) {m = _mm_setr_ps(v2.x, v2.y, 0.0f, 0.0f);}
|
|
inline Vect(const Vect& v) {m = v.m;}
|
|
explicit inline Vect(float f) {m = _mm_load1_ps(&f); w = 0.0f;}
|
|
inline Vect(float a, float b, float c) {m = _mm_setr_ps(a, b, c, 0.0f);}
|
|
inline Vect(const CompactVect &v) {m = _mm_setr_ps(v.x, v.y, v.z, 0.0f);}
|
|
inline Vect(float a, float b, float c, float d) {m = _mm_setr_ps(a, b, c, d);}
|
|
explicit inline Vect(__m128 val) : m(val) {}
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Vect operator+(const Vect &v) const {return Vect(_mm_add_ps(m, v.m));}
|
|
inline Vect operator-(const Vect &v) const {return Vect(_mm_sub_ps(m, v.m));}
|
|
inline Vect operator*(const Vect &v) const {return Vect(_mm_mul_ps(m, v.m));}
|
|
inline Vect operator/(const Vect &v) const {__m128 tmp = _mm_div_ps(m, v.m); tmp.m128_f32[3] = 0.0f; return Vect(tmp);}
|
|
|
|
inline Vect operator+(float f) const {Vect val(_mm_add_ps(m, _mm_set1_ps(f))); val.w = 0.0f; return val;}
|
|
inline Vect operator-(float f) const {Vect val(_mm_sub_ps(m, _mm_set1_ps(f))); val.w = 0.0f; return val;}
|
|
inline Vect operator*(float f) const {return Vect(_mm_mul_ps(m, _mm_set1_ps(f)));}
|
|
inline Vect operator/(float f) const {__m128 tmp = _mm_div_ps(m, _mm_set1_ps(f)); tmp.m128_f32[3] = 0.0f; return Vect(tmp);}
|
|
|
|
inline float operator|(const Vect &v) const {return Dot(v);}
|
|
inline Vect operator^(const Vect &v) const {return Cross(v);}
|
|
|
|
inline Vect operator-() const {return Vect(-x, -y, -z);}
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Vect& operator+=(const Vect &v) {m = _mm_add_ps(m, v.m); return *this;}
|
|
inline Vect& operator-=(const Vect &v) {m = _mm_sub_ps(m, v.m); return *this;}
|
|
inline Vect& operator*=(const Vect &v) {m = _mm_mul_ps(m, v.m); return *this;}
|
|
inline Vect& operator/=(const Vect &v) {m = _mm_div_ps(m, v.m); w=0.0f; return *this;}
|
|
|
|
inline Vect& operator+=(float f) {m = _mm_add_ps(m, _mm_set1_ps(f)); w=0.0f; return *this;}
|
|
inline Vect& operator-=(float f) {m = _mm_sub_ps(m, _mm_set1_ps(f)); w=0.0f; return *this;}
|
|
inline Vect& operator*=(float f) {m = _mm_mul_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Vect& operator/=(float f) {m = _mm_div_ps(m, _mm_set1_ps(f)); w=0.0f; return *this;}
|
|
|
|
inline Vect& operator=(const Vect &v) {
|
|
_mm_store_ps(ptr, v.m);
|
|
m = v.m;
|
|
return *this;
|
|
}
|
|
inline Vect& operator=(const Vect2 &v2) {x = v2.x; y = v2.y; z = w = 0.0f; return *this;}
|
|
inline Vect& operator=(float f) {m = _mm_set1_ps(f); w=0.0f; return *this;}
|
|
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Vect &v) const {return CloseTo(v);}
|
|
inline BOOL operator!=(const Vect &v) const {return !CloseTo(v);}
|
|
|
|
|
|
////////////////////////
|
|
//Other
|
|
inline Vect& Set(float a, float b) {m = _mm_setr_ps(a, b, 0.0f, 0.0f); return *this;}
|
|
inline Vect& Set(float a, float b, float c) {m = _mm_setr_ps(a, b, c, 0.0f); return *this;}
|
|
|
|
//as far as I know an SSE dot is not really any better than an FPU dot
|
|
inline float Dot(const Vect &v) const
|
|
{
|
|
__m128 mulVal = _mm_mul_ps(m, v.m); //mul = xyzw*v.xyzw
|
|
__m128 addVal = _mm_add_ps(_mm_movehl_ps(mulVal, mulVal), mulVal); //add = mul.yzyz+mul.xyzw
|
|
addVal = _mm_add_ps(_mm_shuffle_ps(addVal, addVal, 0x55), addVal); //add = add.yyyy+add.xyxw
|
|
return addVal.m128_f32[0]; //return add.x
|
|
}
|
|
|
|
//same with cross.
|
|
inline Vect Cross(const Vect &v) const
|
|
{
|
|
return Vect(_mm_sub_ps(_mm_mul_ps(_mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 0, 2, 1)), _mm_shuffle_ps(v.m, v.m, _MM_SHUFFLE(3, 1, 0, 2))),
|
|
_mm_mul_ps(_mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 1, 0, 2)), _mm_shuffle_ps(v.m, v.m, _MM_SHUFFLE(3, 0, 2, 1)))));
|
|
|
|
}
|
|
|
|
inline float Len() const
|
|
{
|
|
float dotVal = Dot(*this);
|
|
return (dotVal > 0.0f) ? sqrtf(dotVal) : 0.0f;
|
|
}
|
|
|
|
inline float Dist(const Vect &v) const
|
|
{
|
|
Vect subVal = *this - v;
|
|
float dotVal = subVal.Dot(subVal);
|
|
return (dotVal > 0.0f) ? sqrtf(dotVal) : 0.0f;
|
|
}
|
|
|
|
inline Vect& Norm()
|
|
{
|
|
float dotVal = Dot(*this);
|
|
if(dotVal > 0.0f)
|
|
m = _mm_mul_ps(m, _mm_set1_ps(1.0f/sqrtf(dotVal)));
|
|
else
|
|
m = _mm_setzero_ps();
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline BOOL CloseTo(const Vect &v, float epsilon=EPSILON) const
|
|
{
|
|
__m128 subVal = _mm_sub_ps(m, v.m);
|
|
return (fabs(subVal.m128_f32[0]) < epsilon) &&
|
|
(fabs(subVal.m128_f32[1]) < epsilon) &&
|
|
(fabs(subVal.m128_f32[2]) < epsilon);
|
|
}
|
|
|
|
inline Vect& SetZero() {m = _mm_setzero_ps(); return *this;}
|
|
|
|
inline Vect& ClampMin(float val) {m = _mm_max_ps(m, _mm_set1_ps(val)); w = 0.0f; return *this;}
|
|
inline Vect& ClampMin(const Vect &v) {m = _mm_max_ps(m, v.m); w = 0.0f; return *this;}
|
|
|
|
inline Vect& ClampMax(float val) {m = _mm_min_ps(m, _mm_set1_ps(val)); w = 0.0f; return *this;}
|
|
inline Vect& ClampMax(const Vect &v) {m = _mm_min_ps(m, v.m); w = 0.0f; return *this;}
|
|
|
|
static inline Vect Max(const Vect &v, float val) {Vect out(_mm_max_ps(v.m, _mm_set1_ps(val))); out.w = 0.0f; return out;}
|
|
static inline Vect Max(const Vect &v1, const Vect &v2) {Vect out(_mm_max_ps(v1.m, v2.m)); out.w = 0.0f; return out;}
|
|
|
|
static inline Vect Min(const Vect &v, float val) {Vect out(_mm_min_ps(v.m, _mm_set1_ps(val))); out.w = 0.0f; return out;}
|
|
static inline Vect Min(const Vect &v1, const Vect &v2) {Vect out(_mm_min_ps(v1.m, v2.m)); out.w = 0.0f; return out;}
|
|
#else
|
|
inline Vect() {w=0.0f;}
|
|
explicit inline Vect(float f) : x(f), y(f), z(f), w(0.0f) {}
|
|
inline Vect(float a, float b, float c) : x(a), y(b), z(c), w(0.0f) {}
|
|
inline Vect(float a, float b, float c, float d): x(a), y(b), z(c), w(d) {}
|
|
inline Vect(const CompactVect &v) {x = v.x; y = v.y; z = v.z; w = 0.0f;}
|
|
explicit inline Vect(const Vect2 &v2) : x(v2.x), y(v2.y), z(0.0f), w(0.0f) {}
|
|
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Vect operator+(const Vect &v) const {return Vect(x+v.x, y+v.y, z+v.z);}
|
|
inline Vect operator-(const Vect &v) const {return Vect(x-v.x, y-v.y, z-v.z);}
|
|
inline Vect operator*(const Vect &v) const {return Vect(x*v.x, y*v.y, z*v.z);}
|
|
inline Vect operator/(const Vect &v) const {return Vect(x/v.x, y/v.y, z/v.z);}
|
|
|
|
inline Vect operator+(float f) const {return Vect( x+f, y+f, z+f);}
|
|
inline Vect operator-(float f) const {return Vect( x-f, y-f, z-f);}
|
|
inline Vect operator*(float f) const {return Vect( x*f, y*f, z*f);}
|
|
inline Vect operator/(float f) const
|
|
{
|
|
f = 1 / f;
|
|
return Vect(x*f, y*f, z*f);
|
|
}
|
|
|
|
inline float operator|(const Vect &v) const {return (x*v.x)+(y*v.y)+(z*v.z);}
|
|
inline Vect operator^(const Vect &v) const {return Vect((y*v.z)-(z*v.y), (z*v.x)-(x*v.z), (x*v.y)-(y*v.x));}
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Vect& operator+=(const Vect &v) {return (*this)=(*this)+v;}
|
|
inline Vect& operator-=(const Vect &v) {return (*this)=(*this)-v;}
|
|
inline Vect& operator*=(const Vect &v) {return (*this)=(*this)*v;}
|
|
inline Vect& operator/=(const Vect &v) {return (*this)=(*this)/v;}
|
|
|
|
inline Vect& operator+=(float f) {return (*this)=(*this)+f;}
|
|
inline Vect& operator-=(float f) {return (*this)=(*this)-f;}
|
|
inline Vect& operator*=(float f) {return (*this)=(*this)*f;}
|
|
inline Vect& operator/=(float f) {return (*this)=(*this)/f;}
|
|
|
|
inline Vect& operator^=(const Vect &v) {return (*this)=(*this)^v;}
|
|
|
|
inline Vect& operator=(const Vect2 &v2) {x = v2.x; y = v2.y; z = w = 0.0f; return *this;}
|
|
inline Vect& operator=(const Vect &v) {x=v.x; y=v.y; z=v.z; return *this;}
|
|
inline Vect& operator=(float f) {x=f; y=f; z=f; return *this;}
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Vect &v) const {return CloseTo(v);}
|
|
inline BOOL operator!=(const Vect &v) const {return !CloseTo(v);}
|
|
|
|
inline Vect operator-() const {return Vect(-x, -y, -z);}
|
|
|
|
|
|
////////////////////////
|
|
//Other
|
|
inline Vect& Set(float a, float b) {x=a; y=b; z=0.0f; return *this;}
|
|
inline Vect& Set(float a, float b, float c) {x=a; y=b; z=c; return *this;}
|
|
|
|
inline float Len() const {return (float)sqrt((double)(x*x)+(y*y)+(z*z));}
|
|
|
|
inline float Dist(const Vect &v) const
|
|
{
|
|
//only do this stuff once
|
|
float a=(x-v.x),b=(y-v.y),c=(z-v.z);
|
|
return (float)sqrt((double)(a*a)+(b*b)+(c*c));
|
|
}
|
|
|
|
inline Vect& Norm()
|
|
{
|
|
float len=Len();
|
|
|
|
if(len != 0.0f)
|
|
{
|
|
len = 1.0f / len;
|
|
|
|
x *= len; y *= len; z *= len;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline float Dot(const Vect &v) const {return (*this)|v;}
|
|
inline Vect Cross(const Vect &v) const {return (*this)^v;}
|
|
|
|
inline BOOL CloseTo(const Vect &v, float epsilon=EPSILON) const
|
|
{
|
|
return CloseFloat(x, v.x, epsilon) && CloseFloat(y, v.y, epsilon) && CloseFloat(z, v.z, epsilon);
|
|
}
|
|
|
|
inline Vect& SetZero() {x = y = z = w = 0.0f; return *this;}
|
|
|
|
inline Vect& ClampMin(float val) {if(x < val) x = val; if(y < val) y = val; if(z < val) z = val; return *this;}
|
|
inline Vect& ClampMin(const Vect &v) {if(x < v.x) x = v.x; if(y < v.y) y = v.y; if(z < v.z) z = v.z; return *this;}
|
|
|
|
inline Vect& ClampMax(float val) {if(x > val) x = val; if(y > val) y = val; if(z > val) z = val; return *this;}
|
|
inline Vect& ClampMax(const Vect &v) {if(x > v.x) x = v.x; if(y > v.y) y = v.y; if(z > v.z) z = v.z; return *this;}
|
|
|
|
static inline Vect Max(const Vect &v, float val) {return Vect(MAX(v.x, val), MAX(v.y, val), MAX(v.z, val));}
|
|
static inline Vect Max(const Vect &v1, const Vect &v2) {return Vect(MAX(v1.x, v2.x), MAX(v1.y, v2.y), MAX(v1.z, v2.z));}
|
|
|
|
static inline Vect Min(const Vect &v, float val) {return Vect(MIN(v.x, val), MIN(v.y, val), MIN(v.z, val));}
|
|
static inline Vect Min(const Vect &v1, const Vect &v2) {return Vect(MIN(v1.x, v2.x), MIN(v1.y, v2.y), MIN(v1.z, v2.z));}
|
|
#endif
|
|
|
|
inline Vect& Abs() {x=fabsf(x); y=fabsf(y); z=fabsf(z); return *this;}
|
|
|
|
inline Vect& Floor() {x=floorf(x); y=floorf(y); z=floorf(z); return *this;}
|
|
inline Vect GetFloor() const {return Vect(*this).Floor();}
|
|
|
|
inline Vect& Ceil() {x=ceilf(x); y=ceilf(y); z=ceilf(z); return *this;}
|
|
inline Vect GetCeil() const {return Vect(*this).Ceil();}
|
|
|
|
static inline Vect Zero() {return Vect().SetZero();}
|
|
|
|
inline Vect GetClampMax(float f) {return Vect(*this).ClampMax(f);}
|
|
inline Vect GetClampMin(float f) {return Vect(*this).ClampMin(f);}
|
|
|
|
float DistFromPlane(const Plane &p) const;
|
|
|
|
inline Vect& TransformPoint(const Matrix &m);
|
|
inline Vect& TransformVector(const Matrix &m);
|
|
|
|
inline Vect GetTransformedPoint(const Matrix &m) const {return Vect(*this).TransformPoint(m);}
|
|
inline Vect GetTransformedVector(const Matrix &m) const {return Vect(*this).TransformVector(m);}
|
|
|
|
inline void MirrorByPlane(const Plane &p);
|
|
inline void MirrorByVector(const Vect &v);
|
|
|
|
inline operator float*() {return ptr;}
|
|
|
|
inline Vect GetAbs() const {return Vect(*this).Abs();}
|
|
|
|
inline Vect GetNorm() const
|
|
{
|
|
return Vect(*this).Norm();
|
|
}
|
|
|
|
inline Vect &MakeFromRGB(DWORD dwRGB)
|
|
{
|
|
x = RGB_Rf(dwRGB);
|
|
y = RGB_Gf(dwRGB);
|
|
z = RGB_Bf(dwRGB);
|
|
w = 0.0f;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline void GetNormalByteValue()
|
|
{
|
|
Norm();
|
|
x = ((x + 1.0f) * 0.5f) * 255.0f;
|
|
y = ((y + 1.0f) * 0.5f) * 255.0f;
|
|
z = ((z + 1.0f) * 0.5f) * 255.0f;
|
|
}
|
|
|
|
inline void GetNormalWordValue()
|
|
{
|
|
Norm();
|
|
x = ((x + 1.0f) * 0.5f) * 65535.0f;
|
|
y = ((y + 1.0f) * 0.5f) * 65535.0f;
|
|
z = ((z + 1.0f) * 0.5f) * 65535.0f;
|
|
}
|
|
|
|
inline DWORD GetRGB() const {return Vect_to_RGB(*this)|0xFF000000;}
|
|
|
|
Vect GetInterpolationTangent(const Vect &prev, const Vect &next) const;
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Vect &v)
|
|
{
|
|
s.Serialize(v.ptr, sizeof(float)*3);
|
|
return s;
|
|
}
|
|
|
|
static inline Serializer& SerializeList(Serializer &s, List<Vect> &list)
|
|
{
|
|
UINT num;
|
|
if(s.IsLoading())
|
|
{
|
|
s << num;
|
|
list.SetSize(num);
|
|
}
|
|
else
|
|
{
|
|
num = list.Num();
|
|
s << num;
|
|
}
|
|
|
|
for(unsigned int i=0; i<num; i++)
|
|
s << list[i];
|
|
|
|
return s;
|
|
}
|
|
|
|
static inline Serializer& SerializeArray(Serializer &s, Vect *array, UINT num)
|
|
{
|
|
for(unsigned int i=0; i<num; i++)
|
|
s << array[i];
|
|
|
|
return s;
|
|
}
|
|
};
|
|
|
|
typedef Vect Color3, UVWCoord, Vect3;
|
|
|
|
|
|
/*=========================================================
|
|
4-D Vector
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Vect4
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
};
|
|
#ifdef USE_SSE
|
|
__m128 m;
|
|
#endif
|
|
float ptr[4];
|
|
};
|
|
|
|
|
|
inline Vect4() {}
|
|
|
|
#ifdef USE_SSE
|
|
inline Vect4(float a, float b, float c, float d) {m = _mm_setr_ps(a, b, c, d);}
|
|
explicit inline Vect4(const Vect2 &v2) {m = _mm_setr_ps(v2.x, v2.y, 0.0f, 1.0f);}
|
|
explicit inline Vect4(const Vect &v) {m = v.m; w = 1.0f;}
|
|
inline Vect4(const Vect &v, float wIn) {m = v.m; w = wIn;}
|
|
explicit inline Vect4(__m128 m2) : m(m2) {}
|
|
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Vect4 operator+(const Vect4 &v) const {return Vect4(_mm_add_ps(m, v.m));}
|
|
inline Vect4 operator-(const Vect4 &v) const {return Vect4(_mm_sub_ps(m, v.m));}
|
|
inline Vect4 operator*(const Vect4 &v) const {return Vect4(_mm_mul_ps(m, v.m));}
|
|
inline Vect4 operator/(const Vect4 &v) const {return Vect4(_mm_div_ps(m, v.m));}
|
|
|
|
inline Vect4 operator+(float f) const {return Vect4(_mm_add_ps(m, _mm_set1_ps(f)));}
|
|
inline Vect4 operator-(float f) const {return Vect4(_mm_sub_ps(m, _mm_set1_ps(f)));}
|
|
inline Vect4 operator*(float f) const {return Vect4(_mm_mul_ps(m, _mm_set1_ps(f)));}
|
|
inline Vect4 operator/(float f) const {return Vect4(_mm_div_ps(m, _mm_set1_ps(f)));}
|
|
|
|
inline float operator|(const Vect4 &v) const
|
|
{
|
|
__m128 mulVal = _mm_mul_ps(m, v.m); //mul = xyzw*v.xyzw
|
|
__m128 addVal = _mm_add_ps(_mm_movehl_ps(mulVal, mulVal), mulVal); //add = mul.yzyz+mul.xyzw
|
|
addVal = _mm_add_ps(_mm_shuffle_ps(addVal, addVal, 0x55), addVal); //add = add.yyyy+add.xyxw
|
|
return addVal.m128_f32[0]; //return add.x
|
|
}
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Vect4& operator+=(const Vect4 &v) {m = _mm_add_ps(m, v.m); return *this;}
|
|
inline Vect4& operator-=(const Vect4 &v) {m = _mm_sub_ps(m, v.m); return *this;}
|
|
inline Vect4& operator*=(const Vect4 &v) {m = _mm_mul_ps(m, v.m); return *this;}
|
|
inline Vect4& operator/=(const Vect4 &v) {m = _mm_div_ps(m, v.m); return *this;}
|
|
|
|
inline Vect4& operator+=(float f) {m = _mm_add_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Vect4& operator-=(float f) {m = _mm_sub_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Vect4& operator*=(float f) {m = _mm_mul_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Vect4& operator/=(float f) {m = _mm_div_ps(m, _mm_set1_ps(f)); return *this;}
|
|
|
|
inline Vect4& operator=(const Vect4 &v) {m=v.m; return *this;}
|
|
inline Vect4& operator=(float f) {m = _mm_set1_ps(f); return *this;}
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Vect4 &v) const {return CloseTo(v);}
|
|
inline BOOL operator!=(const Vect4 &v) const {return !CloseTo(v);}
|
|
|
|
|
|
////////////////////////
|
|
//Other
|
|
inline Vect4& Set(float a, float b) {x=a; y=b; z=0.0f; w=1.0f; return *this;}
|
|
inline Vect4& Set(float a, float b, float c) {x=a; y=b; z=c; w=1.0f; return *this;}
|
|
inline Vect4& Set(float a, float b, float c, float d) {x=a; y=b; z=c; w=d; return *this;}
|
|
|
|
inline BOOL CloseTo(const Vect4 &v, float epsilon=EPSILON) const
|
|
{
|
|
Vect4 subVal = (*this - v);
|
|
return (fabsf(subVal.x) < epsilon) &&
|
|
(fabsf(subVal.y) < epsilon) &&
|
|
(fabsf(subVal.z) < epsilon) &&
|
|
(fabsf(subVal.w) < epsilon);
|
|
}
|
|
|
|
inline Vect4& SetZero() {m = _mm_setzero_ps(); return *this;}
|
|
#else
|
|
inline Vect4(float a, float b, float c, float d) : x(a), y(b), z(c), w(d) {}
|
|
explicit inline Vect4(const Vect2 &v2) : x(v2.x), y(v2.y), z(0.0f), w(1.0f) {}
|
|
explicit inline Vect4(const Vect &v) : x(v.x), y(v.y), z(v.z), w(1.0f) {}
|
|
inline Vect4(const Vect &v, float w) : x(v.x), y(v.y), z(v.z), w(w) {}
|
|
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Vect4 operator+(const Vect4 &v) const {return Vect4(x+v.x, y+v.y, z+v.z, w+v.w);}
|
|
inline Vect4 operator-(const Vect4 &v) const {return Vect4(x-v.x, y-v.y, z-v.z, w-v.w);}
|
|
inline Vect4 operator*(const Vect4 &v) const {return Vect4(x*v.x, y*v.y, z*v.z, w*v.w);}
|
|
inline Vect4 operator/(const Vect4 &v) const {return Vect4(x/v.x, y/v.y, z/v.z, w/v.w);}
|
|
|
|
inline Vect4 operator+(float f) const {return Vect4( x+f, y+f, z+f, w+f);}
|
|
inline Vect4 operator-(float f) const {return Vect4( x-f, y-f, z-f, w-f);}
|
|
inline Vect4 operator*(float f) const {return Vect4( x*f, y*f, z*f, w*f);}
|
|
inline Vect4 operator/(float f) const
|
|
{
|
|
f = 1 / f;
|
|
return Vect4(x*f, y*f, z*f, w*f);
|
|
}
|
|
|
|
inline float operator|(const Vect4 &v) const {return (x*v.x)+(y*v.y)+(z*v.z)+(w*v.w);}
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Vect4& operator+=(const Vect4 &v) {return (*this)=(*this)+v;}
|
|
inline Vect4& operator-=(const Vect4 &v) {return (*this)=(*this)-v;}
|
|
inline Vect4& operator*=(const Vect4 &v) {return (*this)=(*this)*v;}
|
|
inline Vect4& operator/=(const Vect4 &v) {return (*this)=(*this)/v;}
|
|
|
|
inline Vect4& operator+=(float f) {return (*this)=(*this)+f;}
|
|
inline Vect4& operator-=(float f) {return (*this)=(*this)-f;}
|
|
inline Vect4& operator*=(float f) {return (*this)=(*this)*f;}
|
|
inline Vect4& operator/=(float f) {return (*this)=(*this)/f;}
|
|
|
|
inline Vect4& operator=(const Vect4 &v) {x=v.x; y=v.y; z=v.z; w=v.w; return *this;}
|
|
inline Vect4& operator=(float f) {x=f; y=f; z=f; w=f; return *this;}
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Vect4 &v) const {return (v.x==x)&&(v.y==y)&&(v.z==z);}
|
|
inline BOOL operator!=(const Vect4 &v) const {return (v.x!=x)||(v.y!=y)||(v.z!=z);}
|
|
|
|
|
|
////////////////////////
|
|
//Other
|
|
inline Vect4& Set(float a, float b) {x=a; y=b; z=0.0f; w=1.0f; return *this;}
|
|
inline Vect4& Set(float a, float b, float c) {x=a; y=b; z=c; w=1.0f; return *this;}
|
|
inline Vect4& Set(float a, float b, float c, float d) {x=a; y=b; z=c; w=d; return *this;}
|
|
|
|
inline BOOL CloseTo(const Vect4 &v, float epsilon=EPSILON) const
|
|
{
|
|
return CloseFloat(x, v.x, epsilon) && CloseFloat(y, v.y, epsilon) && CloseFloat(z, v.z, epsilon) && CloseFloat(w, v.w, epsilon);
|
|
}
|
|
|
|
inline Vect4& SetZero() {x = y = z = w = 0.0f; return *this;}
|
|
|
|
#endif
|
|
|
|
inline Vect4 operator-() const {return Vect4(-x, -y, -z, -w);}
|
|
|
|
inline Vect4& Abs() {x=fabs(x); y=fabs(y); z=fabs(z); w=fabs(w); return *this;}
|
|
inline Vect4 GetAbs() {Vect4 temp(*this); return temp.Abs();}
|
|
|
|
inline Vect4& Floor() {x=floorf(x); y=floorf(y); z=floorf(z); w=floorf(w); return *this;}
|
|
inline Vect4 GetFloor() const {return Vect4(*this).Floor();}
|
|
|
|
inline Vect4& Ceil() {x=ceilf(x); y=ceilf(y); z=ceilf(z); w=ceilf(w); return *this;}
|
|
inline Vect4 GetCeil() const {return Vect4(*this).Ceil();}
|
|
|
|
static inline Vect4 Zero() {return Vect4().SetZero();}
|
|
|
|
inline Vect4& NormXYZ()
|
|
{
|
|
float multiplyVal = 1.0f/sqrtf((x*x)+(y*y)+(z*z));
|
|
|
|
x *= multiplyVal;
|
|
y *= multiplyVal;
|
|
z *= multiplyVal;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect4 GetNormXYZ() {return Vect4(*this).NormXYZ();}
|
|
|
|
inline Vect4& NormFull()
|
|
{
|
|
float multiplyVal = 1.0f/sqrtf((x*x)+(y*y)+(z*z)+(w*w));
|
|
|
|
x *= multiplyVal;
|
|
y *= multiplyVal;
|
|
z *= multiplyVal;
|
|
w *= multiplyVal;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect4 GetNormFull() {return Vect4(*this).NormFull();}
|
|
|
|
//...don't ask. it's just a name I sort of invented out of thin air
|
|
inline Vect4& SquarifyColor()
|
|
{
|
|
register int highest = (x>y) ? 0 : 1;
|
|
if(z > ptr[highest])
|
|
highest = 2;
|
|
|
|
float offset = 1.0f-ptr[highest];
|
|
|
|
x += offset;
|
|
y += offset;
|
|
z += offset;
|
|
|
|
return (*this).ClampColor();
|
|
}
|
|
|
|
inline Vect4 GetSquarifiedColor() {return Vect4(*this).SquarifyColor();}
|
|
|
|
inline Vect4& ClampColor()
|
|
{
|
|
for(register int i=0; i<4; i++)
|
|
{
|
|
if(ptr[i] < 0.0f)
|
|
ptr[i] = 0.0f;
|
|
else if(ptr[i] > 1.0f)
|
|
ptr[i] = 1.0f;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect4 GetClampedColor() {return Vect4(*this).ClampColor();}
|
|
|
|
inline Vect4& DesaturateColor()
|
|
{
|
|
float average = (x+y+z)*0.3333333333f;
|
|
|
|
x = y = z = average;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect4 GetDesaturatedColor() {return Vect4(*this).DesaturateColor();}
|
|
|
|
inline Vect4& MakeFromRGBA(DWORD dwRGBA)
|
|
{
|
|
x = RGB_Rf(dwRGBA);
|
|
y = RGB_Gf(dwRGBA);
|
|
z = RGB_Bf(dwRGBA);
|
|
w = RGB_Af(dwRGBA);
|
|
return *this;
|
|
}
|
|
|
|
inline DWORD GetRGBA() const {return Vect4_to_RGBA(*this);}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Vect4 &v)
|
|
{
|
|
return s << v.x << v.y << v.z << v.w;
|
|
}
|
|
};
|
|
typedef Vect4 Color4;
|
|
|
|
|
|
/*=========================================================
|
|
Quaternion
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Quat
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
};
|
|
#ifdef USE_SSE
|
|
__m128 m;
|
|
#endif
|
|
float ptr[4];
|
|
};
|
|
|
|
inline Quat() {}
|
|
explicit inline Quat(const AxisAngle &aa) {MakeFromAxisAngle(aa);}
|
|
Quat(const Euler &e);
|
|
|
|
#ifdef USE_SSE
|
|
inline Quat(float a, float b, float c, float d) {m = _mm_setr_ps(a, b, c, d);}
|
|
explicit inline Quat(const Vect &v) : m(v.m), w(1.0f) {}
|
|
inline Quat(const Vect &v, float wIn) : m(v.m), w(wIn) {}
|
|
explicit inline Quat(__m128 m2) : m(m2) {}
|
|
|
|
|
|
/////////////////////////
|
|
//Arithmetic operators
|
|
inline Quat operator+(const Quat &v) const {return Quat(_mm_add_ps(m, v.m));}
|
|
inline Quat operator-(const Quat &v) const {return Quat(_mm_sub_ps(m, v.m));}
|
|
|
|
inline Quat operator+(float f) const {return Quat(_mm_add_ps(m, _mm_set1_ps(f)));}
|
|
inline Quat operator-(float f) const {return Quat(_mm_sub_ps(m, _mm_set1_ps(f)));}
|
|
inline Quat operator*(float f) const {return Quat(_mm_mul_ps(m, _mm_set1_ps(f)));}
|
|
inline Quat operator/(float f) const {return Quat(_mm_div_ps(m, _mm_set1_ps(f)));}
|
|
|
|
inline float operator|(const Quat &v) const
|
|
{
|
|
__m128 mulVal = _mm_mul_ps(m, v.m); //mul = xyzw*v.xyzw
|
|
__m128 addVal = _mm_add_ps(_mm_movehl_ps(mulVal, mulVal), mulVal); //add = mul.yzyz+mul.xyzw
|
|
addVal = _mm_add_ps(_mm_shuffle_ps(addVal, addVal, 0x55), addVal); //add = add.yyyy+add.xyxw
|
|
return addVal.m128_f32[0]; //return add.x
|
|
}
|
|
|
|
inline Quat operator^(const Quat &q) const
|
|
{
|
|
return Quat(
|
|
(y*q.z)-(z*q.y)+(w*q.x)+(x*q.w),
|
|
(z*q.x)-(x*q.z)+(w*q.y)+(y*q.w),
|
|
(x*q.y)-(y*q.x)+(w*q.z)+(z*q.w),
|
|
(w*q.w)-(x*q.x)-(y*q.y)-(z*q.z));
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
//Transform operators
|
|
Quat operator*(const Quat &q) const;
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Quat& operator+=(const Quat &v) {m = _mm_add_ps(m, v.m); return *this;}
|
|
inline Quat& operator-=(const Quat &v) {m = _mm_sub_ps(m, v.m); return *this;}
|
|
Quat& operator*=(const Quat &q);
|
|
inline Quat& operator*=(const Euler &e);
|
|
|
|
inline Quat& operator+=(float f) {m = _mm_add_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Quat& operator-=(float f) {m = _mm_sub_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Quat& operator*=(float f) {m = _mm_mul_ps(m, _mm_set1_ps(f)); return *this;}
|
|
inline Quat& operator/=(float f) {m = _mm_div_ps(m, _mm_set1_ps(f)); return *this;}
|
|
|
|
inline Quat& operator^=(const Quat &q) {return (*this)=(*this)^q;}
|
|
|
|
inline Quat& operator=(const Quat &q) {m = q.m; return *this;}
|
|
inline Quat& operator=(const Vect &v) {m = v.m; w=1.0f; return *this;}
|
|
inline Quat& operator=(const AxisAngle &aa) {return MakeFromAxisAngle(aa);}
|
|
Quat& operator=(const Euler &e);
|
|
|
|
|
|
/////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Quat &q) const {return (q.x==x)&&(q.y==y)&&(q.z==z)&&(q.w==w);}
|
|
inline BOOL operator!=(const Quat &q) const {return (q.x!=x)||(q.y!=y)||(q.z!=z)||(q.w!=w);}
|
|
|
|
/////////////////////////
|
|
//Other
|
|
inline Quat& Set(float a, float b, float c, float d) {m = _mm_setr_ps(a, b, c, d); return *this;}
|
|
|
|
inline Quat& SetIdentity() {m = _mm_setr_ps(0.0f, 0.0f, 0.0f, 1.0f); return *this;}
|
|
|
|
inline float Len() const
|
|
{
|
|
return sqrtf(*this | *this);
|
|
}
|
|
|
|
inline float Dist(const Quat &v) const
|
|
{
|
|
Quat subVal = *this - v;
|
|
return sqrtf(subVal | subVal);
|
|
}
|
|
|
|
inline Quat& Norm()
|
|
{
|
|
m = _mm_mul_ps(m, _mm_set1_ps(1.0f/sqrtf(*this | *this)));
|
|
return *this;
|
|
}
|
|
|
|
inline BOOL CloseTo(const Quat &v, float epsilon=EPSILON) const
|
|
{
|
|
Quat subVal = (*this - v);
|
|
return (fabs(subVal.x) < epsilon) &&
|
|
(fabs(subVal.y) < epsilon) &&
|
|
(fabs(subVal.z) < epsilon) &&
|
|
(fabs(subVal.w) < epsilon);
|
|
}
|
|
#else
|
|
inline Quat(float a, float b, float c, float d) : x(a), y(b), z(c), w(d) {}
|
|
inline Quat(const Vect &v, float d) : x(v.x), y(v.y), z(v.z), w(d) {}
|
|
explicit inline Quat(const Vect &v) : x(v.x), y(v.y), z(v.z), w(1.0f) {}
|
|
|
|
|
|
/////////////////////////
|
|
//Arithmetic operators
|
|
inline Quat operator+(const Quat &q) const {return Quat(x+q.x, y+q.y, z+q.z, w+q.w);}
|
|
inline Quat operator-(const Quat &q) const {return Quat(x-q.x, y-q.y, z-q.z, w-q.w);}
|
|
|
|
inline Quat operator+(float f) const {return Quat( x+f, y+f, z+f, w+f);}
|
|
inline Quat operator-(float f) const {return Quat( x-f, y-f, z-f, w-f);}
|
|
inline Quat operator*(float f) const {return Quat( x*f, y*f, z*f, w*f);}
|
|
inline Quat operator/(float f) const
|
|
{
|
|
f = 1 / f;
|
|
return Quat(x*f, y*f, z*f, w*f);
|
|
}
|
|
|
|
inline float operator| (const Quat &q) const {return (x*q.x)+(y*q.y)+(z*q.z)+(w*q.w);}
|
|
inline Quat operator^(const Quat &q) const
|
|
{
|
|
return Quat(
|
|
(y*q.z)-(z*q.y)+(w*q.x)+(x*q.w),
|
|
(z*q.x)-(x*q.z)+(w*q.y)+(y*q.w),
|
|
(x*q.y)-(y*q.x)+(w*q.z)+(z*q.w),
|
|
(w*q.w)-(x*q.x)-(y*q.y)-(z*q.z));
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
//Transform operators
|
|
Quat operator*(const Quat &q) const;
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Quat& operator+=(const Quat &q) {return (*this)=(*this)+q;}
|
|
inline Quat& operator-=(const Quat &q) {return (*this)=(*this)-q;}
|
|
Quat& Quat::operator*=(const Quat &q);
|
|
inline Quat& operator*=(const Euler &e);
|
|
|
|
|
|
inline Quat& operator+=(float f) {return (*this)=(*this)+f;}
|
|
inline Quat& operator-=(float f) {return (*this)=(*this)-f;}
|
|
inline Quat& operator*=(float f) {return (*this)=(*this)*f;}
|
|
inline Quat& operator/=(float f) {return (*this)=(*this)/f;}
|
|
|
|
inline Quat& operator^=(const Quat &q) {return (*this)=(*this)^q;}
|
|
|
|
inline Quat& operator=(const Quat &q) {x=q.x; y=q.y; z=q.z; w=q.w; return *this;}
|
|
inline Quat& operator=(const Vect &v) {x=v.x; y=v.y; z=v.z; w=1.0f; return *this;}
|
|
inline Quat& operator=(const AxisAngle &aa) {return MakeFromAxisAngle(aa);}
|
|
Quat& operator=(const Euler &e);
|
|
|
|
|
|
/////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Quat &q) const {return (q.x==x)&&(q.y==y)&&(q.z==z)&&(q.w==w);}
|
|
inline BOOL operator!=(const Quat &q) const {return (q.x!=x)||(q.y!=y)||(q.z!=z)||(q.w!=w);}
|
|
|
|
/////////////////////////
|
|
//Other
|
|
inline Quat& Set(float a, float b, float c, float d) {x=a; y=b; z=c; w=d; return *this;}
|
|
|
|
inline Quat& SetIdentity() {x=0.0f; y=0.0f; z=0.0f; w=1.0f; return *this;}
|
|
|
|
inline float Len() const {return (float)sqrt((double)(x*x)+(y*y)+(z*z)+(w*w));}
|
|
|
|
inline float Dist(const Quat &q) const
|
|
{
|
|
//only do this stuff once
|
|
float a=(x-q.x),b=(y-q.y),c=(z-q.z),d=(w-q.w);
|
|
return (float)sqrt((double)(a*a)+(b*b)+(c*c)+(d*d));
|
|
}
|
|
|
|
inline Quat& Norm()
|
|
{
|
|
float len=Len();
|
|
|
|
if(len != 0)
|
|
{
|
|
len = 1 / len;
|
|
|
|
x *= len; y *= len; z *= len; w *= len;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline BOOL CloseTo(const Quat &v, float epsilon=EPSILON) const
|
|
{
|
|
return CloseFloat(x, v.x, epsilon) && CloseFloat(y, v.y, epsilon) && CloseFloat(z, v.z, epsilon) && CloseFloat(w, v.w, epsilon);
|
|
}
|
|
#endif
|
|
|
|
inline Quat operator-() const {return GetInv();}
|
|
|
|
inline Quat& Inv() {w=-w;return *this;}//{x=-x;y=-y;z=-z;return *this;}
|
|
inline Quat GetInv() const {return Quat(*this).Inv();}
|
|
|
|
inline Quat& Reverse() {x=-x;y=-y;z=-z;w=-w;return *this;}
|
|
inline Quat GetReverse() const {return Quat(*this).Reverse();}
|
|
|
|
inline Quat GetNorm() const {return Quat(*this).Norm();}
|
|
|
|
Quat& MakeFromAxisAngle(const AxisAngle &aa);
|
|
AxisAngle GetAxisAngle() const;
|
|
|
|
Quat& CreateFromMatrix(const Matrix &m);
|
|
|
|
inline Quat& operator*=(const AxisAngle &aa);
|
|
inline Quat operator*(const AxisAngle &aa)const;
|
|
|
|
inline operator float*() {return ptr;}
|
|
|
|
|
|
Vect GetDirectionVector() const;
|
|
|
|
Quat& MakeFromDirection(const Vect &dir);
|
|
Quat& SetLookDirection(const Vect &dir);
|
|
|
|
static inline Quat GetLookDirection(const Vect &dir) {return Quat().SetLookDirection(dir);}
|
|
|
|
Quat& Log();
|
|
Quat& Exp();
|
|
|
|
inline Quat GetLog() const {return Quat(*this).Log();}
|
|
inline Quat GetExp() const {return Quat(*this).Exp();}
|
|
|
|
Quat GetInterpolationTangent(const Quat &prev, const Quat &next) const;
|
|
|
|
static inline Quat Identity() {return Quat().SetIdentity();}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Quat &q)
|
|
{
|
|
s.Serialize(q.ptr, sizeof(float)*4);
|
|
return s;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Axis Angle
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT AxisAngle
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
};
|
|
/*struct
|
|
{
|
|
Vect axis;
|
|
float angle;
|
|
};*/
|
|
float ptr[4];
|
|
};
|
|
|
|
inline AxisAngle() {}
|
|
|
|
inline AxisAngle(float a, float b, float c, float d) : x(a), y(b), z(c), w(d) {}
|
|
inline AxisAngle(const Vect &v, float d) : x(v.x), y(v.y), z(v.z), w(d) {}
|
|
explicit inline AxisAngle(const Vect &v) : x(v.x), y(v.y), z(v.z), w(1.0f) {}
|
|
explicit inline AxisAngle(const Quat &q) {MakeFromQuat(q);}
|
|
|
|
|
|
/////////////////////////
|
|
//Conversion functions
|
|
AxisAngle& MakeFromQuat(const Quat &q);
|
|
Quat GetQuat() const {Quat newQuat(*this); return newQuat;}
|
|
|
|
inline AxisAngle& operator=(const Vect &v) {x = v.x; y = v.y; z = v.z; return *this;}
|
|
inline AxisAngle& operator=(const Quat &aa) {return MakeFromQuat(aa);}
|
|
|
|
|
|
/////////////////////////
|
|
//Other
|
|
inline AxisAngle& Set(float a, float b, float c, float d) {x=a; y=b; z=c; w=d; return *this;}
|
|
|
|
inline AxisAngle& Clear() {zero(this, sizeof(AxisAngle)); return *this;}
|
|
|
|
inline BOOL CloseTo(const AxisAngle &v, float epsilon=EPSILON) const
|
|
{
|
|
return CloseFloat(x, v.x, epsilon) && CloseFloat(y, v.y, epsilon) && CloseFloat(z, v.z, epsilon) && CloseFloat(w, v.w, epsilon);
|
|
}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, AxisAngle &aa)
|
|
{
|
|
return s << aa.x << aa.y << aa.z << aa.w;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Euler Rotation
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Euler
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float pitch;
|
|
float yaw;
|
|
float roll;
|
|
};
|
|
struct
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
};
|
|
float ptr[3];
|
|
};
|
|
|
|
|
|
inline Euler() {}
|
|
inline Euler(float a, float b, float c) : x(a), y(b), z(c) {}
|
|
|
|
|
|
////////////////////////
|
|
//Arithmetic operators
|
|
inline Euler operator+(const Euler &v) const {return Euler(x+v.x, y+v.y, z+v.z);}
|
|
inline Euler operator-(const Euler &v) const {return Euler(x-v.x, y-v.y, z-v.z);}
|
|
inline Euler operator*(const Euler &v) const {return Euler(x*v.x, y*v.y, z*v.z);}
|
|
inline Euler operator/(const Euler &v) const {return Euler(x/v.x, y/v.y, z/v.z);}
|
|
|
|
inline Euler operator+(float f) const {return Euler( x+f, y+f, z+f);}
|
|
inline Euler operator-(float f) const {return Euler( x-f, y-f, z-f);}
|
|
inline Euler operator*(float f) const {return Euler( x*f, y*f, z*f);}
|
|
inline Euler operator/(float f) const
|
|
{
|
|
f = 1 / f;
|
|
return Euler(x*f, y*f, z*f);
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Euler& operator+=(const Euler &v) {return (*this)=(*this)+v;}
|
|
inline Euler& operator-=(const Euler &v) {return (*this)=(*this)-v;}
|
|
inline Euler& operator*=(const Euler &v) {return (*this)=(*this)*v;}
|
|
inline Euler& operator/=(const Euler &v) {return (*this)=(*this)/v;}
|
|
|
|
inline Euler& operator+=(float f) {return (*this)=(*this)+f;}
|
|
inline Euler& operator-=(float f) {return (*this)=(*this)-f;}
|
|
inline Euler& operator*=(float f) {return (*this)=(*this)*f;}
|
|
inline Euler& operator/=(float f) {return (*this)=(*this)/f;}
|
|
|
|
inline Euler& operator=(const Euler &v) {x=v.x; y=v.y; z=v.z; return *this;}
|
|
inline Euler& operator=(float f) {x=f; y=f; z=f; return *this;}
|
|
|
|
////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Euler &v) const {return (v.x==x)&&(v.y==y)&&(v.z==z);}
|
|
inline BOOL operator!=(const Euler &v) const {return (v.x!=x)||(v.y!=y)||(v.z!=z);}
|
|
|
|
inline Euler operator-() const {return Euler(-x, -y, -z);}
|
|
|
|
|
|
////////////////////////
|
|
//Type casting
|
|
inline operator float*() {return ptr;}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Euler &e)
|
|
{
|
|
return s << e.pitch << e.yaw << e.roll;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Bounds
|
|
==========================================================*/
|
|
|
|
enum {BOUNDS_OUTSIDE=1, BOUNDS_INSIDE=2, BOUNDS_PARTIAL=4};
|
|
|
|
//for use with getpoint, as flags
|
|
enum {MAX_Z=1, MAX_Y=2, MAX_X=4};
|
|
|
|
struct BASE_EXPORT Bounds
|
|
{
|
|
Vect Min;
|
|
Vect Max;
|
|
|
|
|
|
inline Bounds() {}
|
|
inline Bounds(const Vect &a, const Vect &b) : Min(a), Max(b) {}
|
|
|
|
inline Bounds operator+(const Vect &pos) const
|
|
{
|
|
Bounds movedBounds = *this;
|
|
movedBounds.Min += pos;
|
|
movedBounds.Max += pos;
|
|
return movedBounds;
|
|
}
|
|
|
|
inline Bounds& operator+=(const Vect &pos)
|
|
{
|
|
Min += pos;
|
|
Max += pos;
|
|
return *this;
|
|
}
|
|
|
|
inline Bounds& operator=(const Bounds &box)
|
|
{
|
|
Min = box.Min;
|
|
Max = box.Max;
|
|
return *this;
|
|
}
|
|
|
|
inline Bounds GetScaled(const Vect &scale) const
|
|
{
|
|
return Bounds(*this).Scale(scale);
|
|
}
|
|
|
|
inline Bounds& Scale(const Vect &scale)
|
|
{
|
|
Min *= scale;
|
|
Max *= scale;
|
|
return *this;
|
|
}
|
|
|
|
inline Bounds GetMerged(const Bounds &bounds) const
|
|
{
|
|
return Bounds(*this).Merge(bounds);
|
|
}
|
|
|
|
inline Bounds& Merge(const Bounds &bounds)
|
|
{
|
|
Min.ClampMax(bounds.Min);
|
|
Max.ClampMin(bounds.Max);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Bounds& MergePoint(const Vect &point)
|
|
{
|
|
Min.ClampMax(point);
|
|
Max.ClampMin(point);
|
|
return *this;
|
|
}
|
|
|
|
Vect GetPoint(unsigned int i) const;
|
|
|
|
Bounds GetTransformedBounds(const Matrix &m) const;
|
|
Bounds& Transform(const Matrix &m);
|
|
|
|
Bounds& TransformNoRot(const Matrix &m);
|
|
|
|
inline Vect GetCenter() const
|
|
{
|
|
return (((Max-Min)*0.5f)+Min);
|
|
}
|
|
|
|
inline BOOL BoundsInside(const Bounds &test) const
|
|
{
|
|
return (test.Min.x >= Min.x) && (test.Min.y >= Min.y) && (test.Min.z >= Min.z) &&
|
|
(test.Max.x <= Max.x) && (test.Max.y <= Max.y) && (test.Max.z <= Max.z);
|
|
|
|
}
|
|
|
|
inline BOOL Intersects(const Bounds &test, float epsilon=EPSILON) const
|
|
{
|
|
/*int i;
|
|
|
|
for(i=0;i<3;i++)
|
|
{
|
|
if(((Min.ptr[i]-test.Max.ptr[i]) > epsilon) || ((test.Min.ptr[i]-Max.ptr[i]) > epsilon))
|
|
//if((Min.ptr[i] > test.Max.ptr[i]) || (test.Min.ptr[i] > Max.ptr[i]))
|
|
return 0;
|
|
}*/
|
|
|
|
if( ((Min.x - test.Max.x) > epsilon) || ((test.Min.x - Max.x) > epsilon) ||
|
|
((Min.y - test.Max.y) > epsilon) || ((test.Min.y - Max.y) > epsilon) ||
|
|
((Min.z - test.Max.z) > epsilon) || ((test.Min.z - Max.z) > epsilon) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL IntersectsOBB(const Bounds &test, const Matrix &transform) const;
|
|
|
|
inline BOOL SphereIntersects(const Vect ¢er, float radius) const
|
|
{
|
|
int i;
|
|
float s, d = 0;
|
|
|
|
for(i=0;i<3;i++)
|
|
{
|
|
if(center.ptr[i] < Min.ptr[i])
|
|
{
|
|
s = center.ptr[i] - Min.ptr[i];
|
|
d += s*s;
|
|
}
|
|
else if(center.ptr[i] > Max.ptr[i])
|
|
{
|
|
s = center.ptr[i] - Max.ptr[i];
|
|
d += s*s;
|
|
}
|
|
}
|
|
return (d <= (radius*radius));
|
|
}
|
|
|
|
BOOL CylinderIntersects(const Vect ¢er, float radius, float height) const;
|
|
|
|
inline float VectorOffsetLength(const Vect &v) const
|
|
{
|
|
return (Max-Min).Abs().Dot(v.GetAbs());
|
|
}
|
|
|
|
float MinDistFrom(const Plane &p) const;
|
|
|
|
inline float MaxDistFrom(const Plane &p) const
|
|
{
|
|
float bestDist = 1.0f;
|
|
|
|
for(int i=0; i<8; i++)
|
|
{
|
|
float dist = GetPoint(i).DistFromPlane(p);
|
|
if(dist > bestDist)
|
|
bestDist = dist;
|
|
}
|
|
|
|
return bestDist;
|
|
}
|
|
|
|
/*inline void Transform(const Matrix &m)
|
|
{
|
|
Min.TransformPoint(m);
|
|
Max.TransformPoint(m);
|
|
}*/
|
|
|
|
inline BOOL PointInside(const Vect &point) const
|
|
{
|
|
return ((point.x >= (Min.x-EPSILON)) &&
|
|
(point.x <= (Max.x+EPSILON)) &&
|
|
(point.y >= (Min.y-EPSILON)) &&
|
|
(point.y <= (Max.y+EPSILON)) &&
|
|
(point.z >= (Min.z-EPSILON)) &&
|
|
(point.z <= (Max.z+EPSILON)));
|
|
|
|
}
|
|
|
|
inline BOOL PointInsideTopDown(const Vect &point) const
|
|
{
|
|
return ((point.x >= (Min.x-EPSILON)) &&
|
|
(point.x <= (Max.x+EPSILON)) &&
|
|
(point.z >= (Min.z-EPSILON)) &&
|
|
(point.z <= (Max.z+EPSILON)));
|
|
|
|
}
|
|
|
|
inline float GetDiamater()
|
|
{
|
|
return Max.Dist(Min);
|
|
}
|
|
|
|
BOOL RayIntersection(const Vect &rayOrig, const Vect &rayDir, float &fT) const;
|
|
BOOL RayIntersectionTopDown(const Vect &rayOrig, const Vect &rayDir, float &fT) const;
|
|
BOOL LineIntersection(const Vect &v1, const Vect &v2, float &fT) const;
|
|
BOOL LineIntersectionTopDown(const Vect &v1, const Vect &v2, float &fT) const;
|
|
|
|
inline BOOL RayIntersects(const Vect &rayOrig, const Vect &rayDir) const
|
|
{
|
|
float fT;
|
|
return RayIntersection(rayOrig, rayDir, fT);
|
|
}
|
|
|
|
inline BOOL RayIntersectsTopDown(const Vect &rayOrig, const Vect &rayDir) const
|
|
{
|
|
float fT;
|
|
return RayIntersectionTopDown(rayOrig, rayDir, fT);
|
|
}
|
|
|
|
inline BOOL LineIntersects(const Vect &v1, const Vect &v2) const
|
|
{
|
|
float fT;
|
|
return LineIntersection(v1, v2, fT);
|
|
}
|
|
|
|
inline BOOL LineIntersectsTopDown(const Vect &v1, const Vect &v2) const
|
|
{
|
|
float fT;
|
|
return LineIntersectionTopDown(v1, v2, fT);
|
|
}
|
|
|
|
int PlaneTest(const Plane &p) const;
|
|
BOOL OutsidePlane(const Plane &p) const;
|
|
|
|
inline Bounds ModifiedPos(const Vect &pos) const
|
|
{
|
|
Bounds modBounds = *this;
|
|
modBounds.Min += pos;
|
|
modBounds.Max += pos;
|
|
return modBounds;
|
|
}
|
|
|
|
inline Vect GetSize() const
|
|
{
|
|
return Max-Min;
|
|
}
|
|
|
|
Bounds& MakeFromPoints(const List<Vect> &pointList);
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Bounds &b)
|
|
{
|
|
return s << b.Min << b.Max;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Plane
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Plane
|
|
{
|
|
Vect Dir;
|
|
float Dist;
|
|
|
|
inline Plane() {}
|
|
inline Plane(float a, float b, float c, float d) : Dir(a, b, c), Dist(d) {}
|
|
inline Plane(const Vect &a, float b) : Dir(a), Dist(b) {}
|
|
inline Plane(const Vect &a, const Vect &b, const Vect &c) {CreateFromTri(a, b, c);}
|
|
|
|
|
|
/////////////////////////
|
|
//Arithmetic operators
|
|
inline float operator|(const Vect& p) const {return (p|Dir)-Dist;}
|
|
inline Plane operator-() const {return Plane(-Dir, -Dist);}
|
|
|
|
|
|
/////////////////////////
|
|
//Boolean operators
|
|
inline BOOL operator==(const Plane& p) const {return CloseTo(p, EPSILON);}
|
|
inline BOOL operator!=(const Plane& p) const {return !CloseTo(p, EPSILON);}
|
|
|
|
|
|
/////////////////////////
|
|
//Assignment operators
|
|
inline Plane& operator=(const Plane& p) {Dir = p.Dir; Dist = p.Dist; return *this;}
|
|
|
|
|
|
/////////////////////////
|
|
//Matrix Transformation
|
|
Plane& Transform(const Matrix &m);
|
|
Plane GetTransform(const Matrix &m) const
|
|
{
|
|
return Plane(*this).Transform(m);
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
//Other
|
|
void CreateFromTri(const Vect &a, const Vect &b, const Vect &c);
|
|
|
|
Plane& Set(float a, float b, float c, float d)
|
|
{
|
|
Dir.x = a; Dir.y = b; Dir.z = c; Dist = d;
|
|
return *this;
|
|
}
|
|
|
|
BOOL GetRayIntersection(const Vect &rayOrigin, const Vect &rayDir, float &fT) const;
|
|
BOOL GetIntersection(const Vect &p1, const Vect &p2, float &fT) const;
|
|
|
|
BOOL GetDoublePlaneIntersection(const Plane &p2, Vect &intOrigin, Vect &intDir) const;
|
|
BOOL GetTriplePlaneIntersection(const Plane &p2, const Plane &p3, Vect &intersection) const;
|
|
|
|
|
|
inline int TriInside(const Vect &p1, const Vect &p2, const Vect &p3, float precision=LARGE_EPSILON) const
|
|
{
|
|
//bit 1: part or all of the triangle is behind the plane
|
|
//bit 2: part or all of the triangle is in front of the plane
|
|
int sides=0;
|
|
float d1 = p1.DistFromPlane(*this);
|
|
float d2 = p2.DistFromPlane(*this);
|
|
float d3 = p3.DistFromPlane(*this);
|
|
|
|
if(d1 >= precision)
|
|
sides |= 2;
|
|
else if(d1 <= -precision)
|
|
sides |= 1;
|
|
|
|
if(d2 >= precision)
|
|
sides |= 2;
|
|
else if(d2 <= -precision)
|
|
sides |= 1;
|
|
|
|
if(d3 >= precision)
|
|
sides |= 2;
|
|
else if(d3 <= -precision)
|
|
sides |= 1;
|
|
|
|
return sides;
|
|
}
|
|
|
|
inline int LineInside(const Vect &p1, const Vect &p2, float precision=EPSILON) const
|
|
{
|
|
int sides=0;
|
|
float d1 = p1.DistFromPlane(*this);
|
|
float d2 = p2.DistFromPlane(*this);
|
|
|
|
if(d1 >= precision)
|
|
sides |= 2;
|
|
else if(d1 <= -precision)
|
|
sides |= 1;
|
|
|
|
if(d2 >= precision)
|
|
sides |= 2;
|
|
else if(d2 <= -precision)
|
|
sides |= 1;
|
|
|
|
return sides;
|
|
}
|
|
|
|
BOOL CloseTo(const Plane &plane, float precision=LARGE_EPSILON) const
|
|
{
|
|
return Dir.CloseTo(plane.Dir, precision) && CloseFloat(Dist, plane.Dist, precision);
|
|
}
|
|
|
|
BOOL Coplanar(const Plane &plane, float precision=EPSILON) const
|
|
{
|
|
float fCosAngle = Dir.Dot(plane.Dir);
|
|
|
|
if(CloseFloat(fCosAngle, 1.0f, precision))
|
|
return CloseFloat(plane.Dist, Dist, precision);
|
|
else if(CloseFloat(fCosAngle, -1.0f, precision))
|
|
return CloseFloat(plane.Dist, -Dist, precision);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Plane &p)
|
|
{
|
|
return s << p.Dir << p.Dist;
|
|
}
|
|
|
|
static inline Serializer& SerializeList(Serializer &s, List<Plane> &list)
|
|
{
|
|
UINT num;
|
|
if(s.IsLoading())
|
|
{
|
|
s << num;
|
|
list.SetSize(num);
|
|
}
|
|
else
|
|
{
|
|
num = list.Num();
|
|
s << num;
|
|
}
|
|
|
|
for(unsigned int i=0; i<num; i++)
|
|
s << list[i];
|
|
|
|
return s;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*=========================================================
|
|
Matrix (3x4)
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Matrix
|
|
{
|
|
/*union
|
|
{
|
|
struct
|
|
{ */
|
|
Vect X; //X axis
|
|
Vect Y; //Y axis
|
|
Vect Z; //Z axis
|
|
Vect T; //location (origin)
|
|
/*};
|
|
float ptr[12];
|
|
float ptr3x4[3][4];
|
|
}; */
|
|
|
|
inline Matrix() {}
|
|
inline Matrix(const Quat &q) {CreateFromQuat(q); T = 0;}
|
|
inline Matrix(const AxisAngle &aa) {CreateFromQuat(aa.GetQuat()); T = 0;}
|
|
inline Matrix(const Euler &e) {SetIdentity() *= e;}
|
|
|
|
inline Matrix(const Vect &a, const Vect &b, const Vect &c, const Vect &o)
|
|
: X(a), Y(b), Z(c), T(o) {}
|
|
|
|
|
|
/////////////////////////
|
|
//Arithmetic operators
|
|
inline Matrix& operator*=(const Matrix &m)
|
|
{
|
|
X.TransformVector(m);
|
|
Y.TransformVector(m);
|
|
Z.TransformVector(m);
|
|
T.TransformPoint(m);
|
|
return *this;
|
|
}
|
|
|
|
inline Matrix operator*(const Matrix &m) const
|
|
{
|
|
return Matrix(*this) *= m;
|
|
}
|
|
|
|
inline Matrix& Multiply(const Matrix &m)
|
|
{
|
|
return (*this *= m);
|
|
}
|
|
|
|
inline Matrix GetMultiply(const Matrix &m) const
|
|
{
|
|
return (Matrix(*this) *= m);
|
|
}
|
|
|
|
|
|
inline Matrix& operator*=(const Vect &v)
|
|
{
|
|
/*Vect Temp(v);
|
|
Temp.TransformVector(*this);
|
|
T += Temp;*/
|
|
|
|
T -= v;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Matrix operator*(const Vect &v) const
|
|
{
|
|
return Matrix(*this) *= v;
|
|
}
|
|
|
|
inline Matrix& Translate(const Vect &v)
|
|
{
|
|
return (*this *= v);
|
|
}
|
|
|
|
|
|
inline Matrix& operator*=(const Quat &q)
|
|
{
|
|
return *this *= Matrix(q);
|
|
}
|
|
|
|
inline Matrix operator*(const Quat &q) const
|
|
{
|
|
return Matrix(*this) *= q;
|
|
}
|
|
|
|
inline Matrix& operator*=(const Euler &e)
|
|
{
|
|
Matrix Temp;
|
|
|
|
Temp.T = 0.0;
|
|
|
|
if(e.x)
|
|
{
|
|
Temp.X.x = 1.0; Temp.X.y = 0.0; Temp.X.z = 0.0;
|
|
Temp.Y.x = 0.0; Temp.Y.y = cos(e.x); Temp.Y.z = -sin(e.x);
|
|
Temp.Z.x = 0.0; Temp.Z.y = sin(e.x); Temp.Z.z = cos(e.x);
|
|
|
|
*this *= Temp;
|
|
|
|
}
|
|
if(e.y)
|
|
{
|
|
Temp.X.x = cos(e.y); Temp.X.y = 0.0; Temp.X.z = sin(e.y);
|
|
Temp.Y.x = 0.0; Temp.Y.y = 1.0; Temp.Y.z = 0.0;
|
|
Temp.Z.x = -sin(e.y); Temp.Z.y = 0.0; Temp.Z.z = cos(e.y);
|
|
|
|
*this *= Temp;
|
|
}
|
|
if(e.z)
|
|
{
|
|
Temp.X.x = cos(e.z); Temp.X.y = -sin(e.z); Temp.X.z = 0.0;
|
|
Temp.Y.x = sin(e.z); Temp.Y.y = cos(e.z); Temp.Y.z = 0.0;
|
|
Temp.Z.x = 0.0; Temp.Z.y = 0.0; Temp.Z.z = 1.0;
|
|
|
|
*this *= Temp;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Matrix operator*(const Euler &e) const
|
|
{
|
|
return Matrix(*this) *= e;
|
|
}
|
|
|
|
inline Matrix& Rotate(const Quat &q)
|
|
{
|
|
return (*this *= q);
|
|
}
|
|
|
|
inline Matrix& Rotate(const AxisAngle &aa)
|
|
{
|
|
return (*this *= Quat(aa));
|
|
}
|
|
|
|
inline Matrix& Rotate(const Euler &e)
|
|
{
|
|
return (*this *= e);
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
//Matrix functions
|
|
inline Matrix& SetIdentity()
|
|
{
|
|
zero(this, sizeof(Matrix));
|
|
X.x = Y.y = Z.z = 1.0;
|
|
return *this;
|
|
}
|
|
|
|
static inline Matrix Identity()
|
|
{
|
|
Matrix Temp;
|
|
Temp.SetIdentity();
|
|
return Temp;
|
|
}
|
|
|
|
#ifdef USE_SSE
|
|
//transposing an affine matrix is the same as an inverse
|
|
inline Matrix GetTranspose() const
|
|
{
|
|
return Matrix(*this).Transpose();
|
|
}
|
|
|
|
//tmp1 = x.x, x.y, y.x, y.y
|
|
//tmp2 = x.z, x.w, y.z, y.w
|
|
//tmp1 = shuffle X, Y, 0 1 0 1 = movelh
|
|
//tmp2 = shuffle X, Y, 2 3 2 3 = movehl
|
|
//X = shuffle tmp1, Z, 0 2 0 3
|
|
//Y = shuffle tmp1, Z, 1 3 1 3
|
|
//Z = shuffle tmp2, Z, 0 2 2 3
|
|
inline Matrix& Transpose()
|
|
{
|
|
T.TransformVector(*this); T = -T;
|
|
|
|
__m128 tmp1 = _mm_movelh_ps(X.m, Y.m);
|
|
__m128 tmp2 = _mm_movehl_ps(Y.m, X.m);
|
|
X.m = _mm_shuffle_ps(tmp1, Z.m, _MM_SHUFFLE(3, 0, 2, 0));
|
|
Y.m = _mm_shuffle_ps(tmp1, Z.m, _MM_SHUFFLE(3, 1, 3, 1));
|
|
Z.m = _mm_shuffle_ps(tmp2, Z.m, _MM_SHUFFLE(3, 2, 2, 0));
|
|
|
|
return *this;
|
|
}
|
|
#else
|
|
//transposing an affine matrix is the same as an inverse
|
|
inline Matrix GetTranspose() const
|
|
{
|
|
return Matrix(Vect(X.x, Y.x, Z.x), Vect(X.y, Y.y, Z.y), Vect(X.z, Y.z, Z.z), -T.GetTransformedVector(*this));
|
|
}
|
|
|
|
inline Matrix& Transpose()
|
|
{
|
|
return (*this = GetTranspose());
|
|
}
|
|
#endif
|
|
|
|
inline Matrix& Scale(float scaleX, float scaleY, float scaleZ)
|
|
{
|
|
/*X.x *= scaleX;
|
|
X.y *= scaleY;
|
|
X.z *= scaleZ;
|
|
|
|
Y.x *= scaleX;
|
|
Y.y *= scaleY;
|
|
Y.z *= scaleZ;
|
|
|
|
Z.x *= scaleX;
|
|
Z.y *= scaleY;
|
|
Z.z *= scaleZ;
|
|
|
|
T.x /= scaleX;
|
|
T.y /= scaleY;
|
|
T.z /= scaleZ;
|
|
return *this;*/
|
|
return Scale(Vect(scaleX, scaleY, scaleZ));
|
|
}
|
|
|
|
inline Matrix& Scale(const Vect &scale)
|
|
{
|
|
X *= scale;
|
|
Y *= scale;
|
|
Z *= scale;
|
|
T /= scale;
|
|
|
|
return *this;
|
|
//return Scale(scale.x, scale.y, scale.z);
|
|
}
|
|
|
|
inline Matrix GetScale(float scaleX, float scaleY, float scaleZ) const
|
|
{
|
|
return Matrix(*this).Scale(Vect(scaleX, scaleY, scaleZ));
|
|
}
|
|
|
|
inline Matrix GetScale(const Vect &scale) const
|
|
{
|
|
return Matrix(*this).Scale(scale);
|
|
}
|
|
|
|
Matrix GetInverse() const;
|
|
Matrix& Inverse();
|
|
|
|
inline Matrix& MirrorByVector(const Vect &v)
|
|
{
|
|
X.MirrorByVector(v);
|
|
Y.MirrorByVector(v);
|
|
Z.MirrorByVector(v);
|
|
T.MirrorByVector(v);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Matrix& MirrorByPlane(const Plane &p)
|
|
{
|
|
Vect dir = p.Dir;
|
|
X.MirrorByVector(dir);
|
|
Y.MirrorByVector(dir);
|
|
Z.MirrorByVector(dir);
|
|
T.MirrorByPlane(p);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Matrix GetMirrorByVector(const Vect &v) const
|
|
{
|
|
return Matrix(*this).MirrorByVector(v);
|
|
}
|
|
|
|
inline Matrix GetMirrorByPlane(const Plane &p) const
|
|
{
|
|
return Matrix(*this).MirrorByPlane(p);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////
|
|
//Other
|
|
/*inline float operator[](unsigned int index) const
|
|
{
|
|
assert(index < 12);
|
|
|
|
return ptr[index];
|
|
}*/
|
|
|
|
|
|
/////////////////////////
|
|
//Conversion functions
|
|
void CreateFromQuat(const Quat &q);
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Matrix &m)
|
|
{
|
|
return s << m.X << m.Y << m.Z << m.T;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Line2
|
|
==========================================================*/
|
|
|
|
struct BASE_EXPORT Line2
|
|
{
|
|
Vect2 A;
|
|
Vect2 B;
|
|
|
|
Line2() {}
|
|
Line2(const Vect2 &v1, const Vect2 &v2) : A(v1), B(v2) {}
|
|
|
|
BOOL LinesIntersect(const Line2 &collider) const;
|
|
|
|
inline Vect2& GetDirection() const
|
|
{
|
|
return (B-A).Norm();
|
|
}
|
|
|
|
////////////////////////
|
|
// Serialization
|
|
friend inline Serializer& operator<<(Serializer &s, Line2 &line2)
|
|
{
|
|
return s << line2.A << line2.B;
|
|
}
|
|
};
|
|
|
|
|
|
/*=========================================================
|
|
Other
|
|
==========================================================*/
|
|
|
|
BASE_EXPORT Quat InterpolateQuat(const Quat &from, const Quat &to, float t);
|
|
BASE_EXPORT Quat CubicInterpolateQuat(const Quat &prev, const Quat &from, const Quat &to, const Quat &after, float t);
|
|
|
|
BASE_EXPORT Vect GetHSpline(const Vect &v0, const Vect &v1, const Vect &m0, const Vect &m1, float fT);
|
|
|
|
BASE_EXPORT BOOL SphereRayCollision(const Vect &sphereCenter, float sphereRadius, const Vect &rayOrig, const Vect &rayDir, Vect *collision=NULL, Plane *collisionPlane=NULL);
|
|
BASE_EXPORT BOOL CylinderRayCollision(const Vect &cylCenter, float cylRadius, float cylHeight, const Vect &rayOrig, const Vect &rayDir, Vect *collision=NULL, Plane *collisionPlane=NULL);
|
|
|
|
BASE_EXPORT BOOL PointOnFiniteLine(const Vect &lineV1, const Vect &lineV2, const Vect &p);
|
|
|
|
BASE_EXPORT BOOL ClosestLinePoint(const Vect &ray1Origin, const Vect &ray1Dir, const Vect &ray2Origin, const Vect &ray2Dir, float &fT);
|
|
BASE_EXPORT BOOL ClosestLinePoints(const Vect &ray1Origin, const Vect &ray1Dir, const Vect &ray2Origin, const Vect &ray2Dir, float &fT1, float &fT2);
|
|
|
|
|
|
inline Vect2::Vect2(const Vect &v)
|
|
{
|
|
x = v.x;
|
|
y = v.y;
|
|
}
|
|
|
|
inline Vect2& Vect2::operator=(const Vect &v)
|
|
{
|
|
x=v.x;
|
|
y=v.y;
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline CompactVect::CompactVect(const Vect &v)
|
|
{
|
|
x = v.x; y = v.y; z = v.z;
|
|
}
|
|
|
|
inline CompactVect& CompactVect::operator=(const Vect &v)
|
|
{
|
|
x = v.x; y = v.y; z = v.z;
|
|
return *this;
|
|
}
|
|
|
|
|
|
#ifdef USE_SSE
|
|
inline Vect::Vect(const Vect4 &v) {m = v.m; w = 0.0f;}
|
|
#else
|
|
inline Vect::Vect(const Vect4 &v) : x(v.x), y(v.y), z(v.z), w(0.0f) {}
|
|
#endif
|
|
|
|
inline Vect& Vect::TransformPoint(const Matrix &m)
|
|
{
|
|
Vect Temp(*this-m.T);
|
|
x = Temp.Dot(m.X);
|
|
y = Temp.Dot(m.Y);
|
|
z = Temp.Dot(m.Z);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vect& Vect::TransformVector(const Matrix &m)
|
|
{
|
|
Vect Temp(*this);
|
|
x = Temp.Dot(m.X);
|
|
y = Temp.Dot(m.Y);
|
|
z = Temp.Dot(m.Z);
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline void Vect::MirrorByPlane(const Plane& p)
|
|
{
|
|
*this -= (p.Dir * (2.0f * DistFromPlane(p)));
|
|
}
|
|
|
|
inline void Vect::MirrorByVector(const Vect& v)
|
|
{
|
|
(*this) -= (v * (2.0f * Dot(v)));
|
|
}
|
|
|
|
inline Quat Quat::operator*(const Quat &q) const
|
|
{
|
|
return Quat(*this) *= q;
|
|
}
|
|
|
|
inline Quat& Quat::operator*=(const AxisAngle &aa) {return *this *= aa.GetQuat();}
|
|
inline Quat Quat::operator*(const AxisAngle &aa) const {return Quat(*this) *= aa.GetQuat();}
|
|
|
|
BASE_EXPORT Vect CartToPolar(const Vect &cart);
|
|
BASE_EXPORT Vect PolarToCart(const Vect &polar);
|
|
BASE_EXPORT Vect PolarToCart(float latitude, float longitude, float dist);
|
|
|
|
BASE_EXPORT Vect2 NormToPolar(const Vect &norm);
|
|
BASE_EXPORT void NormToPolar(const Vect &norm, float &latitude, float &longitude);
|
|
BASE_EXPORT Vect PolarToNorm(const Vect2 &polar);
|
|
|
|
BASE_EXPORT float GetPlaneCylinderOffset(const Vect &dir, float cylHalfHeight, float cylRadius);
|
|
BASE_EXPORT float GetPlaneCapsuleOffset(const Vect &dir, float capsuleHalfHeight, float capsuleRadius);
|
|
BASE_EXPORT float GetPlaneConeOffset(const Vect &dir, float coneHeight, float coneRadius);
|
|
|
|
BASE_EXPORT float RandomFloat(BOOL bPositiveOnly=FALSE);
|
|
BASE_EXPORT Vect RandomVect(BOOL bPositiveOnly=FALSE);
|
|
|
|
//calculates a torque between two values and makes the adjustment to val1
|
|
BASE_EXPORT void CalcTorque(float &val1, float val2, float torque, float minAdjust, float fT);
|
|
BASE_EXPORT void CalcTorque(Vect &val1, const Vect &val2, float torque, float minAdjust, float fT);
|
|
|
|
inline float GetPercentage(float startVal, float endVal, float middleVal)
|
|
{
|
|
return (middleVal-startVal)/(endVal-startVal);
|
|
}
|
|
|
|
inline float GetPercentageI(int startVal, int endVal, int middleVal)
|
|
{
|
|
return (float)(middleVal-startVal)/(float)(endVal-startVal);
|
|
}
|
|
|
|
inline float TriangleArea(const Vect &v0, const Vect &v1, const Vect &v2)
|
|
{
|
|
return fabsf(((v1-v0)^(v2-v0)).Len()*0.5f);
|
|
}
|
|
|
|
//simple version
|
|
inline BOOL PointInsideTri(const Vect2 &v1, const Vect2 &v2, const Vect2 &v3, const Vect2 &p)
|
|
{
|
|
Vect2 n1 = (v1-p).Norm();
|
|
Vect2 n2 = (v2-p).Norm();
|
|
Vect2 n3 = (v3-p).Norm();
|
|
|
|
float a1 = acos(n1.Dot(n2));
|
|
float a2 = acos(n2.Dot(n3));
|
|
float a3 = acos(n3.Dot(n1));
|
|
|
|
return CloseFloat((a1+a2+a3), M_PI*2.0f);
|
|
}
|
|
|
|
BASE_EXPORT void Matrix4x4Identity(float *destMatrix);
|
|
BASE_EXPORT void Matrix4x4Convert(float *destMat4x4, const Matrix &matSource);
|
|
BASE_EXPORT void Matrix4x4Convert(Matrix &destMat3x4, float *matSource);
|
|
BASE_EXPORT void Matrix4x4Multiply(float *destMatrix, float *M1, float *M2);
|
|
BASE_EXPORT void Matrix4x4TransformVect(Vect4 &out, float *M1, const Vect4 &vec);
|
|
BASE_EXPORT float Matrix3x3Determinant(float *M1);
|
|
BASE_EXPORT float Matrix4x4Determinant(float *M1);
|
|
BASE_EXPORT void Matrix4x4SubMatrix(float *destMatrix, float *M1, int i, int j);
|
|
BASE_EXPORT BOOL Matrix4x4Inverse(float *destMatrix, float *M1);
|
|
BASE_EXPORT void Matrix4x4Transpose(float *destMatrix, float *srcMatrix);
|
|
BASE_EXPORT void Matrix4x4Ortho(float *destMatrix, double left, double right, double bottom, double top, double near, double far);
|
|
BASE_EXPORT void Matrix4x4Frustum(float *destMatrix, double left, double right, double bottom, double top, double near, double far);
|
|
BASE_EXPORT void Matrix4x4Perspective(float *destMatrix, float angle, float aspect, float near, float far);
|