diff --git a/src/CELLMath.hpp b/src/CELLMath.hpp new file mode 100644 index 0000000..af7c7d7 --- /dev/null +++ b/src/CELLMath.hpp @@ -0,0 +1,5933 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace CELL +{ + + + #define PI 3.14159265358979323 + #define TWO_PI 6.28318530717958647 + #define HALF_PI 1.57079632679489661 + #define DEG2RAD(theta) (0.01745329251994329 * theta) + #define RAD2DEG 57.2957795130823208 + #define LOG2 0.69314718055994529 + #define WGS_84_RADIUS_EQUATOR 6378137.0 + #define WGS_84_RADIUS_POLAR 6356752.3142 + #define MIN(a,b) ((a) < (b) ? (a) : (b)) + #define MAX(a,b) ((a) > (b) ? (a) : (b)) + #ifndef FLT_MAX + #define FLT_MAX 3.402823466e+38F + #endif + + #ifndef FLT_MIN + #define FLT_MIN 1.175494351e-38F + #endif + + #define MAKE_INT(a, b) ((int)(((short)(((int)(a)) & 0xffff)) | ((int)((short)(((int)(b)) & 0xffff))) << 16)) + + typedef unsigned char byte; + typedef long long int64; + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; + + template inline T tmin(T a,T b) + { + return a < b ? a:b; + } + + template inline T tmax(T a,T b) + { + return a > b ? a:b; + } + + + union LargeInt + { + struct __LARGE_INT + { + unsigned int LowPart; + unsigned int HighPart; + }_largeInt; + int64 int64Data; + } ; + + + inline float unitRandom () + { + return float(rand()) / float( RAND_MAX ); + } + + //----------------------------------------------------------------------- + inline float rangeRandom (float fLow, float fHigh) + { + return (fHigh-fLow)*unitRandom() + fLow; + } + + /** + * 产生64位数字 + */ + inline int64 makeInt64(unsigned low,unsigned hi) + { + LargeInt intdata; + intdata._largeInt.HighPart = low; + intdata._largeInt.LowPart = hi; + return intdata.int64Data; + } + + + template + struct tvec2 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec2 type; + + value_type x; + value_type y; + + + value_type & operator[](size_type i) + { + assert(i < this->length()); + return (&x)[i]; + } + + value_type const & operator[]( size_type i ) const + { + assert(i < this->length()); + return (&x)[i]; + } + tvec2() : + x(value_type(0)), + y(value_type(0)) + {} + tvec2(tvec2 const & v) : + x(v.x), + y(v.y) + {} + tvec2(value_type const & s) : + x(s), + y(s) + {} + + tvec2(value_type const & s1, value_type const & s2) : + x(s1), + y(s2) + {} + + template + tvec2(U const & x) : + x(value_type(x)), + y(value_type(x)) + {} + + template + tvec2(U const & a, V b) : + x(value_type(a)), + y(value_type(b)) + {} + + + template + tvec2(tvec2 const & v) : + x(value_type(v.x)), + y(value_type(v.y)) + {} + + tvec2 & operator= (tvec2 const & v) + { + this->x = v.x; + this->y = v.y; + return *this; + } + + template + tvec2 & operator= (tvec2 const & v) + { + this->x = T(v.x); + this->y = T(v.y); + return *this; + } + + template + tvec2 & operator+=(U const & s) + { + this->x += T(s); + this->y += T(s); + return *this; + } + + template + tvec2 & operator+=(tvec2 const & v) + { + this->x += T(v.x); + this->y += T(v.y); + return *this; + } + + + template + tvec2 & operator-=(U const & s) + { + this->x -= T(s); + this->y -= T(s); + return *this; + } + + template + tvec2 & operator-=(tvec2 const & v) + { + this->x -= T(v.x); + this->y -= T(v.y); + return *this; + } + + template + tvec2 & operator*=(U s) + { + this->x *= T(s); + this->y *= T(s); + return *this; + } + + template + tvec2 & operator*=(tvec2 const & v) + { + this->x *= T(v.x); + this->y *= T(v.y); + return *this; + } + + template + tvec2 & operator/=(U s) + { + this->x /= T(s); + this->y /= T(s); + return *this; + } + + template + tvec2 & operator/=(tvec2 const & v) + { + this->x /= T(v.x); + this->y /= T(v.y); + return *this; + } + + tvec2 & operator++() + { + ++ this->x; + ++ this->y; + return *this; + } + tvec2 & operator--() + { + --this->x; + --this->y; + return *this; + } + void makeCeil( tvec2 cmp ) + { + if( cmp.x > x ) x = cmp.x; + if( cmp.y > y ) y = cmp.y; + } + void makeFloor( tvec2 cmp ) + { + if( cmp.x < x ) x = cmp.x; + if( cmp.y < y ) y = cmp.y; + } + }; + + template + tvec2 rotate(tvec2 const & v, T angle) + { + tvec2 res; + T const c(cos(DEG2RAD(angle))); + T const s(sin(DEG2RAD(angle))); + res.x = v.x * c - v.y * s; + res.y = v.x * s + v.y * c; + return res; + } + + template + bool operator==(tvec2 const & v1, tvec2 const & v2) + { + return (v1.x == v2.x) && (v1.y == v2.y); + } + + template + bool operator!=(tvec2 const & v1, tvec2 const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y); + } + + template + tvec2 operator+ (tvec2 const & v, T const & s) + { + return tvec2( + v.x + T(s), + v.y + T(s)); + } + + template + tvec2 operator+ (T const & s, tvec2 const & v) + { + return tvec2( + T(s) + v.x, + T(s) + v.y); + } + + template + tvec2 operator+ (tvec2 const & v1, tvec2 const & v2) + { + return tvec2( + v1.x + T(v2.x), + v1.y + T(v2.y)); + } + + template + tvec2 operator-(tvec2 const & v, T const & s) + { + return tvec2( + v.x - T(s), + v.y - T(s)); + } + + template + tvec2 operator- (T const & s, tvec2 const & v) + { + return tvec2( + T(s) - v.x, + T(s) - v.y); + } + + template + tvec2 operator- (tvec2 const & v1, tvec2 const & v2) + { + return tvec2( + v1.x - T(v2.x), + v1.y - T(v2.y)); + } + + template + tvec2 operator* (tvec2 const & v, T const & s) + { + return tvec2( + v.x * T(s), + v.y * T(s)); + } + + template + tvec2 operator* (T const & s, tvec2 const & v) + { + return tvec2( + T(s) * v.x, + T(s) * v.y); + } + + template + tvec2 operator*(tvec2 const & v1, tvec2 const & v2) + { + return tvec2( + v1.x * T(v2.x), + v1.y * T(v2.y)); + } + + template + tvec2 operator/(tvec2 const & v, T const & s) + { + return tvec2( + v.x / T(s), + v.y / T(s)); + } + + template + tvec2 operator/(T const & s, tvec2 const & v) + { + return tvec2( + T(s) / v.x, + T(s) / v.y); + } + + template + tvec2 operator/ (tvec2 const & v1, tvec2 const & v2 ) + { + return tvec2( + v1.x / T(v2.x), + v1.y / T(v2.y) + ); + } + + template + tvec2 operator- (tvec2 const & v) + { + return tvec2 ( + -v.x, + -v.y + ); + } + + template + tvec2 operator++ (tvec2 const & v, int) + { + return tvec2( + v.x + T(1), + v.y + T(1) + ); + } + + template + tvec2 operator-- (tvec2 const & v, int) + { + return tvec2( + v.x - T(1), + v.y - T(1) + ); + } + + + template + struct tvec3 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec3 type; + + value_type x; + value_type y; + value_type z; + + size_type length() const + { + return 3; + } + + value_type & operator[](size_type i) + { + assert(i < this->length()); + return (&x)[i]; + } + + value_type const & operator[](size_type i) const + { + assert(i < this->length()); + return (&x)[i]; + } + + inline tvec3() : + x(value_type(0)), + y(value_type(0)), + z(value_type(0)) + {} + + inline tvec3(tvec3 const & v) : + x(v.x), + y(v.y), + z(v.z) + {} + + inline tvec3(value_type s) : + x(s), + y(s), + z(s) + {} + + inline tvec3(value_type s0, value_type s1, value_type s2) : + x(s0), + y(s1), + z(s2) + {} + + + template + tvec3(U s) : + x(value_type(s)), + y(value_type(s)), + z(value_type(s)) + {} + + template + tvec3(A x, B y, C z) : + x(value_type(x)), + y(value_type(y)), + z(value_type(z)) + {} + + template + tvec3(tvec2 const& v, B s) : + x(value_type(v.x)), + y(value_type(v.y)), + z(value_type(s)) + {} + template + tvec3(A s,tvec2 const& v) : + x(value_type(s)), + y(value_type(v.x)), + z(value_type(v.y)) + {} + + template + tvec3(tvec3 const & v) : + x(value_type(v.x)), + y(value_type(v.y)), + z(value_type(v.z)) + {} + + + tvec3& operator= (tvec3 const & v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + return *this; + } + + template + tvec3& operator= (tvec3 const & v) + { + this->x = T(v.x); + this->y = T(v.y); + this->z = T(v.z); + return *this; + } + + template + tvec3 & operator+=(U const & s) + { + this->x += T(s); + this->y += T(s); + this->z += T(s); + return *this; + } + + template + tvec3 & operator+=(tvec3 const & v) + { + this->x += T(v.x); + this->y += T(v.y); + this->z += T(v.z); + return *this; + } + + template + tvec3 & operator-=(U const & s) + { + this->x -= T(s); + this->y -= T(s); + this->z -= T(s); + return *this; + } + + template + tvec3 & operator-=(tvec3 const & v) + { + this->x -= T(v.x); + this->y -= T(v.y); + this->z -= T(v.z); + return *this; + } + template + tvec3 & operator*=(U const & s) + { + this->x *= T(s); + this->y *= T(s); + this->z *= T(s); + return *this; + } + + template + tvec3 & operator*=(tvec3 const & v) + { + this->x *= T(v.x); + this->y *= T(v.y); + this->z *= T(v.z); + return *this; + } + + template + tvec3 & operator/=(U const & s) + { + this->x /= T(s); + this->y /= T(s); + this->z /= T(s); + return *this; + } + + template + tvec3 & operator/=(tvec3 const & v) + { + this->x /= T(v.x); + this->y /= T(v.y); + this->z /= T(v.z); + return *this; + } + + tvec3 & operator++() + { + ++this->x; + ++this->y; + ++this->z; + return *this; + } + tvec3 & operator--() + { + --this->x; + --this->y; + --this->z; + return *this; + } + + void makeFloor( const tvec3& cmp ) + { + if( cmp.x < x ) x = cmp.x; + if( cmp.y < y ) y = cmp.y; + if( cmp.z < z ) z = cmp.z; + } + void makeCeil( const tvec3& cmp ) + { + if( cmp.x > x ) x = cmp.x; + if( cmp.y > y ) y = cmp.y; + if( cmp.z > z ) z = cmp.z; + } + T lengthf() const + { + return (T)sqrtf( x * x + y * y + z * z ); + } + + }; + + template + bool operator >(const tvec3& left ,const tvec3& right) + { + return left.x > right.x && left.y > right.y && left.z > right.z; + } + + template + bool operator <(const tvec3& left ,const tvec3& right) + { + return left.x < right.x && left.y < right.y && left.z < right.z; + } + + template + tvec3 rotateX(const tvec3& v, T angle) + { + tvec3 res(v); + T c = cos(T(DEG2RAD(angle))); + T s = sin(T(DEG2RAD(angle))); + + res.y = v.y * c - v.z * s; + res.z = v.y * s + v.z * c; + return res; + } + + template + tvec3 rotateY(tvec3 const & v, T angle) + { + tvec3 res = v; + + T c = cos(T(DEG2RAD(angle))); + T s = sin(T(DEG2RAD(angle))); + + res.x = v.x * c + v.z * s; + res.z = -v.x * s + v.z * c; + return res; + } + + template + tvec3 rotateZ(tvec3 const & v, T angle) + { + + tvec3 res = v; + + T c = cos(DEG2RAD(angle)); + + T s = sin(DEG2RAD(angle)); + + res.x = v.x * c - v.y * s; + res.y = v.x * s + v.y * c; + return res; + } + /** + * 两个向量的夹角 + * 定义两个向量 A,B + * A·B = |A|*|B|*cos(@) + * cos(@) = A·B/|A|*|B| + * @ = acos(@) + */ + template + T angleBetweenVector(const tvec3& a, const tvec3& b) + { + #define Mag(V) (sqrtf(V.x*V.x + V.y*V.y + V.z*V.z)) + T dotProduct = dot(a, b); + T vectorsMagnitude = Mag(a) * Mag(b) ; + T angle = acos( dotProduct / vectorsMagnitude ); + T result = angle * T(RAD2DEG); + if(_isnan(result)) + { + return T(0); + } + else + { + return result; + } + } + + template + inline bool _isnan(T t) + { + return t == t; + } + + template + T angleBetweenVector(const tvec2& a, const tvec2& b) + { + #define Mag2D(V) (sqrtf(V.x*V.x + V.y*V.y)) + + T dotProduct = dot(a, b); + T vectorsMagnitude = Mag2D(a) * Mag2D(b) ; + T angle = acos( dotProduct / vectorsMagnitude ); + T result = angle * T(RAD2DEG); + if(_isnan(result)) + { + return T(0); + } + else + { + return result; + } + } + + template + static T clamp(T val, T minval, T maxval) + { + assert (minval < maxval && "Invalid clamp range"); + return MAX(MIN(val, maxval), minval); + } + + template + inline T acosEx (T val) + { + if ( T(-1.0f) < val ) + { + if ( val < 1.0f ) + return T(acos(val)); + else + return T(0); + } + else + { + return T(PI); + } + } + + template + inline T angleBetween(const tvec3& a, const tvec3& b) + { + T lenProduct = a.lengthf() * b.lengthf(); + + // Divide by zero check + if(lenProduct < 1e-6f) + lenProduct = 1e-6f; + + float f = dot(a,b) / lenProduct; + + f = clamp(f, T(-1.0), T(1.0)); + return acosEx(f); + + } + + /** + * 点在多边形里 + * 如果点在多边形中,则,点与边的夹角之和 == 360 + */ + template + bool insidePolyon( const tvec3& point, const tvec3 polygon[], size_t count) + { + tvec3 vA, vB; + T angle = T(0.0); + for (size_t i = 0; i < count; ++i) + { + vA = polygon[i] - point; + vB = polygon[(i + 1) % count] - point; + angle += angleBetweenVector(vA, vB); + } + if( abs(angle - 360 ) >= 0.5f) + { + return true; + } + return false; + } + + template + bool insidePolyon( const tvec2& point, const tvec2 polygon[], size_t count) + { + T angle = T(0.0); + tvec2 vA, vB; + for (size_t i = 0; i < count; ++i) + { + vA = polygon[i] - point; + vB = polygon[(i + 1) % count] - point; + tvec3 a(vA.x,vA.y,0); + tvec3 b(vB.x,vB.y,0); + angle += angleBetweenVector(a, b); + } + if( abs(angle - 360 ) >= 0.5f) + { + return true; + } + return false; + } + + template + bool pointinTriangle(tvec3 A, tvec3 B, tvec3 C, tvec3 P) + { + tvec3 v0 = C - A ; + tvec3 v1 = B - A ; + tvec3 v2 = P - A ; + + float dot00 = dot(v0,v0) ; + float dot01 = dot(v0,v1) ; + float dot02 = dot(v0,v2) ; + float dot11 = dot(v1,v1) ; + float dot12 = dot(v1,v2) ; + + float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01) ; + + float u = (dot11 * dot02 - dot01 * dot12) * inverDeno ; + if (u < 0 || u > 1) // if u out of range, return directly + { + return false ; + } + + float v = (dot00 * dot12 - dot01 * dot02) * inverDeno ; + if (v < 0 || v > 1) // if v out of range, return directly + { + return false ; + } + + return u + v <= 1 ; + } + + + + template + bool pointinTriangle(tvec2 A, tvec2 B, tvec2 C, tvec2 P) + { + return pointinTriangle( + tvec3(A.x,A.y,0), + tvec3(B.x,B.y,0), + tvec3(C.x,C.y,0), + tvec3(P.x,P.y,0)); + } + + + /** + * 射线与三角形相交 + */ + template + bool intersectTriangle( + const tvec3& orig, + const tvec3& dir, + tvec3& v0, + tvec3& v1, + tvec3& v2, + T* t, + T* u, + T* v + ) + { + // Find vectors for two edges sharing vert0 + tvec3 edge1 = v1 - v0; + tvec3 edge2 = v2 - v0; + + // Begin calculating determinant - also used to calculate U parameter + tvec3 pvec; + pvec = cross(dir, edge2 ); + + // If determinant is near zero, ray lies in plane of triangle + T det = dot( edge1,pvec ); + + tvec3 tvec; + if( det > 0 ) + { + tvec = orig - v0; + } + else + { + tvec = v0 - orig; + det = -det; + } + if( det < 0.0001f ) + return false; + // Calculate U parameter and test bounds + *u = dot( tvec, pvec ); + if( *u < 0.0f || *u > det ) + return false; + + // Prepare to test V parameter + tvec3 qvec; + qvec = cross(tvec, edge1 ); + + // Calculate V parameter and test bounds + *v = dot( dir, qvec ); + if( *v < T(0.0f) || *u + *v > det ) + return false; + + *t = dot( edge2,qvec ); + T fInvDet = T(1.0) / det; + *t *= fInvDet; + *u *= fInvDet; + *v *= fInvDet; + + return true; + } + /** + * 计算三角形面积 + */ + template T calcTriangleArea(const tvec3& pt1,const tvec3& pt2,const tvec3& pt3) + { + tvec3 e1 = pt2 - pt1; + tvec3 e2 = pt3 - pt1; + tvec3 e3 = cross(e1,e2); + return length(e3) * T(0.5); + } + + + template + bool operator==(tvec3 const & v1, tvec3 const & v2) + { + return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z); + } + + template + bool operator!=(tvec3 const & v1, tvec3 const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z); + } + + + template + tvec3 operator+(tvec3 const & v, T const & s) + { + return tvec3( + v.x + T(s), + v.y + T(s), + v.z + T(s)); + } + + template + tvec3 operator+ ( T const & s, tvec3 const & v) + { + return tvec3( + T(s) + v.x, + T(s) + v.y, + T(s) + v.z); + } + + template + tvec3 operator+ (tvec3 const & v1, tvec3 const & v2) + { + return tvec3( + v1.x + T(v2.x), + v1.y + T(v2.y), + v1.z + T(v2.z)); + } + + template + tvec3 operator- (tvec3 const & v, T const & s) + { + return tvec3( + v.x - T(s), + v.y - T(s), + v.z - T(s)); + } + + template + tvec3 operator- (T const & s, tvec3 const & v) + { + return tvec3( + T(s) - v.x, + T(s) - v.y, + T(s) - v.z); + } + + template + tvec3 operator- (tvec3 const & v1, tvec3 const & v2) + { + return tvec3( + v1.x - T(v2.x), + v1.y - T(v2.y), + v1.z - T(v2.z)); + } + + template + tvec3 operator*(tvec3 const & v, T const & s) + { + return tvec3( + v.x * T(s), + v.y * T(s), + v.z * T(s)); + } + + template + tvec3 operator* (T const & s, tvec3 const & v) + { + return tvec3( + T(s) * v.x, + T(s) * v.y, + T(s) * v.z); + } + + template + tvec3 operator* (tvec3 const & v1, tvec3 const & v2) + { + return tvec3( + v1.x * T(v2.x), + v1.y * T(v2.y), + v1.z * T(v2.z)); + } + + template + tvec3 operator/ (tvec3 const & v, T const & s) + { + return tvec3( + v.x / T(s), + v.y / T(s), + v.z / T(s)); + } + + template + tvec3 operator/ (T const & s, tvec3 const & v) + { + return tvec3( + T(s) / v.x, + T(s) / v.y, + T(s) / v.z); + } + + template + tvec3 operator/ (tvec3 const & v1, tvec3 const & v2) + { + return tvec3( + v1.x / T(v2.x), + v1.y / T(v2.y), + v1.z / T(v2.z)); + } + + template + tvec3 operator- (tvec3 const & v) + { + return tvec3( + -v.x, + -v.y, + -v.z); + } + + template + tvec3 operator++ (tvec3 const & v, int) + { + return tvec3( + v.x + T(1), + v.y + T(1), + v.z + T(1)); + } + + template + tvec3 operator-- (tvec3 const & v, int) + { + return tvec3( + v.x - T(1), + v.y - T(1), + v.z - T(1)); + } + template + struct tvec4 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec4 type; + + + + value_type x, y, z, w; + + size_type length() const + { + return 4; + } + + value_type & operator[](size_type i) + { + assert(i < this->length()); + return (&x)[i]; + } + + value_type const & operator[](size_type i) const + { + assert(i < this->length()); + return (&x)[i]; + } + + tvec4() : + x(value_type(0)), + y(value_type(0)), + z(value_type(0)), + w(value_type(0)) + {} + tvec4(tvec3 const& v, T s) : + x(v.x), + y(v.y), + z(v.z), + w(s) + {} + tvec4(T s) : + x(s), + y(s), + z(s), + w(s) + {} + tvec4(tvec4 const & v) : + x(v.x), + y(v.y), + z(v.z), + w(v.w) + {} + + template + tvec4(tvec3 const & v, B s): + x(value_type(v.x)), + y(value_type(v.y)), + z(value_type(v.z)), + w(value_type(s)) + {} + + template + tvec4(A s,tvec3 const & v): + x(value_type(s)), + y(value_type(v.x)), + z(value_type(v.y)), + w(value_type(v.z)) + {} + + template + tvec4(tvec4 const & v) : + x(value_type(v.x)), + y(value_type(v.y)), + z(value_type(v.z)), + w(value_type(v.w)) + {} + + tvec4 + ( + value_type s1, + value_type s2, + value_type s3, + value_type s4 + ) : + x(s1), + y(s2), + z(s3), + w(s4) + {} + + tvec4 & operator=(tvec4 const & v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + this->w = v.w; + return *this; + } + + template + tvec4 & operator= (tvec4 const & v) + { + this->x = T(v.x); + this->y = T(v.y); + this->z = T(v.z); + this->w = T(v.w); + return *this; + } + + template + tvec4 & operator+=(U const & s) + { + this->x += T(s); + this->y += T(s); + this->z += T(s); + this->w += T(s); + return *this; + } + template + tvec4 & operator+=(tvec4 const & v) + { + this->x += T(v.x); + this->y += T(v.y); + this->z += T(v.z); + this->w += T(v.w); + return *this; + } + + template + tvec4 & operator-=(U const & s) + { + this->x -= T(s); + this->y -= T(s); + this->z -= T(s); + this->w -= T(s); + return *this; + } + + template + tvec4 & operator-=(tvec4 const & v) + { + this->x -= T(v.x); + this->y -= T(v.y); + this->z -= T(v.z); + this->w -= T(v.w); + return *this; + } + template + tvec4 & operator*= (U const & s) + { + this->x *= T(s); + this->y *= T(s); + this->z *= T(s); + this->w *= T(s); + return *this; + } + + template + tvec4 & operator*=( tvec4 const & v) + { + this->x *= T(v.x); + this->y *= T(v.y); + this->z *= T(v.z); + this->w *= T(v.w); + return *this; + } + template + tvec4 & operator/=(U const & s) + { + this->x /= T(s); + this->y /= T(s); + this->z /= T(s); + this->w /= T(s); + return *this; + } + + template + tvec4 & operator/=(tvec4 const & v) + { + this->x /= T(v.x); + this->y /= T(v.y); + this->z /= T(v.z); + this->w /= T(v.w); + return *this; + } + + tvec4 & operator++() + { + ++this->x; + ++this->y; + ++this->z; + ++this->w; + return *this; + } + + tvec4 & operator--() + { + --this->x; + --this->y; + --this->z; + --this->w; + return *this; + } + }; + + template + tvec4 rotateX(const tvec4& v, T angle) + { + tvec4 res(v); + T c = cos(DEG2RAD(angle)); + T s = sin(DEG2RAD(angle)); + + res.y = v.y * c - v.z * s; + res.z = v.y * s + v.z * c; + return res; + } + + template + tvec4 rotateY(tvec4 const & v, T angle) + { + tvec4 res = v; + + T c = cos(DEG2RAD(angle)); + T s = sin(DEG2RAD(angle)); + + res.x = v.x * c + v.z * s; + res.z = -v.x * s + v.z * c; + return res; + } + + template + tvec4 rotateZ(tvec4 const & v, T angle) + { + + tvec4 res = v; + + T c = cos(DEG2RAD(angle)); + T s = sin(DEG2RAD(angle)); + + res.x = v.x * c - v.y * s; + res.y = v.x * s + v.y * c; + return res; + } + template + tvec4 operator+ (tvec4 const & v, T const & s) + { + return tvec4( + v.x + s, + v.y + s, + v.z + s, + v.w + s); + } + + template + tvec4 operator+ (T const & s, tvec4 const & v) + { + return tvec4( + s + v.x, + s + v.y, + s + v.z, + s + v.w); + } + + template + tvec4 operator+ (tvec4 const & v1, tvec4 const & v2) + { + return tvec4( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z, + v1.w + v2.w); + } + + template + tvec4 operator- (tvec4 const & v, T const & s) + { + return tvec4( + v.x - s, + v.y - s, + v.z - s, + v.w - s); + } + + template + tvec4 operator- (T const & s, tvec4 const & v) + { + return tvec4( + s - v.x, + s - v.y, + s - v.z, + s - v.w); + } + + template + tvec4 operator- + ( + tvec4 const & v1, + tvec4 const & v2 + ) + { + return tvec4( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z, + v1.w - v2.w); + } + + template + tvec4 operator* (tvec4 const & v, T const & s) + { + return tvec4( + v.x * s, + v.y * s, + v.z * s, + v.w * s); + } + + template + tvec4 operator* (T const & s, tvec4 const & v) + { + return tvec4( + s * v.x, + s * v.y, + s * v.z, + s * v.w); + } + + template + tvec4 operator*(tvec4 const & v1, tvec4 const & v2) + { + return tvec4( + v1.x * v2.x, + v1.y * v2.y, + v1.z * v2.z, + v1.w * v2.w); + } + + template + tvec4 operator/ (tvec4 const & v, T const & s) + { + return tvec4( + v.x / s, + v.y / s, + v.z / s, + v.w / s); + } + + template + tvec4 operator/ (T const & s, tvec4 const & v) + { + return tvec4( + s / v.x, + s / v.y, + s / v.z, + s / v.w); + } + + template + tvec4 operator/ ( tvec4 const & v1, tvec4 const & v2) + { + return tvec4( + v1.x / v2.x, + v1.y / v2.y, + v1.z / v2.z, + v1.w / v2.w); + } + + template + tvec4 operator- ( tvec4 const & v) + { + return tvec4( + -v.x, + -v.y, + -v.z, + -v.w); + } + + + template + bool operator== + ( + tvec4 const & v1, + tvec4 const & v2 + ) + { + return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z) && (v1.w == v2.w); + } + + template + bool operator!=(tvec4 const & v1, tvec4 const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z) || (v1.w != v2.w); + } + + template + class trect + { + public: + trect(T left = 0,T top = 0,T right = 0,T bottom = 0) + { + _left = left; + _top = top; + _right = right; + _bottom = bottom; + } + void fromCenter(T x,T y,T size) + { + _left = x - size * T(0.5f); + _top = y - size * T(0.5f); + _right = x + size * T(0.5f); + _bottom = y + size * T(0.5f); + } + + void fromCenter(T x,T y,T sizeX,T sizeY) + { + _left = x - sizeX * T(0.5f); + _top = y - sizeY * T(0.5f); + _right = x + sizeX * T(0.5f); + _bottom = y + sizeY * T(0.5f); + } + + bool ptInRect(T x,T y) + { + return x >= _left && x <= _right && y >= _top && y <= _bottom; + } + + tvec2center() const + { + return tvec2((_left + _right) * T(0.5f),(_bottom + _top) * T(0.5f)); + } + + tvec2halSize() const + { + return tvec2((_right - _left) * T(0.5f),(_bottom - _top) * T(0.5f)); + } + public: + T _left; + T _top; + T _right; + T _bottom; + }; + + template + struct tmat2x2 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec2 col_type; + typedef tvec2 row_type; + typedef tmat2x2 type; + typedef tmat2x2 transpose_type; + + + public: + tmat2x2 _inverse() const + { + value_type Determinant = this->value[0][0] * this->value[1][1] - this->value[1][0] * this->value[0][1]; + + tmat2x2 Inverse( + + this->value[1][1] / Determinant, + - this->value[0][1] / Determinant, + - this->value[1][0] / Determinant, + + this->value[0][0] / Determinant); + return Inverse; + } + + private: + col_type value[2]; + + public: + + size_type length() const + { + return 2; + } + + static size_type col_size() + { + return 2; + } + + static size_type row_size() + { + return 2; + } + + col_type &operator[](size_type i) + { + assert(i < this->length()); + return this->value[i]; + } + col_type const &operator[](size_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + tmat2x2() + { + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + } + + tmat2x2(tmat2x2 const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + tmat2x2(value_type s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero); + this->value[1] = col_type(Zero, s); + } + + tmat2x2(value_type x0, value_type y0, value_type x1, value_type y1) + { + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + } + + tmat2x2(col_type const & v0, col_type const & v1) + { + this->value[0] = v0; + this->value[1] = v1; + } + + template + tmat2x2(U s) + { + value_type const Zero(0); + this->value[0] = tvec2(value_type(s), Zero); + this->value[1] = tvec2(Zero, value_type(s)); + } + + template + tmat2x2(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + this->value[0] = col_type(value_type(x1), value_type(y1)); + this->value[1] = col_type(value_type(x2), value_type(y2)); + } + template + tmat2x2 + ( + tvec2 const & v1, + tvec2 const & v2 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + } + + template + tmat2x2(tmat2x2 const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + tmat2x2& operator=(tmat2x2 const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + tmat2x2& operator= + ( + tmat2x2 const & m + ) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + tmat2x2& operator+=(U const & s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template + tmat2x2& operator+= + ( + tmat2x2 const & m + ) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + tmat2x2& operator-=(U const & s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template + tmat2x2& operator-=(tmat2x2 const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + tmat2x2& operator*= ( U const & s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template + tmat2x2& operator*= (tmat2x2 const & m) + { + return (*this = *this * m); + } + + template + tmat2x2& operator/= (U const & s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + template + tmat2x2& operator/= (tmat2x2 const & m) + { + return (*this = *this / m); + } + + tmat2x2& operator++ () + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + tmat2x2& operator-- () + { + --this->value[0]; + --this->value[1]; + return *this; + }; + }; + + template + tmat2x2 rotate(T angle) + { + T c = cos(DEG2RAD(angle)); + T s = sin(DEG2RAD(angle)); + return tmat2x2(c,s,-s,c); + } + + template + tmat2x2 operator+ (tmat2x2 const & m, T const & s) + { + return tmat2x2(m[0] + s,m[1] + s); + } + + template + tmat2x2 operator+ (T const & s, tmat2x2 const & m) + { + return tmat2x2(m[0] + s,m[1] + s); + } + + template + tmat2x2 operator+ (tmat2x2 const & m1, tmat2x2 const & m2) + { + return tmat2x2(m1[0] + m2[0],m1[1] + m2[1]); + } + + template + tmat2x2 operator- (tmat2x2 const & m, T const & s) + { + return tmat2x2(m[0] - s,m[1] - s); + } + + template + tmat2x2 operator- (T const & s, tmat2x2 const & m) + { + return tmat2x2(s - m[0],s - m[1]); + } + + template + tmat2x2 operator- (tmat2x2 const & m1, tmat2x2 const & m2) + { + return tmat2x2(m1[0] - m2[0],m1[1] - m2[1]); + } + + template + tmat2x2 operator* (tmat2x2 const & m, T const & s) + { + return tmat2x2(m[0] * s,m[1] * s); + } + + template + tmat2x2 operator* ( T const & s, tmat2x2 const & m) + { + return tmat2x2(m[0] * s,m[1] * s); + } + + template + tvec2 operator*(tmat2x2 const & m, tvec2 const & v) + { + return tvec2( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y); + } + + template + tvec2 operator*(tvec2 const & v, tmat2x2 const & m) + { + return tvec2( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1]); + } + + template + tmat2x2 operator*(tmat2x2 const & m1,tmat2x2 const & m2) + { + return tmat2x2( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1]); + } + + + + template + struct tmat3x3 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec3 col_type; + typedef tvec3 row_type; + typedef tmat3x3 type; + typedef tmat3x3 transpose_type; + + + private: + // Data + col_type value[3]; + + public: + size_type length() const + { + return 3; + } + size_type col_size() + { + return 3; + } + + size_type row_size() + { + return 3; + } + + tmat3x3() + { + value_type const Zero(0); + value_type const One(1); + this->value[0] = col_type(One, Zero, Zero); + this->value[1] = col_type(Zero, One, Zero); + this->value[2] = col_type(Zero, Zero, One); + } + + tmat3x3 + ( + tmat3x3 const & m + ) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + + tmat3x3(value_type const & s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero, Zero); + this->value[1] = col_type(Zero, s, Zero); + this->value[2] = col_type(Zero, Zero, s); + } + + + tmat3x3 + ( + value_type const & x0, value_type const & y0, value_type const & z0, + value_type const & x1, value_type const & y1, value_type const & z1, + value_type const & x2, value_type const & y2, value_type const & z2 + ) + { + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + } + + tmat3x3 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + } + + template + tmat3x3(U const & s) + { + value_type const Zero(0); + this->value[0] = tvec3(value_type(s), Zero, Zero); + this->value[1] = tvec3(Zero, value_type(s), Zero); + this->value[2] = tvec3(Zero, Zero, value_type(s)); + } + + template < + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + tmat3x3 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2, + X3 const & x3, Y3 const & y3, Z3 const & z3 + ) + { + this->value[0] = col_type(value_type(x1), value_type(y1), value_type(z1)); + this->value[1] = col_type(value_type(x2), value_type(y2), value_type(z2)); + this->value[2] = col_type(value_type(x3), value_type(y3), value_type(z3)); + } + + template + tmat3x3 + ( + tvec3 const & v1, + tvec3 const & v2, + tvec3 const & v3 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + } + + template + tmat3x3(tmat3x3 const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + + + tmat3x3 _inverse() const + { + T S00 = value[0][0]; + T S01 = value[0][1]; + T S02 = value[0][2]; + + T S10 = value[1][0]; + T S11 = value[1][1]; + T S12 = value[1][2]; + + T S20 = value[2][0]; + T S21 = value[2][1]; + T S22 = value[2][2]; + + tmat3x3 Inverse( + S11 * S22 - S21 * S12, + S12 * S20 - S22 * S10, + S10 * S21 - S20 * S11, + S02 * S21 - S01 * S22, + S00 * S22 - S02 * S20, + S01 * S20 - S00 * S21, + S12 * S01 - S11 * S02, + S10 * S02 - S12 * S00, + S11 * S00 - S10 * S01); + + T Determinant = S00 * (S11 * S22 - S21 * S12) + - S10 * (S01 * S22 - S21 * S02) + + S20 * (S01 * S12 - S11 * S02); + + Inverse /= Determinant; + return Inverse; + } + + col_type & operator[](size_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + col_type const & operator[](size_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + tmat3x3 & operator=(tmat3x3 const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + template + tmat3x3 & operator=(tmat3x3 const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + tmat3x3 & operator+= (U const & s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + tmat3x3 & operator+=(tmat3x3 const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + tmat3x3 & operator-= (U const & s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + tmat3x3 & operator-= (tmat3x3 const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + tmat3x3 & operator*= (U const & s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + template + tmat3x3 & operator*= (tmat3x3 const & m) + { + return (*this = *this * m); + } + + template + tmat3x3 & operator/= (U const & s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template + tmat3x3 & operator/= (tmat3x3 const & m) + { + return (*this = *this / m); + } + + tmat3x3 & operator++ () + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + tmat3x3 & operator-- () + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + }; + + template + tmat3x3 operator+ (tmat3x3 const & m, T const & s) + { + return tmat3x3( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template + tmat3x3 operator+ (T const & s, tmat3x3 const & m) + { + return tmat3x3( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template + tmat3x3 operator+ (tmat3x3 const & m1, tmat3x3 const & m2) + { + return tmat3x3( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + tmat3x3 operator- (tmat3x3 const & m, T const & s) + { + return tmat3x3( + m[0] - s, + m[1] - s, + m[2] - s); + } + + template + tmat3x3 operator- (T const & s, tmat3x3 const & m) + { + return tmat3x3( + s - m[0], + s - m[1], + s - m[2]); + } + + template + tmat3x3 operator- (tmat3x3 const & m1, tmat3x3 const & m2) + { + return tmat3x3( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + tmat3x3 operator* (tmat3x3 const & m, T const & s) + { + return tmat3x3( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template + tmat3x3 operator* (T const & s, tmat3x3 const & m) + { + return tmat3x3( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template + tvec3 operator* (tmat3x3 const & m, tvec3 const & v) + { + return tvec3( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z); + } + + template + tvec3 operator* (tvec3 const & v, tmat3x3 const & m) + { + return tvec3( + m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, + m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z, + m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z); + } + + template + tmat3x3 operator* (tmat3x3 const & m1, tmat3x3 const & m2) + { + T const srcA00 = m1[0][0]; + T const srcA01 = m1[0][1]; + T const srcA02 = m1[0][2]; + T const srcA10 = m1[1][0]; + T const srcA11 = m1[1][1]; + T const srcA12 = m1[1][2]; + T const srcA20 = m1[2][0]; + T const srcA21 = m1[2][1]; + T const srcA22 = m1[2][2]; + + T const srcB00 = m2[0][0]; + T const srcB01 = m2[0][1]; + T const srcB02 = m2[0][2]; + T const srcB10 = m2[1][0]; + T const srcB11 = m2[1][1]; + T const srcB12 = m2[1][2]; + T const srcB20 = m2[2][0]; + T const srcB21 = m2[2][1]; + T const srcB22 = m2[2][2]; + + tmat3x3 res; + res[0][0] = srcA00 * srcB00 + srcA10 * srcB01 + srcA20 * srcB02; + res[0][1] = srcA01 * srcB00 + srcA11 * srcB01 + srcA21 * srcB02; + res[0][2] = srcA02 * srcB00 + srcA12 * srcB01 + srcA22 * srcB02; + res[1][0] = srcA00 * srcB10 + srcA10 * srcB11 + srcA20 * srcB12; + res[1][1] = srcA01 * srcB10 + srcA11 * srcB11 + srcA21 * srcB12; + res[1][2] = srcA02 * srcB10 + srcA12 * srcB11 + srcA22 * srcB12; + res[2][0] = srcA00 * srcB20 + srcA10 * srcB21 + srcA20 * srcB22; + res[2][1] = srcA01 * srcB20 + srcA11 * srcB21 + srcA21 * srcB22; + res[2][2] = srcA02 * srcB20 + srcA12 * srcB21 + srcA22 * srcB22; + return res; + } + + template + tmat3x3 operator/ (tmat3x3 const & m, T const & s) + { + return tmat3x3( + m[0] / s, + m[1] / s, + m[2] / s); + } + + template + tmat3x3 operator/ (T const & s, tmat3x3 const & m) + { + return tmat3x3( + s / m[0], + s / m[1], + s / m[2] + ); + } + + template + tvec3 operator/ (tmat3x3 const & m, tvec3 const & v) + { + return m._inverse() * v; + } + + template + tvec3 operator/ (tvec3 const & v, tmat3x3 const & m) + { + return v * m._inverse(); + } + + template + tmat3x3 operator/ (tmat3x3 const & m1, tmat3x3 const & m2) + { + return m1 * m2._inverse(); + } + + template + tmat3x3 const operator- (tmat3x3 const & m) + { + return tmat3x3( + -m[0], + -m[1], + -m[2]); + } + + template + tmat3x3 const operator++ (tmat3x3 const & m, int) + { + return tmat3x3( + m[0] + T(1), + m[1] + T(1), + m[2] + T(1)); + } + + template + tmat3x3 const operator-- (tmat3x3 const & m, int) + { + return tmat3x3( + m[0] - T(1), + m[1] - T(1), + m[2] - T(1)); + } + template + bool operator==(tmat3x3 const & m1, tmat3x3 const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + bool operator!=(tmat3x3 const & m1, tmat3x3 const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } + + + + template + struct tmat4x4 + { + typedef T value_type; + typedef std::size_t size_type; + typedef tvec4 col_type; + typedef tvec4 row_type; + typedef tmat4x4 type; + typedef tmat4x4 transpose_type; + + + public: + tmat4x4 inverse() const + { + value_type subFactor00 = this->value[2][2] * this->value[3][3] - this->value[3][2] * this->value[2][3]; + value_type subFactor01 = this->value[2][1] * this->value[3][3] - this->value[3][1] * this->value[2][3]; + value_type subFactor02 = this->value[2][1] * this->value[3][2] - this->value[3][1] * this->value[2][2]; + value_type subFactor03 = this->value[2][0] * this->value[3][3] - this->value[3][0] * this->value[2][3]; + value_type subFactor04 = this->value[2][0] * this->value[3][2] - this->value[3][0] * this->value[2][2]; + value_type subFactor05 = this->value[2][0] * this->value[3][1] - this->value[3][0] * this->value[2][1]; + value_type subFactor06 = this->value[1][2] * this->value[3][3] - this->value[3][2] * this->value[1][3]; + value_type subFactor07 = this->value[1][1] * this->value[3][3] - this->value[3][1] * this->value[1][3]; + value_type subFactor08 = this->value[1][1] * this->value[3][2] - this->value[3][1] * this->value[1][2]; + value_type subFactor09 = this->value[1][0] * this->value[3][3] - this->value[3][0] * this->value[1][3]; + value_type subFactor10 = this->value[1][0] * this->value[3][2] - this->value[3][0] * this->value[1][2]; + value_type subFactor11 = this->value[1][1] * this->value[3][3] - this->value[3][1] * this->value[1][3]; + value_type SubFactor12 = this->value[1][0] * this->value[3][1] - this->value[3][0] * this->value[1][1]; + value_type subFactor13 = this->value[1][2] * this->value[2][3] - this->value[2][2] * this->value[1][3]; + value_type subFactor14 = this->value[1][1] * this->value[2][3] - this->value[2][1] * this->value[1][3]; + value_type subFactor15 = this->value[1][1] * this->value[2][2] - this->value[2][1] * this->value[1][2]; + value_type subFactor16 = this->value[1][0] * this->value[2][3] - this->value[2][0] * this->value[1][3]; + value_type subFactor17 = this->value[1][0] * this->value[2][2] - this->value[2][0] * this->value[1][2]; + value_type subFactor18 = this->value[1][0] * this->value[2][1] - this->value[2][0] * this->value[1][1]; + + tmat4x4 res( + + this->value[1][1] * subFactor00 - this->value[1][2] * subFactor01 + this->value[1][3] * subFactor02, + - this->value[1][0] * subFactor00 + this->value[1][2] * subFactor03 - this->value[1][3] * subFactor04, + + this->value[1][0] * subFactor01 - this->value[1][1] * subFactor03 + this->value[1][3] * subFactor05, + - this->value[1][0] * subFactor02 + this->value[1][1] * subFactor04 - this->value[1][2] * subFactor05, + + - this->value[0][1] * subFactor00 + this->value[0][2] * subFactor01 - this->value[0][3] * subFactor02, + + this->value[0][0] * subFactor00 - this->value[0][2] * subFactor03 + this->value[0][3] * subFactor04, + - this->value[0][0] * subFactor01 + this->value[0][1] * subFactor03 - this->value[0][3] * subFactor05, + + this->value[0][0] * subFactor02 - this->value[0][1] * subFactor04 + this->value[0][2] * subFactor05, + + + this->value[0][1] * subFactor06 - this->value[0][2] * subFactor07 + this->value[0][3] * subFactor08, + - this->value[0][0] * subFactor06 + this->value[0][2] * subFactor09 - this->value[0][3] * subFactor10, + + this->value[0][0] * subFactor11 - this->value[0][1] * subFactor09 + this->value[0][3] * SubFactor12, + - this->value[0][0] * subFactor08 + this->value[0][1] * subFactor10 - this->value[0][2] * SubFactor12, + + - this->value[0][1] * subFactor13 + this->value[0][2] * subFactor14 - this->value[0][3] * subFactor15, + + this->value[0][0] * subFactor13 - this->value[0][2] * subFactor16 + this->value[0][3] * subFactor17, + - this->value[0][0] * subFactor14 + this->value[0][1] * subFactor16 - this->value[0][3] * subFactor18, + + this->value[0][0] * subFactor15 - this->value[0][1] * subFactor17 + this->value[0][2] * subFactor18); + + value_type determinant = + + this->value[0][0] * res[0][0] + + this->value[0][1] * res[1][0] + + this->value[0][2] * res[2][0] + + this->value[0][3] * res[3][0]; + + res /= determinant; + return res; + } + + + private: + col_type value[4]; + public: + + size_type length() const + { + return 4; + } + size_type col_size() + { + return 4; + } + size_type row_size() + { + return 4; + } + void identify() + { + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); + } + col_type & operator[](size_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + col_type const & operator[](size_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + tmat4x4(tmat4x4 const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + this->value[3] = m.value[3]; + } + + tmat4x4(tmat3x3 const & m) + { + this->value[0] = col_type(m[0], value_type(0)); + this->value[1] = col_type(m[1], value_type(0)); + this->value[2] = col_type(m[2], value_type(0)); + this->value[3] = col_type(value_type(0), value_type(0), value_type(0), value_type(1)); + } + tmat4x4() + { + } + + tmat4x4(value_type s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero, Zero, Zero); + this->value[1] = col_type(Zero, s, Zero, Zero); + this->value[2] = col_type(Zero, Zero, s, Zero); + this->value[3] = col_type(Zero, Zero, Zero, s); + } + + tmat4x4 + ( + value_type const & x0, value_type const & y0, value_type const & z0, value_type const & w0, + value_type const & x1, value_type const & y1, value_type const & z1, value_type const & w1, + value_type const & x2, value_type const & y2, value_type const & z2, value_type const & w2, + value_type const & x3, value_type const & y3, value_type const & z3, value_type const & w3 + ) + { + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); + this->value[3] = col_type(x3, y3, z3, w3); + } + + tmat4x4 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; + } + + template + tmat4x4(tmat4x4 const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template + tmat4x4(U const & s) + { + value_type const Zero(0); + this->value[0] = tvec4(value_type(s), Zero, Zero, Zero); + this->value[1] = tvec4(Zero, value_type(s), Zero, Zero); + this->value[2] = tvec4(Zero, Zero, value_type(s), Zero); + this->value[3] = tvec4(Zero, Zero, Zero, value_type(s)); + } + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + tmat4x4 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2, + X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3, + X4 const & x4, Y4 const & y4, Z4 const & z4, W4 const & w4 + ) + { + this->value[0] = col_type(value_type(x1), value_type(y1), value_type(z1), value_type(w1)); + this->value[1] = col_type(value_type(x2), value_type(y2), value_type(z2), value_type(w2)); + this->value[2] = col_type(value_type(x3), value_type(y3), value_type(z3), value_type(w3)); + this->value[3] = col_type(value_type(x4), value_type(y4), value_type(z4), value_type(w4)); + } + template + tmat4x4 + ( + tvec4 const & v1, + tvec4 const & v2, + tvec4 const & v3, + tvec4 const & v4 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); + } + + T const * data() const + { + return &this->value[0][0]; + } + tmat4x4& operator= (tmat4x4 const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + tmat4x4& operator= (tmat4x4 const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + tmat4x4& operator+= (U const & s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + tmat4x4& operator+= (tmat4x4 const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + tmat4x4 & operator-= (U const & s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + tmat4x4 & operator-= (tmat4x4 const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + tmat4x4 & operator*= (U const & s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + tmat4x4 & operator*= (tmat4x4 const & m) + { + return (*this = *this * m); + } + + template + tmat4x4 & operator/= (U const & s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + template + tmat4x4 & operator/= (tmat4x4 const & m) + { + return (*this = *this / m); + } + + tmat4x4 & operator++ () + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + tmat4x4 & operator-- () + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + tmat4x4& translate( value_type x,value_type y,value_type z) + { + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(x, y, z, 1); + return *this; + } + template + tmat4x4& translate( U x,U y,U z) + { + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(T(x), T(y), T(z), 1); + return *this; + } + + tmat4x4& translate(tvec3 const& pos) + { + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(pos.x,pos.y, pos.z, 1); + return *this; + } + template + tmat4x4& translate(tvec3 const& pos) + { + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(T(pos.x),T(pos.y), T(pos.z), 1); + return *this; + } + + tmat4x4& rotate(value_type angle,tvec3 const & v ) + { + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + tvec3 axis = normalize(v); + + tvec3 temp = (T(1) - c) * axis; + + tmat4x4 res; + this->value[0][0] = c + temp[0] * axis[0]; + this->value[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + this->value[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + this->value[0][3] = 0; + + this->value[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + this->value[1][1] = c + temp[1] * axis[1]; + this->value[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + this->value[1][3] = 0; + + this->value[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + this->value[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + this->value[2][2] = c + temp[2] * axis[2]; + this->value[2][3] = 0; + + this->value[3][0] = 0; + this->value[3][1] = 0; + this->value[3][2] = 0; + this->value[3][3] = 1; + return *this; + } + + tmat4x4& rotateX(value_type angle) + { + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, c, s, 0); + this->value[2] = col_type(0,-s, c, 0); + this->value[3] = col_type(0, 0, 0, 1); + + return *this; + } + template + tmat4x4& rotateX(U angle) + { + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, c, s, 0); + this->value[2] = col_type(0,-s, c, 0); + this->value[3] = col_type(0, 0, 0, 1); + + return *this; + } + + tmat4x4& rotateY(value_type angle) + { + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type(c, 0,-s, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(s, 0, c, 0); + this->value[3] = col_type(0, 0, 0, 1); + return *this; + + } + template + tmat4x4& rotateY(U angle) + { + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type(c, 0,-s, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(s, 0, c, 0); + this->value[3] = col_type(0, 0, 0, 1); + return *this; + + } + tmat4x4& rotateZ(value_type angle) + { + T a = T(DEG2RAD(angle)); + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type( c, s, 0, 0); + this->value[1] = col_type(-s, c, 0, 0); + this->value[2] = col_type( 0, 0, 1, 0); + this->value[3] = col_type( 0, 0, 0, 1); + return *this; + } + template + tmat4x4& rotateZ(U angle) + { + T a = DEG2RAD(angle); + + T c = cos(a); + T s = sin(a); + + this->value[0] = col_type( c, s, 0, 0); + this->value[1] = col_type(-s, c, 0, 0); + this->value[2] = col_type( 0, 0, 1, 0); + this->value[3] = col_type( 0, 0, 0, 1); + return *this; + } + + + tmat4x4 rotateXY(T angleX, T angleY) + { + T cosX = cos(DEG2RAD(angleX)); + T sinX = sin(DEG2RAD(angleX)); + T cosY = cos(DEG2RAD(angleY)); + T sinY = sin(DEG2RAD(angleY)); + + + this->value[0] = col_type( cosY, -sinX * sinY, cosX * sinY,0); + this->value[1] = col_type( 0, cosX, sinX, 0); + this->value[2] = col_type( -sinY , -sinX * cosY, cosX * cosY,0); + this->value[3] = col_type( 0, 0, 0, 1); + return *this; + } + + tmat4x4 rotateYX(T angleX, T angleY) + { + T cosX = cos(DEG2RAD(angleX)); + T sinX = sin(DEG2RAD(angleX)); + T cosY = cos(DEG2RAD(angleY)); + T sinY = sin(DEG2RAD(angleY)); + + + this->value[0] = col_type( cosY, 0, sinY, 0); + this->value[1] = col_type( -sinX * sinY,cosX, sinX * cosY,0); + this->value[2] = col_type( -cosX * sinY,-sinX, cosX * cosY,0); + this->value[3] = col_type( 0, 0, 0, 1); + + return *this; + } + + tmat4x4 rotateYXZ( T yaw, T pitch, T roll) + { + T tmp_ch = cos(DEG2RAD(yaw)); + T tmp_sh = sin(DEG2RAD(yaw)); + T tmp_cp = cos(DEG2RAD(pitch)); + T tmp_sp = sin(DEG2RAD(pitch)); + T tmp_cb = cos(DEG2RAD(roll)); + T tmp_sb = sin(DEG2RAD(roll)); + + tmat4x4 Result; + this->value[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + this->value[0][1] = tmp_sb * tmp_cp; + this->value[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + this->value[0][3] = T(0); + this->value[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + this->value[1][1] = tmp_cb * tmp_cp; + this->value[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + this->value[1][3] = T(0); + this->value[2][0] = tmp_sh * tmp_cp; + this->value[2][1] = -tmp_sp; + this->value[2][2] = tmp_ch * tmp_cp; + this->value[2][3] = T(0); + this->value[3][0] = T(0); + this->value[3][1] = T(0); + this->value[3][2] = T(0); + this->value[3][3] = T(1); + + return *this; + } + + tmat4x4 yawPitchRoll( T yaw, T pitch, T roll) + { + T tmp_ch = cos(DEG2RAD(yaw)); + T tmp_sh = sin(DEG2RAD(yaw)); + T tmp_cp = cos(DEG2RAD(pitch)); + T tmp_sp = sin(DEG2RAD(pitch)); + T tmp_cb = cos(DEG2RAD(roll)); + T tmp_sb = sin(DEG2RAD(roll)); + + this->value[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + this->value[0][1] = tmp_sb * tmp_cp; + this->value[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + this->value[0][3] = T(0); + this->value[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + this->value[1][1] = tmp_cb * tmp_cp; + this->value[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + this->value[1][3] = T(0); + this->value[2][0] = tmp_sh * tmp_cp; + this->value[2][1] = -tmp_sp; + this->value[2][2] = tmp_ch * tmp_cp; + this->value[2][3] = T(0); + this->value[3][0] = T(0); + this->value[3][1] = T(0); + this->value[3][2] = T(0); + this->value[3][3] = T(1); + + return *this; + } + + tmat4x4& scale(tvec3 const& s) + { + this->value[0] = col_type(s[0], 0, 0, 0); + this->value[1] = col_type(0, s[1], 0, 0); + this->value[2] = col_type(0, 0, s[2], 0); + this->value[3] = col_type(0, 0, 0, 1); + + return *this; + } + + tmat4x4& scale(value_type x,value_type y,value_type z) + { + this->value[0] = col_type(x, 0, 0, 0); + this->value[1] = col_type(0, y, 0, 0); + this->value[2] = col_type(0, 0, z, 0); + this->value[3] = col_type(0, 0, 0, 1); + + return *this; + } + + template + tmat4x4& scale(U x,U y,U z) + { + this->value[0] = col_type(value_type(x), 0, 0, 0); + this->value[1] = col_type(0, value_type(y), 0, 0); + this->value[2] = col_type(0, 0, value_type(z), 0); + this->value[3] = col_type(0, 0, 0, 1); + + return *this; + } + + template + tmat4x4& scale(U x,V y,W z) + { + this->value[0] = col_type(value_type(x), 0, 0, 0); + this->value[1] = col_type(0, value_type(y), 0, 0); + this->value[2] = col_type(0, 0, value_type(z), 0); + this->value[3] = col_type(0, 0, 0, 1); + return *this; + } + + tmat4x4 transpose( ) const + { + return tmat4x4( + this->value[0][0], this->value[1][0], this->value[2][0], this->value[3][0], + this->value[0][1], this->value[1][1], this->value[2][1], this->value[3][1], + this->value[0][2], this->value[1][2], this->value[2][2], this->value[3][2], + this->value[0][3], this->value[1][3], this->value[2][3], this->value[3][3] + ); + } + + tmat4x4 extractMatrixRotation() const + { + return tmat4x4( + this->value[0][0], this->value[0][1], this->value[0][2], 0.0, + this->value[1][0], this->value[1][1], this->value[1][2], 0.0, + this->value[2][0], this->value[2][1], this->value[2][2], 0.0, + 0.0, 0.0, 0.0, 1.0 + ); + } + }; + + + + template + tmat4x4 rotateX(T angleX) + { + T cosX = cos(DEG2RAD(angleX)); + T sinX = sin(DEG2RAD(angleX)); + + return tmat4x4( + T(1), T(0), T(0), T(0), + T(0), cosX, sinX, T(0), + T(0),-sinX, cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template + tmat4x4 rotateY(T angleY) + { + T cosY = cos(DEG2RAD(angleY)); + T sinY = sin(DEG2RAD(angleY)); + + return tmat4x4( + cosY, T(0), sinY, T(0), + T(0), T(1), T(0), T(0), + -sinY, T(0), cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + tmat4x4 rotateZ(T angleZ) + { + T cosZ = (T)cos(DEG2RAD(angleZ)); + T sinZ = (T)sin(DEG2RAD(angleZ)); + + return tmat4x4( + cosZ, sinZ, T(0), T(0), + -sinZ, cosZ, T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1)); + } + + template + tmat4x4 rotateXY(T angleX, T angleY) + { + T cosX = cos(DEG2RAD(angleX)); + T sinX = sin(DEG2RAD(angleX)); + T cosY = cos(DEG2RAD(angleY)); + T sinY = sin(DEG2RAD(angleY)); + + return tmat4x4( + cosY, -sinX * sinY, cosX * sinY, T(0), + T(0), cosX, sinX, T(0), + -sinY, -sinX * cosY, cosX * cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + tmat4x4 rotateYX(T angleY, T angleX) + { + + T cosX = cos(DEG2RAD(angleX)); + T sinX = sin(DEG2RAD(angleX)); + T cosY = cos(DEG2RAD(angleY)); + T sinY = sin(DEG2RAD(angleY)); + + return tmat4x4( + cosY, T(0), sinY, T(0), + -sinX * sinY, cosX, sinX * cosY, T(0), + -cosX * sinY, -sinX, cosX * cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + tmat4x4 rotateXZ(T angleX, T angleZ) + { + return rotateX(angleX) * rotateZ(angleZ); + } + + template + tmat4x4 rotateZX(T angleX, T angleZ) + { + return rotateZ(angleZ) * rotateX(angleX); + } + + template + tmat4x4 rotateYXZ(T yaw, T pitch, T roll) + { + T tmp_ch = cos(DEG2RAD(yaw)); + T tmp_sh = sin(DEG2RAD(yaw)); + T tmp_cp = cos(DEG2RAD(pitch)); + T tmp_sp = sin(DEG2RAD(pitch)); + T tmp_cb = cos(DEG2RAD(roll)); + T tmp_sb = sin(DEG2RAD(roll)); + + tmat4x4 res; + res[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + res[0][1] = tmp_sb * tmp_cp; + res[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + res[0][3] = T(0); + res[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + res[1][1] = tmp_cb * tmp_cp; + res[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + res[1][3] = T(0); + res[2][0] = tmp_sh * tmp_cp; + res[2][1] = -tmp_sp; + res[2][2] = tmp_ch * tmp_cp; + res[2][3] = T(0); + res[3][0] = T(0); + res[3][1] = T(0); + res[3][2] = T(0); + res[3][3] = T(1); + return res; + } + + template + tmat4x4 yawPitchRoll(T yaw, T pitch, T roll) + { + T tmp_ch = cos(DEG2RAD(yaw)); + T tmp_sh = sin(DEG2RAD(yaw)); + T tmp_cp = cos(DEG2RAD(pitch)); + T tmp_sp = sin(DEG2RAD(pitch)); + T tmp_cb = cos(DEG2RAD(roll)); + T tmp_sb = sin(DEG2RAD(roll)); + + + tmat4x4 res; + res[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + res[0][1] = tmp_sb * tmp_cp; + res[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + res[0][3] = T(0); + res[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + res[1][1] = tmp_cb * tmp_cp; + res[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + res[1][3] = T(0); + res[2][0] = tmp_sh * tmp_cp; + res[2][1] = -tmp_sp; + res[2][2] = tmp_ch * tmp_cp; + res[2][3] = T(0); + res[3][0] = T(0); + res[3][1] = T(0); + res[3][2] = T(0); + res[3][3] = T(1); + return res; + } + + template + void axisAngle + ( + tmat4x4 const & mat, + tvec3 & axis, + T & angle + ) + { + T epsilon = (T)0.01; + T epsilon2 = (T)0.1; + + if ((fabs(mat[1][0] - mat[0][1]) < epsilon) && + (fabs(mat[2][0] - mat[0][2]) < epsilon) && + (fabs(mat[2][1] - mat[1][2]) < epsilon)) + { + if ((fabs(mat[1][0] + mat[0][1]) < epsilon2) && + (fabs(mat[2][0] + mat[0][2]) < epsilon2) && + (fabs(mat[2][1] + mat[1][2]) < epsilon2) && + (fabs(mat[0][0] + mat[1][1] + mat[2][2] - (T)3.0) < epsilon2)) + { + angle = (T)0.0; + axis.x = (T)1.0; + axis.y = (T)0.0; + axis.z = (T)0.0; + return; + } + angle = T(3.1415926535897932384626433832795); + T xx = (mat[0][0] + (T)1.0) / (T)2.0; + T yy = (mat[1][1] + (T)1.0) / (T)2.0; + T zz = (mat[2][2] + (T)1.0) / (T)2.0; + T xy = (mat[1][0] + mat[0][1]) / (T)4.0; + T xz = (mat[2][0] + mat[0][2]) / (T)4.0; + T yz = (mat[2][1] + mat[1][2]) / (T)4.0; + if ((xx > yy) && (xx > zz)) + { + if (xx < epsilon) + { + axis.x = (T)0.0; + axis.y = (T)0.7071; + axis.z = (T)0.7071; + } + else + { + axis.x = sqrt(xx); + axis.y = xy / axis.x; + axis.z = xz / axis.x; + } + } + else if (yy > zz) + { + if (yy < epsilon) + { + axis.x = (T)0.7071; + axis.y = (T)0.0; + axis.z = (T)0.7071; + } + else + { + axis.y = sqrt(yy); + axis.x = xy / axis.y; + axis.z = yz / axis.y; + } + } + else + { + if (zz < epsilon) + { + axis.x = (T)0.7071; + axis.y = (T)0.7071; + axis.z = (T)0.0; + } + else + { + axis.z = sqrt(zz); + axis.x = xz / axis.z; + axis.y = yz / axis.z; + } + } + return; + } + T s = sqrt((mat[2][1] - mat[1][2]) * (mat[2][1] - mat[1][2]) + (mat[2][0] - mat[0][2]) * (mat[2][0] - mat[0][2]) + (mat[1][0] - mat[0][1]) * (mat[1][0] - mat[0][1])); + if (abs(s) < T(0.001)) + s = (T)1.0; + angle = acos((mat[0][0] + mat[1][1] + mat[2][2] - (T)1.0) / (T)2.0); + axis.x = (mat[1][2] - mat[2][1]) / s; + axis.y = (mat[2][0] - mat[0][2]) / s; + axis.z = (mat[0][1] - mat[1][0]) / s; + } + + template + tmat4x4 axisAngleMatrix(tvec3 const & axis,T const angle) + { + T c = cos(angle); + T s = sin(angle); + T t = T(1) - c; + tvec3 n = normalize(axis); + + return tmat4x4( + t * n.x * n.x + c, t * n.x * n.y + n.z * s, t * n.x * n.z - n.y * s, T(0), + t * n.x * n.y - n.z * s, t * n.y * n.y + c, t * n.y * n.z + n.x * s, T(0), + t * n.x * n.z + n.y * s, t * n.y * n.z - n.x * s, t * n.z * n.z + c, T(0), + T(0), T(0), T(0), T(1) + ); + } + + template + tmat4x4 interpolate + ( + tmat4x4 const & m1, + tmat4x4 const & m2, + T const delta + ) + { + tmat4x4 m1rot = m1.extractMatrixRotation(); + tmat4x4 dltRotation = m2 * m1rot.transpose(); + tvec3 dltAxis; + T dltAngle; + axisAngle(dltRotation, dltAxis, dltAngle); + tmat4x4 out = axisAngleMatrix(dltAxis, dltAngle * delta) * m1rot; + out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]); + out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]); + out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]); + return out; + } + + template + tvec3 operator * (tvec3 const& v, tmat4x4 const& mat) + { + return tvec3 + ( + v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + 1*mat[3][0], + v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + 1*mat[3][1], + v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + 1*mat[3][2] + ); + } + + template + tmat4x4 operator+ (tmat4x4 const & m, typename tmat4x4::value_type s) + { + return tmat4x4( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template + tmat4x4 operator+ (typename tmat4x4::value_type s, tmat4x4 const & m) + { + return tmat4x4( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template + tmat4x4 operator+ (tmat4x4 const & m1, tmat4x4 const & m2) + { + return tmat4x4( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + tmat4x4 operator- (tmat4x4 const & m, typename tmat4x4::value_type s) + { + return tmat4x4( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template + tmat4x4 operator- (typename tmat4x4::value_type s, tmat4x4 const & m) + { + return tmat4x4( + s - m[0], + s - m[1], + s - m[2], + s - m[3]); + } + + template + tmat4x4 operator- (tmat4x4 const & m1, tmat4x4 const & m2) + { + return tmat4x4( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + tmat4x4 operator* (tmat4x4 const & m, typename tmat4x4::value_type s) + { + return tmat4x4( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + tmat4x4 operator* (typename tmat4x4::value_type s, tmat4x4 const & m) + { + return tmat4x4( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + typename tmat4x4::col_type operator* (tmat4x4 const & m, typename tmat4x4::row_type const & v) + { + return typename tmat4x4::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] * v.w, + m[0][3] * v.x + m[1][3] * v.y + m[2][3] * v.z + m[3][3] * v.w); + } + + template + typename tmat4x4::row_type operator* (typename tmat4x4::col_type const & v, tmat4x4 const & m) + { + return typename tmat4x4::row_type( + m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, + m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w, + m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w, + m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w); + } + + + + + template + tmat4x4 operator* (tmat4x4 const & m1, tmat4x4 const & m2) + { + typename tmat4x4::col_type const srcA0 = m1[0]; + typename tmat4x4::col_type const srcA1 = m1[1]; + typename tmat4x4::col_type const srcA2 = m1[2]; + typename tmat4x4::col_type const srcA3 = m1[3]; + + typename tmat4x4::col_type const srcB0 = m2[0]; + typename tmat4x4::col_type const srcB1 = m2[1]; + typename tmat4x4::col_type const srcB2 = m2[2]; + typename tmat4x4::col_type const srcB3 = m2[3]; + + tmat4x4 res; + res[0] = srcA0 * srcB0[0] + srcA1 * srcB0[1] + srcA2 * srcB0[2] + srcA3 * srcB0[3]; + res[1] = srcA0 * srcB1[0] + srcA1 * srcB1[1] + srcA2 * srcB1[2] + srcA3 * srcB1[3]; + res[2] = srcA0 * srcB2[0] + srcA1 * srcB2[1] + srcA2 * srcB2[2] + srcA3 * srcB2[3]; + res[3] = srcA0 * srcB3[0] + srcA1 * srcB3[1] + srcA2 * srcB3[2] + srcA3 * srcB3[3]; + return res; + } + + template + tmat4x4 operator/ (tmat4x4 const & m, typename tmat4x4::value_type s) + { + return tmat4x4( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template + tmat4x4 operator/ (typename tmat4x4::value_type s, tmat4x4 const & m) + { + return tmat4x4( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + template + typename tmat4x4::col_type operator/ (tmat4x4 const & m, typename tmat4x4::row_type const & v) + { + return m.inverse() * v; + } + + template + typename tmat4x4::row_type operator/ (typename tmat4x4::col_type const & v, tmat4x4 const & m) + { + return v * m.inverse(); + } + + template + tmat4x4 operator/ (tmat4x4 const & m1, tmat4x4 const & m2) + { + return m1 * m2.inverse(); + } + + template + tmat4x4 const operator- (tmat4x4 const & m) + { + return tmat4x4( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + template + tmat4x4 const operator++ (tmat4x4 const & m, int) + { + return tmat4x4( + m[0] + T(1), + m[1] + T(1), + m[2] + T(1), + m[3] + T(1)); + } + + template + tmat4x4 const operator-- (tmat4x4 const & m, int) + { + return tmat4x4( + m[0] - T(1), + m[1] - T(1), + m[2] - T(1), + m[3] - T(1)); + } + + template + bool operator==(tmat4x4 const & m1, tmat4x4 const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + bool operator!=(tmat4x4 const & m1, tmat4x4 const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } + + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + //! 射线类 + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + + + + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + template + typename tvec2::value_type length(tvec2 const & v) + { + typename tvec2::value_type sqr = v.x * v.x + v.y * v.y; + return sqrt(sqr); + } + + template + typename tvec3::value_type length(tvec3 const & v) + { + typename tvec3::value_type sqr = v.x * v.x + v.y * v.y + v.z * v.z; + return sqrt(sqr); + } + + template + typename tvec4::value_type length(tvec4 const & v) + { + typename tvec4::value_type sqr = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; + return sqrt(sqr); + } + template + typename tvec2::value_type distance(tvec2 const & p0,tvec2 const & p1) + { + return length(p1 - p0); + } + + template + typename tvec3::value_type distance(tvec3 const & p0,tvec3 const & p1) + { + return length(p1 - p0); + } + + template + typename tvec4::value_type distance(tvec4 const & p0,tvec4 const & p1) + { + return length(p1 - p0); + } + + template + typename tvec2::value_type dot(tvec2 const & x, tvec2 const & y) + { + return x.x * y.x + x.y * y.y; + } + + template + typename tvec3::value_type dot(tvec3 const & x, tvec3 const & y) + { + return x.x * y.x + x.y * y.y + x.z * y.z; + } + template + typename tvec4::value_type dot(tvec4 const & x, tvec4 const & y) + { + return x.x * y.x + x.y * y.y + x.z * y.z + x.w * y.w; + } + + template + tvec3 cross(tvec3 const & x, tvec3 const & y) + { + return tvec3 + ( + x.y * y.z - y.y * x.z, + x.z * y.x - y.z * x.x, + x.x * y.y - y.x * x.y + ); + } + + template + T inversesqrt(T x) + { + return T(1) / sqrt(x); + } + + template + tvec2 normalize(tvec2 const & x) + { + typename tvec2::value_type sqr = x.x * x.x + x.y * x.y; + return x * inversesqrt(sqr); + } + + template + tvec3 normalize(tvec3 const & x) + { + typename tvec3::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z; + return x * inversesqrt(sqr); + } + + template + tvec4 normalize(tvec4 const & x) + { + typename tvec4::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w; + return x * inversesqrt(sqr); + } + + + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + + template + struct tquat + { + typedef T value_type; + typedef std::size_t size_type; + + public: + value_type x; + value_type y; + value_type z; + value_type w; + + size_type length() const + { + return 4; + } + + tquat(): + x(0), + y(0), + z(0), + w(1) + {} + explicit tquat(value_type s, tvec3 const & v): + x(v.x), + y(v.y), + z(v.z), + w(s) + { + } + explicit tquat(tvec3 const & v,value_type s): + x(v.x), + y(v.y), + z(v.z), + w(s) + { + } + explicit tquat(value_type w, value_type x, value_type y, value_type z): + x(x), + y(y), + z(z), + w(w) + {} + + explicit tquat(tvec3 const & eulerAngle) + { + tvec3 c = cos(eulerAngle * value_type(0.5)); + tvec3 s = sin(eulerAngle * value_type(0.5)); + + this->w = c.x * c.y * c.z + s.x * s.y * s.z; + this->x = s.x * c.y * c.z - c.x * s.y * s.z; + this->y = c.x * s.y * c.z + s.x * c.y * s.z; + this->z = c.x * c.y * s.z - s.x * s.y * c.z; + } + + explicit tquat(tmat3x3 const & m) + { + *this = quat_cast(m); + } + + explicit tquat(tmat4x4 const & m) + { + *this = quat_cast(m); + } + + value_type & operator[](int i) + { + return (&x)[i]; + } + + value_type const & operator[](int i) const + { + return (&x)[i]; + } + + tquat & operator*=(value_type s) + { + this->w *= s; + this->x *= s; + this->y *= s; + this->z *= s; + return *this; + } + + tquat & operator = (const tquat& right) + { + this->w = right.w; + this->x = right.x; + this->y = right.y; + this->z = right.z; + return *this; + } + + tquat & operator/=(value_type s) + { + this->w /= s; + this->x /= s; + this->y /= s; + this->z /= s; + return *this; + } + }; + + + template< typename T> + tmat4x4 makeTransform( tvec3 const & position, tvec3 const& scale, const tquat& orientation) + { + tmat3x3 rot3x3 = mat3_cast(orientation); + + return tmat4x4 + ( + scale.x * rot3x3[0][0], scale.x * rot3x3[0][1], scale.x * rot3x3[0][2], 0, + scale.y * rot3x3[1][0], scale.y * rot3x3[1][1], scale.y * rot3x3[1][2], 0, + scale.z * rot3x3[2][0], scale.z * rot3x3[2][1], scale.z * rot3x3[2][2], 0, + position.x, position.y, position.z, 1 + ); + } + + template + T dot(tquat const & q1, tquat const & q2) + { + return q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; + } + + template + tquat cross(tquat const & q1, tquat const & q2) + { + return tquat( + q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, + q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, + q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); + } + + template + T length(tquat const & q) + { + return sqrt(dot(q, q)); + } + + template + genType mix(genType x, genType y, genType a) + { + return x + a * (y - x); + } + + template + T epsilon() + { + return std::numeric_limits::epsilon(); + } + + + + template + tquat conjugate(tquat const & q) + { + return tquat(q.w, -q.x, -q.y, -q.z); + } + + template + tquat inverse(tquat const & q) + { + return conjugate(q) / dot(q, q); + } + + template + bool operator==(tquat const & q1, tquat const & q2) + { + return (q1.x == q2.x) && (q1.y == q2.y) && (q1.z == q2.z) && (q1.w == q2.w); + } + + template + bool operator!=(tquat const & q1, tquat const & q2) + { + return (q1.x != q2.x) || (q1.y != q2.y) || (q1.z != q2.z) || (q1.w != q2.w); + } + + template + tquat operator- (tquat const & q) + { + return tquat(-q.w, -q.x, -q.y, -q.z); + } + + template + tquat operator+ ( tquat const & q, tquat const & p) + { + return tquat( + q.w + p.w, + q.x + p.x, + q.y + p.y, + q.z + p.z + ); + } + + template + tquat operator* ( tquat const & q, tquat const & p) + { + return tquat( + q.w * p.w - q.x * p.x - q.y * p.y - q.z * p.z, + q.w * p.x + q.x * p.w + q.y * p.z - q.z * p.y, + q.w * p.y + q.y * p.w + q.z * p.x - q.x * p.z, + q.w * p.z + q.z * p.w + q.x * p.y - q.y * p.x + ); + } + + template + tvec3 operator* (tquat const & q, tvec3 const & v) + { + typename tquat::value_type two(2); + + tvec3 uv; + tvec3 uuv; + tvec3 quatVector(q.x, q.y, q.z); + uv = cross(quatVector, v); + uuv = cross(quatVector, uv); + uv *= two * q.w; + uuv *= two; + return v + uv + uuv; + } + + template + tvec3 operator* (tvec3 const & v,tquat const & q) + { + return inverse(q) * v; + } + + + template + tquat operator* (tquat const & q, typename tquat::value_type s) + { + return tquat(q.w * s, q.x * s, q.y * s, q.z * s); + } + + template + tquat operator* (typename tquat::value_type s,tquat const & q) + { + return q * s; + } + + template + tquat operator/ (tquat const & q, typename tquat::value_type s) + { + return tquat(q.w / s, q.x / s, q.y / s, q.z / s); + } + + + + template + tquat mix(tquat const & x, tquat const & y, T const & a) + { + T cosTheta = dot(x, y); + if(cosTheta > T(1) - epsilon()) + { + return tquat( + mix(x.w, y.w, a), + mix(x.x, y.x, a), + mix(x.y, y.y, a), + mix(x.z, y.z, a) + ); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((T(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } + } + + template + tquat lerp(tquat const & x, tquat const & y, T a) + { + assert(a >= T(0)); + assert(a <= T(1)); + return x * (T(1) - a) + (y * a); + } + + template + tquat slerp(tquat const & x, tquat const & y, T a) + { + tquat z = y; + + T cosTheta = dot(x, y); + + if (cosTheta < T(0)) + { + z = -y; + cosTheta = -cosTheta; + } + if(cosTheta > T(1) - epsilon()) + { + return tquat + ( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a) + ); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); + } + } + + template + tquat rotate + ( + typename tquat::value_type angle, + tvec3 const & axis + ) + { + tvec3 Tmp = axis; + + typename tquat::value_type len = length(Tmp); + if(abs(len - T(1)) > T(0.001f)) + { + T oneOverLen = T(1) / len; + Tmp.x *= oneOverLen; + Tmp.y *= oneOverLen; + Tmp.z *= oneOverLen; + } + typename tquat::value_type const AngleRad = (T)DEG2RAD(angle); + typename tquat::value_type const Sin = (T)sin(AngleRad * T(0.5)); + return tquat((T)cos(AngleRad * T(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + } + template + valType roll(tquat const & q) + { + return atan2(valType(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z) * valType(RAD2DEG); + } + + template + valType pitch(tquat const & q) + { + return ::atan2(valType(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)* valType(RAD2DEG); + } + template + valType yaw(tquat const & q) + { + return ::asin(valType(-2) * (q.x * q.z - q.w * q.y)) * valType(RAD2DEG); + } + + template + tvec3 eulerAngles(tquat const & x) + { + return tvec3(pitch(x), yaw(x), roll(x)); + } + + + template + tmat3x3 mat3_cast(const tquat& q) + { + + return tmat3x3 + ( + 1 - 2 * q.y * q.y - 2 * q.z * q.z, 2 * q.x * q.y + 2 * q.w * q.z, 2 * q.x * q.z - 2 * q.w * q.y, + 2 * q.x * q.y - 2 * q.w * q.z, 1 - 2 * q.x * q.x - 2 * q.z * q.z, 2 * q.y * q.z + 2 * q.w * q.x, + 2 * q.x * q.z + 2 * q.w * q.y, 2 * q.y * q.z - 2 * q.w * q.x, 1 - 2 * q.x * q.x - 2 * q.y * q.y + ); + } + + template + tmat4x4 mat4_cast(tquat const & q) + { + return tmat4x4(mat3_cast(q)); + } + template + tquat quat_cast(tmat3x3 const & m) + { + typename tquat::value_type fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2]; + typename tquat::value_type fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2]; + typename tquat::value_type fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1]; + typename tquat::value_type fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2]; + + int biggestIndex = 0; + typename tquat::value_type fourBiggestSquaredMinus1 = fourWSquaredMinus1; + if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourXSquaredMinus1; + biggestIndex = 1; + } + if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourYSquaredMinus1; + biggestIndex = 2; + } + if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourZSquaredMinus1; + biggestIndex = 3; + } + + typename tquat::value_type biggestVal = sqrt(fourBiggestSquaredMinus1 + T(1)) * T(0.5); + typename tquat::value_type mult = T(0.25) / biggestVal; + + tquat res; + switch(biggestIndex) + { + case 0: + res.w = biggestVal; + res.x = (m[1][2] - m[2][1]) * mult; + res.y = (m[2][0] - m[0][2]) * mult; + res.z = (m[0][1] - m[1][0]) * mult; + break; + case 1: + res.w = (m[1][2] - m[2][1]) * mult; + res.x = biggestVal; + res.y = (m[0][1] + m[1][0]) * mult; + res.z = (m[2][0] + m[0][2]) * mult; + break; + case 2: + res.w = (m[2][0] - m[0][2]) * mult; + res.x = (m[0][1] + m[1][0]) * mult; + res.y = biggestVal; + res.z = (m[1][2] + m[2][1]) * mult; + break; + case 3: + res.w = (m[0][1] - m[1][0]) * mult; + res.x = (m[2][0] + m[0][2]) * mult; + res.y = (m[1][2] + m[2][1]) * mult; + res.z = biggestVal; + break; + + default: + assert(false); + break; + } + return res; + } + template + tquat quat_cast(tmat4x4 const & m4) + { + return quat_cast(tmat3x3(m4[0][0],m4[0][1],m4[0][2], + m4[1][0],m4[1][1],m4[1][2], + m4[2][0],m4[2][1],m4[2][2])); + } + + template + T angle(tquat const & x) + { + return acos(x.w) * T(2) * T(RAD2DEG); + } + + template + tvec3 axis(tquat const & x) + { + T tmp1 = T(1) - x.w * x.w; + if(tmp1 <= T(0)) + { + return tvec3(0, 0, 1); + } + T tmp2 = T(1) / sqrt(tmp1); + + return tvec3(x.x * tmp2, x.y * tmp2, x.z * tmp2); + } + + + + template + tquat angleAxis(valType angle, tvec3 const & axis) + { + tquat result; + + valType a = (valType)(valType(DEG2RAD(angle))); + valType s = sin(a * valType(0.5)); + + result.w = cos(a * valType(0.5)); + result.x = axis.x * s; + result.y = axis.y * s; + result.z = axis.z * s; + return result; + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////// + + template + tmat4x4 translate(tmat4x4 const & m,tvec3 const & v) + { + tmat4x4 res(m); + res[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; + return res; + } + + template + tmat4x4 rotate + ( + tmat4x4 const & m, + T const & angle, + tvec3 const & v + ) + { + + T a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + + tvec3 axis = normalize(v); + + tvec3 temp = (T(1) - c) * axis; + + tmat4x4 res; + res[0][0] = c + temp[0] * axis[0]; + res[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + res[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + + res[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + res[1][1] = c + temp[1] * axis[1]; + res[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + + res[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + res[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + res[2][2] = c + temp[2] * axis[2]; + + tmat4x4 rot; + + rot[0] = m[0] * res[0][0] + m[1] * res[0][1] + m[2] * res[0][2]; + rot[1] = m[0] * res[1][0] + m[1] * res[1][1] + m[2] * res[1][2]; + rot[2] = m[0] * res[2][0] + m[1] * res[2][1] + m[2] * res[2][2]; + rot[3] = m[3]; + return rot; + } + + template + tmat4x4 scale(tmat4x4 const & m,tvec3 const & v) + { + tmat4x4 res; + res[0] = m[0] * v[0]; + res[1] = m[1] * v[1]; + res[2] = m[2] * v[2]; + res[3] = m[3]; + return res; + } + + template + tmat4x4 rotate_slow + ( + tmat4x4 const & m, + T const & angle, + tvec3 const & v + ) + { + + T const a = DEG2RAD(angle); + T c = cos(a); + T s = sin(a); + tmat4x4 res; + + tvec3 axis = normalize(v); + + res[0][0] = c + (1 - c) * axis.x * axis.x; + res[0][1] = (1 - c) * axis.x * axis.y + s * axis.z; + res[0][2] = (1 - c) * axis.x * axis.z - s * axis.y; + res[0][3] = 0; + + res[1][0] = (1 - c) * axis.y * axis.x - s * axis.z; + res[1][1] = c + (1 - c) * axis.y * axis.y; + res[1][2] = (1 - c) * axis.y * axis.z + s * axis.x; + res[1][3] = 0; + + res[2][0] = (1 - c) * axis.z * axis.x + s * axis.y; + res[2][1] = (1 - c) * axis.z * axis.y - s * axis.x; + res[2][2] = c + (1 - c) * axis.z * axis.z; + res[2][3] = 0; + + res[3] = tvec4(0, 0, 0, 1); + return m * res; + } + + template + tmat4x4 scale_slow(tmat4x4 const & m,tvec3 const & v) + { + tmat4x4 res(T(1)); + res[0][0] = v.x; + res[1][1] = v.y; + res[2][2] = v.z; + + return m * res; + } + + template + tmat4x4 ortho + ( + valType left, + valType right, + valType bottom, + valType top, + valType zNear, + valType zFar + ) + { + tmat4x4 res(1); + res[0][0] = valType(2) / (right - left); + res[1][1] = valType(2) / (top - bottom); + res[2][2] = - valType(2) / (zFar - zNear); + res[3][0] = - (right + left) / (right - left); + res[3][1] = - (top + bottom) / (top - bottom); + res[3][2] = - (zFar + zNear) / (zFar - zNear); + return res; + } + + template + tmat4x4 frustum + ( + valType left, + valType right, + valType bottom, + valType top, + valType nearVal, + valType farVal + ) + { + tmat4x4 res(0); + res[0][0] = (valType(2) * nearVal) / (right - left); + res[1][1] = (valType(2) * nearVal) / (top - bottom); + res[2][0] = (right + left) / (right - left); + res[2][1] = (top + bottom) / (top - bottom); + res[2][2] = -(farVal + nearVal) / (farVal - nearVal); + res[2][3] = valType(-1); + res[3][2] = -(valType(2) * farVal * nearVal) / (farVal - nearVal); + return res; + } + + template + tmat4x4 perspective(valType fovy, valType aspect, valType zNear, valType zFar) + { + valType range = tan(fovy * valType(DEG2RAD(0.5))) * zNear; + valType left = -range * aspect; + valType right = range * aspect; + valType bottom = -range; + valType top = range; + + tmat4x4 res(valType(0)); + res[0][0] = (valType(2) * zNear) / (right - left); + res[1][1] = (valType(2) * zNear) / (top - bottom); + res[2][2] = - (zFar + zNear) / (zFar - zNear); + res[2][3] = - valType(1); + res[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear); + return res; + } + + template + tvec3 project + ( + tvec3 const & obj, + tmat4x4 const & model, + tmat4x4 const & proj, + tvec4 const & viewport + ) + { + tvec4 tmp = tvec4(obj.x, obj.y,obj.z,T(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp = tmp * T(0.5) + T(0.5); + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return tvec3(tmp.x,tmp.y,tmp.z); + } + + template + tvec3 unProject + ( + tvec3 const & win, + tmat4x4 const & model, + tmat4x4 const & proj, + tvec4 const & viewport + ) + { + tmat4x4 inverses = (proj * model).inverse(); + + tvec4 tmp = tvec4(win.x,win.y,win.z, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp = tmp * T(2) - T(1); + + tvec4 obj = inverses * tmp; + obj /= obj.w; + + return tvec3(obj.x,obj.y,obj.z); + } + + template + tmat4x4 pickMatrix + ( + tvec2 const & center, + tvec2 const & delta, + tvec4 const & viewport + ) + { + assert(delta.x > T(0) && delta.y > T(0)); + tmat4x4 res(1.0f); + + if(!(delta.x > T(0) && delta.y > T(0))) + { + return res; + } + + tvec3 Temp + ( + (T(viewport[2]) - T(2) * (center.x - T(viewport[0]))) / delta.x, + (T(viewport[3]) - T(2) * (center.y - T(viewport[1]))) / delta.y, + T(0) + ); + res = translate(res, Temp); + return scale(res, tvec3(T(viewport[2]) / delta.x, T(viewport[3]) / delta.y, T(1))); + } + + template + tmat4x4 lookAt + ( + tvec3 const & eye, + tvec3 const & center, + tvec3 const & up + ) + { + tvec3 f = normalize(center - eye); + tvec3 u = normalize(up); + tvec3 s = normalize(cross(f, u)); + u = cross(s, f); + + tmat4x4 res(1); + res[0][0] = s.x; + res[1][0] = s.y; + res[2][0] = s.z; + res[0][1] = u.x; + res[1][1] = u.y; + res[2][1] = u.z; + res[0][2] = -f.x; + res[1][2] = -f.y; + res[2][2] = -f.z; + res[3][0] = -dot(s, eye); + res[3][1] = -dot(u, eye); + res[3][2] = dot(f, eye); + return res; + } + + template + class AxisAlignedBox2D + { + public: + enum Extent + { + EXTENT_NULL, + EXTENT_FINITE, + EXTENT_INFINITE + }; + public: + tvec2 _minimum; + tvec2 _maximum; + Extent _extent; + public: + /* + 1-----2 + /| /| + / | / | + 5-----4 | + | 0--|--3 + | / | / + |/ |/ + 6-----7 + */ + typedef enum + { + FAR_LEFT_BOTTOM = 0, + FAR_LEFT_TOP = 1, + FAR_RIGHT_TOP = 2, + FAR_RIGHT_BOTTOM = 3, + NEAR_RIGHT_BOTTOM = 7, + NEAR_LEFT_BOTTOM = 6, + NEAR_LEFT_TOP = 5, + NEAR_RIGHT_TOP = 4 + } CornerEnum; + + AxisAlignedBox2D() + { + _minimum = tvec2( T(-0.5), T(-0.5)); + _maximum = tvec2( T(0.5), T(0.5)); + _extent = EXTENT_NULL; + } + AxisAlignedBox2D(const AxisAlignedBox2D & rkBox) + { + setExtents( rkBox._minimum, rkBox._maximum ); + _extent = rkBox._extent; + } + + AxisAlignedBox2D( const tvec2& min, const tvec2& max ) + { + setExtents( min, max ); + } + + AxisAlignedBox2D( + T mx, T my, + T Mx, T My + ) + { + setExtents( tvec2(mx, my), tvec2(Mx, My)); + } + + AxisAlignedBox2D& operator=(const AxisAlignedBox2D& right) + { + setExtents(right._minimum, right._maximum); + return *this; + } + + ~AxisAlignedBox2D() + { + } + /** + * Gets the minimum corner of the box. + */ + const tvec2& getMinimum(void) const + { + return _minimum; + } + + /** + * Gets a modifiable version of the minimum + * corner of the box. + */ + tvec2& getMinimum(void) + { + return _minimum; + } + + void setMinimum( const tvec2& vec ) + { + _minimum = vec; + } + void setMinimum( T x,T y ) + { + _minimum = tvec2(x,y); + } + /** + * Gets the maximum corner of the box. + */ + const tvec2& getMaximum(void) const + { + return _maximum; + } + /** + * Gets a modifiable version of the maximum + * corner of the box. + */ + tvec2& getMaximum(void) + { + return _maximum; + } + + + /** + * Sets the maximum corner of the box. + */ + void setMaximum( const tvec2& vec ) + { + _maximum = vec; + } + + void setMaximum( T x, T y ) + { + _maximum.x = x; + _maximum.y = y; + } + + /** + * Sets both minimum and maximum extents at once. + */ + void setExtents( const tvec2& min, const tvec2& max ) + { + _minimum = min; + _maximum = max; + _extent = EXTENT_FINITE; + } + + void setExtents( + T mx, T my, + T Mx, T My + ) + { + _minimum.x = mx; + _minimum.y = my; + + _maximum.x = Mx; + _maximum.y = My; + _extent = EXTENT_FINITE; + } + inline bool intersects(const AxisAlignedBox2D& b2) const + { + if (_maximum.x < b2._minimum.x) + return false; + if (_maximum.y < b2._minimum.y) + return false; + + if (_minimum.x > b2._maximum.x) + return false; + if (_minimum.y > b2._maximum.y) + return false; + return true; + } + + + inline AxisAlignedBox2D intersection(const AxisAlignedBox2D& b2) const + { + tvec2 intMin = _minimum; + tvec2 intMax = _maximum; + + intMin.makeCeil(b2.getMinimum()); + intMax.makeFloor(b2.getMaximum()); + + if (intMin.x < intMax.x && + intMin.y < intMax.y) + { + return AxisAlignedBox2D(intMin, intMax); + } + + return AxisAlignedBox2D(); + } + inline void setNull() + { + _extent = EXTENT_NULL; + } + + inline bool isNull(void) const + { + return (_extent == EXTENT_NULL); + } + + bool isFinite(void) const + { + return (_extent == EXTENT_FINITE); + } + + inline void setInfinite() + { + _extent = EXTENT_INFINITE; + } + inline bool isInfinite(void) const + { + return (_extent == EXTENT_INFINITE); + } + + + inline bool intersects(const tvec2& v) const + { + return( v.x >= _minimum.x && v.x <= _maximum.x && + v.y >= _minimum.y && v.y <= _maximum.y ); + } + + + inline tvec2 getCenter(void) const + { + return tvec2( + (_maximum.x + _minimum.x) * T(0.5f), + (_maximum.y + _minimum.y) * T(0.5f)); + } + /** + * Gets the size of the box + */ + inline tvec2 getSize(void) const + { + return _maximum - _minimum; + } + + inline tvec2 getHalfSize(void) const + { + return (_maximum - _minimum) * T(0.5); + } + + inline bool contains(const tvec2& v) const + { + return _minimum.x <= v.x && v.x <= _maximum.x && + _minimum.y <= v.y && v.y <= _maximum.y; + } + + inline bool contains(const AxisAlignedBox2D& other) const + { + return this->_minimum.x <= other._minimum.x && + this->_minimum.y <= other._minimum.y && + other._maximum.x <= this->_maximum.x && + other._maximum.y <= this->_maximum.y; + } + inline bool operator== (const AxisAlignedBox2D& right) const + { + return this->_minimum == right._minimum && + this->_maximum == right._maximum; + } + inline bool operator!= (const AxisAlignedBox2D& right) const + { + return !(*this == right); + } + + inline void merge(tvec2 point) + { + if (_minimum.x > point.x) + { + _minimum.x = point.x; + } + + if (_minimum.y > point.y) + { + _minimum.y = point.y; + } + if (_maximum.x < point.x) + { + _maximum.x = point.x; + } + if (_maximum.y < point.y) + { + _maximum.y = point.y; + } + } + + inline void merge(AxisAlignedBox2D other) + { + _maximum.makeCeil(other._maximum); + _minimum.makeFloor(other._minimum); + } + + }; + + + template + class AxisAlignedBox + { + public: + enum Extent + { + EXTENT_NULL, + EXTENT_FINITE, + EXTENT_INFINITE + }; + public: + tvec3 _minimum; + tvec3 _maximum; + Extent _extent; + public: + /* + 1-----2 + /| /| + / | / | + 5-----4 | + | 0--|--3 + | / | / + |/ |/ + 6-----7 + */ + typedef enum + { + FAR_LEFT_BOTTOM = 0, + FAR_LEFT_TOP = 1, + FAR_RIGHT_TOP = 2, + FAR_RIGHT_BOTTOM = 3, + NEAR_RIGHT_BOTTOM = 7, + NEAR_LEFT_BOTTOM = 6, + NEAR_LEFT_TOP = 5, + NEAR_RIGHT_TOP = 4 + } CornerEnum; + + AxisAlignedBox() + { + _minimum = tvec3( T(-0.5), T(-0.5), T(-0.5) ); + _maximum = tvec3( T(0.5), T(0.5), T(0.5) ); + _extent = EXTENT_NULL; + } + AxisAlignedBox(const AxisAlignedBox & rkBox) + { + setExtents( rkBox._minimum, rkBox._maximum ); + _extent = rkBox._extent; + } + + AxisAlignedBox( const tvec3& min, const tvec3& max ) + { + setExtents( min, max ); + } + + AxisAlignedBox( + T mx, T my, T mz, + T Mx, T My, T Mz + ) + { + setExtents( mx, my, mz, Mx, My, Mz ); + } + + AxisAlignedBox& operator=(const AxisAlignedBox& right) + { + setExtents(right._minimum, right._maximum); + return *this; + } + + ~AxisAlignedBox() + { + } + /** + * Gets the minimum corner of the box. + */ + const tvec3& getMinimum(void) const + { + return _minimum; + } + + /** + * Gets a modifiable version of the minimum + * corner of the box. + */ + tvec3& getMinimum(void) + { + return _minimum; + } + + void setMinimum(const tvec3& mins) + { + _minimum = mins; + } + void setMinimum(T x,T y, T z) + { + _minimum = tvec3(x,y,z); + } + /** + * Gets the maximum corner of the box. + */ + const tvec3& getMaximum(void) const + { + return _maximum; + } + /** + * Gets a modifiable version of the maximum + * corner of the box. + */ + tvec3& getMaximum(void) + { + return _maximum; + } + /** + * Sets the maximum corner of the box. + */ + void setMaximum( const tvec3& vec ) + { + _maximum = vec; + } + + void setMaximum( T x, T y, T z ) + { + _maximum.x = x; + _maximum.y = y; + _maximum.z = z; + } + + /** + * Changes one of the components of the maximum corner of the box + * used to resize only one dimension of the box + */ + void setMaximumX( T x ) + { + _maximum.x = x; + } + + void setMaximumY( T y ) + { + _maximum.y = y; + } + + void setMaximumZ( T z ) + { + _maximum.z = z; + } + + /** + * Sets both minimum and maximum extents at once. + */ + void setExtents( const tvec3& min, const tvec3& max ) + { + _minimum = min; + _maximum = max; + _extent = EXTENT_FINITE; + } + + void setExtents( + T mx, T my, T mz, + T Mx, T My, T Mz ) + { + _minimum.x = mx; + _minimum.y = my; + _minimum.z = mz; + + _maximum.x = Mx; + _maximum.y = My; + _maximum.z = Mz; + _extent = EXTENT_FINITE; + + } + + /** Returns a pointer to an array of 8 corner points, useful for + collision vs. non-aligned objects. + @remarks + If the order of these corners is important, they are as + follows: The 4 points of the minimum Z face (note that + because Ogre uses right-handed coordinates, the minimum Z is + at the 'back' of the box) starting with the minimum point of + all, then anticlockwise around this face (if you are looking + onto the face from outside the box). Then the 4 points of the + maximum Z face, starting with maximum point of all, then + anticlockwise around this face (looking onto the face from + outside the box). Like this: +
+        1-----2
+        /|    /|
+        / |   / |
+        5-----4  |
+        |  0--|--3
+        | /   | /
+        |/    |/
+        6-----7
+        
+ @remarks as this implementation uses a static member, make sure to use your own copy ! + */ + void getAllCorners(tvec3 mpCorners[8] ) const + { + mpCorners[0] = _minimum; + mpCorners[1].x = _minimum.x; mpCorners[1].y = _maximum.y; mpCorners[1].z = _minimum.z; + mpCorners[2].x = _maximum.x; mpCorners[2].y = _maximum.y; mpCorners[2].z = _minimum.z; + mpCorners[3].x = _maximum.x; mpCorners[3].y = _minimum.y; mpCorners[3].z = _minimum.z; + + mpCorners[4] = _maximum; + mpCorners[5].x = _minimum.x; mpCorners[5].y = _maximum.y; mpCorners[5].z = _maximum.z; + mpCorners[6].x = _minimum.x; mpCorners[6].y = _minimum.y; mpCorners[6].z = _maximum.z; + mpCorners[7].x = _maximum.x; mpCorners[7].y = _minimum.y; mpCorners[7].z = _maximum.z; + } + + /** + * gets the position of one of the corners + */ + tvec3 getCorner(CornerEnum cornerToGet) const + { + switch(cornerToGet) + { + case FAR_LEFT_BOTTOM: + return _minimum; + case FAR_LEFT_TOP: + return tvec3(_minimum.x, _maximum.y, _minimum.z); + case FAR_RIGHT_TOP: + return tvec3(_maximum.x, _maximum.y, _minimum.z); + case FAR_RIGHT_BOTTOM: + return tvec3(_maximum.x, _minimum.y, _minimum.z); + case NEAR_RIGHT_BOTTOM: + return tvec3(_maximum.x, _minimum.y, _maximum.z); + case NEAR_LEFT_BOTTOM: + return tvec3(_minimum.x, _minimum.y, _maximum.z); + case NEAR_LEFT_TOP: + return tvec3(_minimum.x, _maximum.y, _maximum.z); + case NEAR_RIGHT_TOP: + return _maximum; + default: + return tvec3(); + } + } + + /** + * Merges the passed in box into the current box. The result is the + * box which encompasses both. + */ + void merge( const AxisAlignedBox& right ) + { + + if ((right._extent == EXTENT_NULL) || (_extent == EXTENT_INFINITE)) + { + return; + } + else if (right._extent == EXTENT_INFINITE) + { + _extent = EXTENT_INFINITE; + } + else if (_extent == EXTENT_NULL) + { + setExtents(right._minimum, right._maximum); + } + else + { + //! merge + tvec3 min = _minimum; + tvec3 max = _maximum; + max.makeCeil(right._maximum); + min.makeFloor(right._minimum); + setExtents(min, max); + } + } + + /** + * Extends the box to encompass the specified point (if needed). + */ + void merge( const tvec3& point ) + { + switch (_extent) + { + case EXTENT_NULL: // if null, use this point + setExtents(point, point); + return; + + case EXTENT_FINITE: + _maximum.makeCeil(point); + _minimum.makeFloor(point); + return; + + case EXTENT_INFINITE: + return; + } + } + void transform( const tmat4x4& matrix ) + { + tvec3 oldMin; + tvec3 oldMax; + tvec3 currentCorner; + + oldMin = _minimum; + oldMax = _maximum; + + + // We sequentially compute the corners in the following order : + // 0, 6, 5, 1, 2, 4 ,7 , 3 + // This sequence allows us to only change one member at a time to get at all corners. + + // For each one, we transform it using the matrix + // Which gives the resulting point and merge the resulting point. + + currentCorner = oldMin; + tvec3 vVert = currentCorner * matrix; + setExtents(vVert,vVert); + + // First corner + // min min min + currentCorner = oldMin; + merge( currentCorner * matrix ); + + // min,min,max + currentCorner.z = oldMax.z; + merge( currentCorner * matrix ); + + // min max max + currentCorner.y = oldMax.y; + merge( currentCorner * matrix ); + + // min max min + currentCorner.z = oldMin.z; + merge( currentCorner * matrix ); + + // max max min + currentCorner.x = oldMax.x; + merge( currentCorner * matrix ); + + // max max max + currentCorner.z = oldMax.z; + merge( currentCorner * matrix ); + + // max min max + currentCorner.y = oldMin.y; + merge( currentCorner * matrix); + + // max min min + currentCorner.z = oldMin.z; + merge( currentCorner * matrix); + } + + /** + * Returns whether or not this box intersects another. + */ + bool intersects(const AxisAlignedBox& b2) const + { + if (_maximum.x < b2._minimum.x) + return false; + if (_maximum.y < b2._minimum.y) + return false; + if (_maximum.z < b2._minimum.z) + return false; + + if (_minimum.x > b2._maximum.x) + return false; + if (_minimum.y > b2._maximum.y) + return false; + if (_minimum.z > b2._maximum.z) + return false; + return true; + + } + + /** + * Returns whether or not this box intersects another. + */ + bool intersectsNoZ(const AxisAlignedBox& b2) const + { + if (_maximum.x < b2._minimum.x) + return false; + if (_maximum.y < b2._minimum.y) + return false; + + if (_minimum.x > b2._maximum.x) + return false; + if (_minimum.y > b2._maximum.y) + return false; + return true; + + } + + + AxisAlignedBox intersection(const AxisAlignedBox& b2) const + { + tvec3 intMin = _minimum; + tvec3 intMax = _maximum; + + intMin.makeCeil(b2.getMinimum()); + intMax.makeFloor(b2.getMaximum()); + + if (intMin.x < intMax.x && + intMin.y < intMax.y && + intMin.z < intMax.z) + { + return AxisAlignedBox(intMin, intMax); + } + + return AxisAlignedBox(); + } + void setNull() + { + _extent = EXTENT_NULL; + } + + bool isNull(void) const + { + return (_extent == EXTENT_NULL); + } + + bool isFinite(void) const + { + return (_extent == EXTENT_FINITE); + } + + void setInfinite() + { + _extent = EXTENT_INFINITE; + } + bool isInfinite(void) const + { + return (_extent == EXTENT_INFINITE); + } + + void scale(const tvec3& s) + { + tvec3 min = _minimum * s; + tvec3 max = _maximum * s; + setExtents(min, max); + } + + bool intersects(const tvec3& v) const + { + return( v.x >= _minimum.x && v.x <= _maximum.x && + v.y >= _minimum.y && v.y <= _maximum.y && + v.z >= _minimum.z && v.z <= _maximum.z); + } + + bool intersects(const tvec2& v) const + { + return( v.x >= _minimum.x && v.x <= _maximum.x && + v.y >= _minimum.y && v.y <= _maximum.y ); + } + + tvec3 getCenter(void) const + { + return tvec3( + (_maximum.x + _minimum.x) * T(0.5f), + (_maximum.y + _minimum.y) * T(0.5f), + (_maximum.z + _minimum.z) * T(0.5f) + ); + } + /** + * Gets the size of the box + */ + tvec3 getSize(void) const + { + return _maximum - _minimum; + } + + tvec3 getHalfSize(void) const + { + return (_maximum - _minimum) * T(0.5); + } + + bool contains(const tvec3& v) const + { + return _minimum.x <= v.x && v.x <= _maximum.x && + _minimum.y <= v.y && v.y <= _maximum.y && + _minimum.z <= v.z && v.z <= _maximum.z; + } + + bool contains(const AxisAlignedBox& other) const + { + return this->_minimum.x <= other._minimum.x && + this->_minimum.y <= other._minimum.y && + this->_minimum.z <= other._minimum.z && + other._maximum.x <= this->_maximum.x && + other._maximum.y <= this->_maximum.y && + other._maximum.z <= this->_maximum.z; + } + bool operator== (const AxisAlignedBox& right) const + { + return this->_minimum == right._minimum && + this->_maximum == right._maximum; + } + bool operator!= (const AxisAlignedBox& right) const + { + return !(*this == right); + } + }; + + template + class tspline + { + public: + tspline() + { + mCoeffs[0][0] = 2; + mCoeffs[0][1] = -2; + mCoeffs[0][2] = 1; + mCoeffs[0][3] = 1; + mCoeffs[1][0] = -3; + mCoeffs[1][1] = 3; + mCoeffs[1][2] = -2; + mCoeffs[1][3] = -1; + mCoeffs[2][0] = 0; + mCoeffs[2][1] = 0; + mCoeffs[2][2] = 1; + mCoeffs[2][3] = 0; + mCoeffs[3][0] = 1; + mCoeffs[3][1] = 0; + mCoeffs[3][2] = 0; + mCoeffs[3][3] = 0; + + mCoeffs = mCoeffs.transpose(); + mAutoCalc = true; + } + ~tspline(){}; + + void addPoint(const tvec3& p) + { + mPoints.push_back(p); + if (mAutoCalc) + { + recalcTangents(); + } + } + + const tvec3& getPoint(size_t index) const + { + assert (index < mPoints.size() && "Point index is out of bounds!!"); + + return mPoints[index]; + } + tvec3& getPoint(size_t index) + { + assert (index < mPoints.size() && "Point index is out of bounds!!"); + + return mPoints[index]; + } + + /** + * 获取点的数量 + */ + size_t getNumPoints(void) const + { + return mPoints.size(); + } + /** + * 清除所有的点数据 + */ + void clear(void) + { + mPoints.clear(); + mTangents.clear(); + } + /** + * 更新点数据 + */ + void updatePoint(size_t index, const tvec3& value) + { + assert (index < mPoints.size() && "Point index is out of bounds!!"); + + mPoints[index] = value; + if (mAutoCalc) + { + recalcTangents(); + } + } + /** + * 差值获取点数据 + */ + tvec3 interpolate(T time) const + { + T fSeg = time * (mPoints.size() - 1); + unsigned segIdx = (unsigned)fSeg; + // Apportion t + time = fSeg - segIdx; + + return interpolate(segIdx, time); + } + /** + * 根据索引差值 + */ + tvec3 interpolate(size_t fromIndex, T t) const + { + // Bounds check + assert (fromIndex < mPoints.size() && "fromIndex out of bounds"); + + if ((fromIndex + 1) == mPoints.size()) + { + // Duff request, cannot blend to nothing + // Just return source + return mPoints[fromIndex]; + } + // Fast special cases + if (t == 0.0f) + { + return mPoints[fromIndex]; + } + else if(t == 1.0f) + { + return mPoints[fromIndex + 1]; + } + + // float interpolation + // Form a vector of powers of t + T t2, t3; + t2 = t * t; + t3 = t2 * t; + tvec4 powers(t3, t2, t, 1); + + const tvec3& point1 = mPoints[fromIndex]; + const tvec3& point2 = mPoints[fromIndex+1]; + const tvec3& tan1 = mTangents[fromIndex]; + const tvec3& tan2 = mTangents[fromIndex+1]; + tmat4x4 pt; + + pt[0][0] = point1.x; + pt[0][1] = point1.y; + pt[0][2] = point1.z; + pt[0][3] = 1.0f; + pt[1][0] = point2.x; + pt[1][1] = point2.y; + pt[1][2] = point2.z; + pt[1][3] = 1.0f; + pt[2][0] = tan1.x; + pt[2][1] = tan1.y; + pt[2][2] = tan1.z; + pt[2][3] = 1.0f; + pt[3][0] = tan2.x; + pt[3][1] = tan2.y; + pt[3][2] = tan2.z; + pt[3][3] = 1.0f; + + pt = pt.transpose(); + + tvec4 ret = powers * mCoeffs * pt; + + return tvec3(ret.x, ret.y, ret.z); + } + /** + * 自动计算标记 + */ + void setAutoCalculate(bool autoCalc) + { + mAutoCalc = autoCalc; + } + /** + * 计算切线 + */ + void recalcTangents(void) + { + size_t i, numPoints; + bool isClosed; + + numPoints = mPoints.size(); + if (numPoints < 2) + { + return; + } + if (mPoints[0] == mPoints[numPoints-1]) + { + isClosed = true; + } + else + { + isClosed = false; + } + + mTangents.resize(numPoints); + + + for(i = 0; i < numPoints; ++i) + { + if (i ==0) + { + // Special case start + if (isClosed) + { + // Use numPoints-2 since numPoints-1 is the last point and == [0] + mTangents[i] = 0.5f * (mPoints[1] - mPoints[numPoints-2]); + } + else + { + mTangents[i] = 0.5f * (mPoints[1] - mPoints[0]); + } + } + else if (i == numPoints-1) + { + if (isClosed) + { + mTangents[i] = mTangents[0]; + } + else + { + mTangents[i] = 0.5f * (mPoints[i] - mPoints[i-1]); + } + } + else + { + mTangents[i] = 0.5f * (mPoints[i+1] - mPoints[i-1]); + } + } + } + + public: + bool mAutoCalc; + std::vector< tvec3 > mPoints; + std::vector< tvec3 > mTangents; + tmat4x4 mCoeffs; + }; + + + + + template < typename T > + class tellipsoidModel + { + public: + tellipsoidModel(T radiusEquator = T(WGS_84_RADIUS_EQUATOR),T radiusPolar = T(WGS_84_RADIUS_POLAR)) + { + _radiusEquator = radiusEquator; + _radiusPolar = radiusPolar; + T flattening = (_radiusEquator-_radiusPolar)/_radiusEquator; + _eccentricitySquared= T(2)*flattening - flattening*flattening; + } + + ~tellipsoidModel(void) + { + } + + + void convertLatLongHeightToXYZ( + T latitude, + T longitude, + T height, + T& X, + T& Y, + T& Z + ) const + { + // for details on maths see http://www.colorado.edu/geography/gcraft/notes/datum/gif/llhxyz.gif + T sin_latitude = sin(latitude); + T cos_latitude = cos(latitude); + T N = _radiusEquator / sqrt( 1.0 - _eccentricitySquared*sin_latitude*sin_latitude); + X = (N+height) * cos_latitude*cos(longitude); + Y = (N+height) * cos_latitude*sin(longitude); + Z = (N*(1-_eccentricitySquared)+height)*sin_latitude; + } + + + void convertXYZToLatLongHeight( + T X, + T Y, + T Z, + T& latitude, + T& longitude, + T& height + ) const + { + // http://www.colorado.edu/geography/gcraft/notes/datum/gif/xyzllh.gif + T p = (T)sqrt(X*X + Y*Y); + T theta = (T)atan2(Z*_radiusEquator , (p*_radiusPolar)); + T eDashSquared = (_radiusEquator*_radiusEquator - _radiusPolar*_radiusPolar) / (_radiusPolar*_radiusPolar); + + T sin_theta = (T)sin(theta); + T cos_theta = (T)cos(theta); + + latitude = (T)atan( (Z + eDashSquared*_radiusPolar*sin_theta*sin_theta*sin_theta) / + (p - _eccentricitySquared*_radiusEquator*cos_theta*cos_theta*cos_theta) ); + longitude = (T)atan2(Y,X); + + T sin_latitude = (T)sin(latitude); + T N = _radiusEquator / (T)sqrt( 1.0 - _eccentricitySquared*sin_latitude*sin_latitude); + + height = p/(T)cos(latitude) - N; + } + + protected: + T _radiusEquator; + T _radiusPolar; + T _eccentricitySquared; + }; + class Rgba4Byte + { + public: + Rgba4Byte( + unsigned char r = 255, + unsigned char g = 255, + unsigned char b = 255, + unsigned char a = 255 + ) + { + _r = r; + _g = g; + _b = b; + _a = a; + } + friend bool operator == (const Rgba4Byte& left,const Rgba4Byte& right) + { + return left._r==right._r && + left._g==right._g && + left._b==right._b && + left._a==right._a; + } + friend bool operator != (const Rgba4Byte& left,const Rgba4Byte& right) + { + return left._r !=right._r || + left._g!=right._g || + left._b!=right._b || + left._a!=right._a; + } + operator unsigned() + { + unsigned color; + char* pColor = (char*)&color; + pColor[0] = _r; + pColor[1] = _g; + pColor[2] = _b; + pColor[3] = _a; + return color; + } + operator int() + { + int color; + char* pColor = (char*)&color; + pColor[0] = _r; + pColor[1] = _g; + pColor[2] = _b; + pColor[3] = _a; + return color; + } + operator long() + { + long color; + char* pColor = (char*)&color; + pColor[0] = _r; + pColor[1] = _g; + pColor[2] = _b; + pColor[3] = _a; + return color; + } + public: + unsigned char _r; + unsigned char _g; + unsigned char _b; + unsigned char _a; + }; + + typedef Rgba4Byte Rgba; + + inline Rgba4Byte colorLerp(const Rgba4Byte& c1, const Rgba4Byte& c2, float s) + { + Rgba4Byte color; + + color._r = (unsigned char)(c1._r + s * (c2._r - c1._r)); + color._g = (unsigned char)(c1._g + s * (c2._g - c1._g)); + color._b = (unsigned char)(c1._b + s * (c2._b - c1._b)); + color._a = (unsigned char)(c1._a + s * (c2._a - c1._a)); + return color; + } + + template + class tAxisAlignedBox2 + { + public: + enum Extent + { + EXTENT_NULL, + EXTENT_FINITE, + EXTENT_INFINITE + }; + public: + tvec2 _vMin; + tvec2 _vMax; + Extent mExtent; + public: + tvec2 center() const + { + return (_vMin + _vMax) * T(0.5); + } + + tvec2 size() const + { + return _vMax - _vMin; + } + + tvec2 halfSize() const + { + return (_vMax - _vMin) * T(0.5); + } + + bool intersects(tvec2 v) const + { + return( v.x >= _vMin.x && v.x <= _vMax.x && + v.y >= _vMin.y && v.y <= _vMax.y ); + } + + void merge(tvec2 point) + { + if (_vMin.x > point.x) + { + _vMin.x = point.x; + } + + if (_vMin.y > point.y) + { + _vMin.y = point.y; + } + if (_vMax.x < point.x) + { + _vMax.x = point.x; + } + if (_vMax.y < point.y) + { + _vMax.y = point.y; + } + } + + + void merge(tAxisAlignedBox2 other) + { + _vMax.makeCeil(other._vMax); + _vMin.makeFloor(other._vMin); + } + + bool contains(tvec2 point) const + { + return _vMin.x <= point.x && point.x <= _vMax.x && + _vMin.y <= point.y && point.y <= _vMax.y ; + } + + bool contains(tAxisAlignedBox2 other) const + { + return this->_vMin.x <= other._vMin.x && + this->_vMin.y <= other._vMin.y && + other._vMax.x <= this->_vMax.x && + other._vMax.y <= this->_vMax.y ; + } + }; + + template + class tray + { + typedef T value_type; + typedef tray type; + protected: + tvec3 _origin; + tvec3 _direction; + public: + tray(): + _origin(value_type(0),value_type(0),value_type(0)), + _direction(value_type(0),value_type(0),value_type(1)) + {} + tray(const tvec3& origin, const tvec3& direction): + _origin(origin), + _direction(direction) + {} + + /** + * 设置射线的起点 + */ + void setOrigin(const tvec3& origin) + { + _origin = origin; + } + /** + * 返回射线的起点 + */ + const tvec3& getOrigin(void) const + { + return _origin; + } + + /** + * 设置射线的方向 + */ + void setDirection(const tvec3& dir) + { + _direction = dir; + } + + /** + * 返回射线的方向 + */ + const tvec3& getDirection(void) const + { + return _direction; + } + + /** + * Gets the position of a point t units along the ray. + */ + tvec3 getPoint(T time) const + { + return tvec3(_origin + (_direction * time)); + } + + /** + * 测试射线box相交 + * 如果相交,返回值中的first == true.否则false + * second为射线到点的距离 + * 调用getPoint方法,则返回交点 + */ + std::pair intersects(const AxisAlignedBox& box) const + { + T lowt = 0.0f; + T t; + bool hit = false; + tvec3 hitpoint; + tvec3 min = box.getMinimum(); + tvec3 max = box.getMaximum(); + + /** + * 点在包围盒里面 + */ + if ( _origin > min && _origin < max ) + { + return std::pair(true, 0.0f); + } + + // Check each face in turn, only check closest 3 + // Min x + if (_origin.x <= min.x && _direction.x > 0) + { + t = (min.x - _origin.x) / _direction.x; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.y >= min.y && + hitpoint.y <= max.y && + hitpoint.z >= min.z && + hitpoint.z <= max.z && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Max x + if (_origin.x >= max.x && _direction.x < 0) + { + t = (max.x - _origin.x) / _direction.x; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.y >= min.y && + hitpoint.y <= max.y && + hitpoint.z >= min.z && + hitpoint.z <= max.z && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Min y + if (_origin.y <= min.y && _direction.y > 0) + { + t = (min.y - _origin.y) / _direction.y; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.x >= min.x && + hitpoint.x <= max.x && + hitpoint.z >= min.z && + hitpoint.z <= max.z && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Max y + if (_origin.y >= max.y && _direction.y < 0) + { + t = (max.y - _origin.y) / _direction.y; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.x >= min.x && + hitpoint.x <= max.x && + hitpoint.z >= min.z && + hitpoint.z <= max.z && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Min z + if (_origin.z <= min.z && _direction.z > 0) + { + t = (min.z - _origin.z) / _direction.z; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.x >= min.x && + hitpoint.x <= max.x && + hitpoint.y >= min.y && + hitpoint.y <= max.y && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Max z + if (_origin.z >= max.z && _direction.z < 0) + { + t = (max.z - _origin.z) / _direction.z; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = _origin + _direction * t; + if (hitpoint.x >= min.x && + hitpoint.x <= max.x && + hitpoint.y >= min.y && + hitpoint.y <= max.y && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + return std::pair(hit, lowt); + } + }; + + + template + class Plane + { + public: + tvec3 _normal; + T _distance; + public: + Plane () + { + _normal = tvec3(0,0,0); + _distance = 0.0f; + } + Plane (const Plane& right) + { + _normal = right._normal; + _distance = right._distance; + } + /** Construct a plane through a normal, and a distance to move the plane along the normal.*/ + Plane (const tvec3& rkNormal, T fConstant) + { + _normal = rkNormal; + _distance = -fConstant; + } + /** Construct a plane using the 4 constants directly **/ + Plane (T x, T y, T z, T o) + { + _normal = tvec3(x, y, z); + T invLen = 1.0f / (_normal).length(); + _normal *= invLen; + _distance = o * invLen; + } + Plane (const tvec3& rkNormal, const tvec3& rkPoint) + { + redefine(rkNormal, rkPoint); + } + Plane (const tvec3& rkPoint0, const tvec3& rkPoint1,const tvec3& rkPoint2) + { + redefine(rkPoint0, rkPoint1, rkPoint2); + } + /** + * 到点的距离 + */ + float distance(const tvec3 &pos) const + { + return dot(_normal,pos) + _distance; + } + + /** The "positive side" of the plane is the half space to which the + plane normal points. The "negative side" is the other half + space. The flag "no side" indicates the plane itself. + */ + enum Side + { + NO_SIDE, + POSITIVE_SIDE, + NEGATIVE_SIDE, + BOTH_SIDE + }; + + Side getSide (const tvec3& rkPoint) const + { + float fDistance = getDistance(rkPoint); + + if ( fDistance < 0.0 ) + return Plane::NEGATIVE_SIDE; + + if ( fDistance > 0.0 ) + return Plane::POSITIVE_SIDE; + + return Plane::NO_SIDE; + } + + + Side getSide (const tvec3& centre, const tvec3& halfSize) const + { + // Calculate the distance between box centre and the plane + float dist = getDistance(centre); + + // Calculate the maximise allows absolute distance for + // the distance between box centre and plane + float maxAbsDist = _normal.absDot(halfSize); + + if (dist < -maxAbsDist) + return Plane::NEGATIVE_SIDE; + + if (dist > +maxAbsDist) + return Plane::POSITIVE_SIDE; + + return Plane::BOTH_SIDE; + } + + float getDistance (const tvec3& rkPoint) const + { + return _normal.dot(rkPoint) + _distance; + } + + void redefine(const tvec3& rkPoint0, const tvec3& rkPoint1, + const tvec3& rkPoint2) + { + tvec3 kEdge1 = rkPoint1 - rkPoint0; + tvec3 kEdge2 = rkPoint2 - rkPoint0; + _normal = cross(kEdge1,kEdge2); + _normal.normalise(); + _distance = -dot(_normal,rkPoint0); + } + + /** Redefine this plane based on a normal and a point. */ + void redefine(const tvec3& rkNormal, const tvec3& rkPoint) + { + _normal = rkNormal; + _distance = -dot(rkNormal,rkPoint); + } + + +// tvec3 projectVector(const tvec3& p) const +// { +// matrix3 xform; +// xform[0][0] = 1.0f - _normal.x * _normal.x; +// xform[0][1] = -_normal.x * _normal.y; +// xform[0][2] = -_normal.x * _normal.z; +// xform[1][0] = -_normal.y * _normal.x; +// xform[1][1] = 1.0f - _normal.y * _normal.y; +// xform[1][2] = -_normal.y * _normal.z; +// xform[2][0] = -_normal.z * _normal.x; +// xform[2][1] = -_normal.z * _normal.y; +// xform[2][2] = 1.0f - _normal.z * _normal.z; +// return xform * p; +// } + + /** Normalises the plane. + @remarks + This method normalises the plane's normal and the length scale of d + is as well. + @note + This function will not crash for zero-sized vectors, but there + will be no changes made to their components. + @returns The previous length of the plane's normal. + */ + float normalise(void) + { + float fLength = _normal.length(); + + // Will also work for zero-sized vectors, but will change nothing + if (fLength > 1e-08f) + { + float fInvLength = 1.0f / fLength; + _normal *= fInvLength; + _distance *= fInvLength; + } + + return fLength; + } + + + + /// Comparison operator + bool operator==(const Plane& right) const + { + return (right._distance == _distance && right._normal == _normal); + } + bool operator!=(const Plane& right) const + { + return (right._distance != _distance && right._normal != _normal); + } + }; + + template + class tfrustum + { + public: + enum + { + FRUSTUM_LEFT = 0, + FRUSTUM_RIGHT = 1, + FRUSTUM_TOP = 2, + FRUSTUM_BOTTOM = 3, + FRUSTUM_FAR = 4, + FRUSTUM_NEAR = 5, + }; + public: + /** + * project * modleview + */ + void loadFrustum(const tmat4x4 &mvp) + { + const T* dataPtr = mvp.data(); + _planes[FRUSTUM_LEFT ] = Plane(dataPtr[12] - dataPtr[0], dataPtr[13] - dataPtr[1], dataPtr[14] - dataPtr[2], dataPtr[15] - dataPtr[3]); + _planes[FRUSTUM_RIGHT ] = Plane(dataPtr[12] + dataPtr[0], dataPtr[13] + dataPtr[1], dataPtr[14] + dataPtr[2], dataPtr[15] + dataPtr[3]); + + _planes[FRUSTUM_TOP ] = Plane(dataPtr[12] - dataPtr[4], dataPtr[13] - dataPtr[5], dataPtr[14] - dataPtr[6], dataPtr[15] - dataPtr[7]); + _planes[FRUSTUM_BOTTOM] = Plane(dataPtr[12] + dataPtr[4], dataPtr[13] + dataPtr[5], dataPtr[14] + dataPtr[6], dataPtr[15] + dataPtr[7]); + + _planes[FRUSTUM_FAR ] = Plane(dataPtr[12] - dataPtr[8], dataPtr[13] - dataPtr[9], dataPtr[14] - dataPtr[10], dataPtr[15] - dataPtr[11]); + _planes[FRUSTUM_NEAR ] = Plane(dataPtr[12] + dataPtr[8], dataPtr[13] + dataPtr[9], dataPtr[14] + dataPtr[10], dataPtr[15] + dataPtr[11]); + } + bool pointInFrustum(const tvec3 &pos) const + { + for (int i = 0; i < 6; i++) + { + if (_planes[i].distance(pos) <= 0) + return false; + } + return true; + } + bool sphereInFrustum(const tvec3 &pos, const float radius) const + { + for (int i = 0; i < 6; i++) + { + if (_planes[i].distance(pos) <= -radius) + return false; + } + return true; + } + bool cubeInFrustum(T minX,T maxX,T minY,T maxY,T minZ,T maxZ) const + { + for (int i = 0; i < 6; i++) + { + if (_planes[i].distance(tvec3(minX, minY, minZ)) > 0) continue; + if (_planes[i].distance(tvec3(minX, minY, maxZ)) > 0) continue; + if (_planes[i].distance(tvec3(minX, maxY, minZ)) > 0) continue; + if (_planes[i].distance(tvec3(minX, maxY, maxZ)) > 0) continue; + if (_planes[i].distance(tvec3(maxX, minY, minZ)) > 0) continue; + if (_planes[i].distance(tvec3(maxX, minY, maxZ)) > 0) continue; + if (_planes[i].distance(tvec3(maxX, maxY, minZ)) > 0) continue; + if (_planes[i].distance(tvec3(maxX, maxY, maxZ)) > 0) continue; + return false; + } + return true; + } + + const Plane &getPlane(const int plane) const + { + return _planes[plane]; + } + protected: + Plane _planes[6]; + }; + + + typedef float real; + typedef tvec2 int2; + typedef tvec2 float2; + typedef tvec2 double2; + + typedef tvec2 real2; + + + typedef tvec3 int3; + typedef tvec3 uint3; + typedef tvec3 float3; + typedef tvec3 double3; + + typedef tvec3 real3; + + + typedef tvec4 int4; + typedef tvec4 float4; + typedef tvec4 double4; + typedef tvec4 real4; + typedef trect rect4; + typedef trect rect4i; + + typedef AxisAlignedBox aabb3d; + typedef AxisAlignedBox aabbr; + + typedef AxisAlignedBox2D AABB2D; + typedef AxisAlignedBox2D aabb2dr; + typedef AxisAlignedBox2D aabb2di; + + + + typedef tmat2x2 matrix2; + typedef tmat3x3 matrix3; + typedef tmat4x4 matrix4; + typedef tmat4x4 matrix4r; + + typedef tquat quaternion; + typedef tquat quatr; + typedef tray Ray; + typedef tfrustum Frustum; + + typedef tellipsoidModel ellipsoid; + +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54400fa..c0c21b7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,8 @@ -add_executable(gtktest gtktest.cc Rgba.cc) +add_executable(gtktest gtktest.cc Rgba.cc Rester.cc) target_link_libraries (gtktest ${FC_DEP_LIBS}) add_executable(timer timer.cc) +target_link_libraries (timer ${FC_DEP_LIBS}) + +add_executable(tt tt.cc Rgba.cc) target_link_libraries (timer ${FC_DEP_LIBS}) \ No newline at end of file diff --git a/src/Rester.cc b/src/Rester.cc new file mode 100644 index 0000000..65e25d0 --- /dev/null +++ b/src/Rester.cc @@ -0,0 +1,71 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: Rester.cc + * Author: blobt + * + * Created on January 23, 2020, 6:00 PM + */ + +#include "Rgba.h" +#include "Rester.h" +#include +#include +#include + +using namespace std; + +Rester::Rester(int width, int height) { + _width = width; + _height = height; + + buffer = new Rgba[width * height]; +} + +Rester::~Rester() { + delete buffer; +} + +void Rester::drawPointer(int x, int y, Rgba color, int pointSize) { + switch (pointSize) { + case 1: + setPixel(x, y, color); + case 2: + setPixel(x, y, color); + setPixel(x + 1, y, color); + setPixel(x, y + 1, color); + setPixel(x + 1, y + 1, color); + case 3: + setPixel(x - 1, y - 1, color); + setPixel(x, y - 1, color); + setPixel(x + 1, y - 1, color); + + setPixel(x - 1, y, color); + setPixel(x, y, color); + setPixel(x + 1, y, color); + + setPixel(x - 1, y + 1, color); + setPixel(x, y + 1, color); + setPixel(x + 1, y + 1, color); + } +} + +int Rester::size() { + return _width * _height * sizeof (Rgba); +} + +void Rester::clean() { + memset(buffer, 0, size()); +} + +bool Rester::setPixel(int x, int y, Rgba color) { + if (x < 0 || y < 0 || x >= 500 || y >= 500) { + return false; + } + //行列是反的 + buffer[y * _width + x] = color; +} \ No newline at end of file diff --git a/src/Rester.h b/src/Rester.h new file mode 100644 index 0000000..571f507 --- /dev/null +++ b/src/Rester.h @@ -0,0 +1,32 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: Rester.h + * Author: blobt + * + * Created on January 23, 2020, 6:00 PM + */ + +#ifndef RESTER_H +#define RESTER_H + +class Rester { +public: + Rgba* buffer; + Rester(int width, int height); + virtual ~Rester(); + void drawPointer(int x, int y, Rgba color, int pointSize = 1); + int size(); + void clean(); + bool setPixel(int x, int y, Rgba color); +private: + int _width; + int _height; +}; + +#endif /* RESTER_H */ + diff --git a/src/Rgba.cc b/src/Rgba.cc index e63e492..51ebfe4 100644 --- a/src/Rgba.cc +++ b/src/Rgba.cc @@ -8,18 +8,65 @@ * File: Rgba.cc * Author: Blobt * - * Created on January 22, 2020, 9:14 PM + * Created on January 22, 2020, 11:36 PM */ +#include +#include #include "Rgba.h" -Rgba::Rgba() { - _r = 255; - _g = 255; - _b = 255; - _a = 255; +using namespace std; + +Rgba::Rgba(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + _r = r; + _g = g; + _b = b; + _a = a; +} + +bool operator==(Rgba &left, Rgba &right) { + return left._a == right._a && left._b == right._b && left._g == right._g && left._r == right._r; } -Rgba::~Rgba() { +bool operator!=(Rgba &left, Rgba &right) { + return left._a != right._a || left._b != right._b || left._g != right._g || left._r != right._r; +} + +Rgba::operator unsigned() { + unsigned int ret; + + unsigned char* p = (unsigned char*)&ret; + p[0] = _r; + p[1] = _g; + p[2] = _b; + p[3] = _a; + + //bitset<32> set = ret; + //cout << set << endl; + + return ret; } +Rgba::operator int() { + int ret; + + unsigned char* p = (unsigned char*)&ret; + p[0] = _r; + p[1] = _g; + p[2] = _b; + p[3] = _a; + + return ret; +} + +Rgba::operator long() { + long ret; + + unsigned char* p = (unsigned char*)&ret ; + p[0] = _r; + p[1] = _g; + p[2] = _b; + p[3] = _a; + + return ret; +} \ No newline at end of file diff --git a/src/Rgba.h b/src/Rgba.h index 2502072..74fdd1f 100644 --- a/src/Rgba.h +++ b/src/Rgba.h @@ -8,7 +8,7 @@ * File: Rgba.h * Author: Blobt * - * Created on January 22, 2020, 9:14 PM + * Created on January 22, 2020, 11:36 PM */ #ifndef RGBA_H @@ -16,9 +16,13 @@ class Rgba { public: - Rgba(); - ~Rgba(); -private: + Rgba(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0); + friend bool operator==(Rgba &left, Rgba &right); + friend bool operator!=(Rgba &left, Rgba &righe); + operator unsigned(); + operator int(); + operator long(); +public: unsigned char _r; unsigned char _g; unsigned char _b; diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..37808f3 --- /dev/null +++ b/src/common.h @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: common.h + * Author: Blobt + * + * Created on October 5, 2019, 4:55 PM + */ + +#ifndef COMMON_H +#define COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define die(m) do { perror(m); exit(EXIT_FAILURE); } while(0) + + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H */ + diff --git a/src/gtktest.cc b/src/gtktest.cc index c5c2c46..42c29c8 100644 --- a/src/gtktest.cc +++ b/src/gtktest.cc @@ -2,6 +2,8 @@ #include #include #include "Rgba.h" +#include "Rester.h" +#include "common.h" using namespace std; @@ -9,12 +11,24 @@ using namespace std; gint height = 500; gint width = 500; -unsigned char* makeBitmap() { +Rester rester(width, height); + +unsigned char* makeBitmapRand() { unsigned char* data = new unsigned char[width * height * 4]; for (int i = 0; i < width * height * 4; i++) { data[i] = rand() % 255; } + return data; +} + +unsigned char* makeBitmap() { + rester.clean(); + unsigned char* data = new unsigned char[width * height * 4]; + for (int i = 0; i < 100; i++) { + rester.drawPointer(rand() % 500, rand() % 500, Rgba(255, 0, 0), 3); + } + memcpy(data, rester.buffer, rester.size()); return data; } diff --git a/src/tt.cc b/src/tt.cc new file mode 100644 index 0000000..15c0fed --- /dev/null +++ b/src/tt.cc @@ -0,0 +1,23 @@ +#include "Rgba.h" +#include +#include +#include +#include + +using namespace std; + +int main() { + Rgba x(255, 0, 0, 255); + Rgba y(0, 0, 255, 255); + + unsigned char* z = new unsigned char[4]; + + Rgba buffer[5][5]; + + printf("%ld\n", sizeof(buffer)); + //memcpy(z, x, sizeof(x)); +// +// +// bitset<32> set = (int)z; +// cout << set << endl; +}