00001
00011 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00012 #pragma once
00013 #endif
00014 #ifndef COMMON_MATH_H_
00015 #define COMMON_MATH_H_
00016
00017 #ifdef WIN32
00018 #include <windows.h>
00019 #endif
00020
00021 #ifdef USE_DIRECTX
00022 #include <d3d9types.h>
00023 #include <d3dx9math.h>
00024 #endif
00025
00026 namespace common
00027 {
00028
00033
00035
00036 template <typename DestT, typename SrcT>
00037 DestT & math_cast(const SrcT &x)
00038 {
00039 assert(0 && "Unsupported type in math_cast.");
00040 }
00041
00042
00043
00046
00048
00053 struct POINT_
00054 {
00055 union
00056 {
00057 struct
00058 {
00059 int x, y;
00060 };
00061 int v[2];
00062 };
00063
00064 static const POINT_ ZERO;
00065
00066 POINT_() { }
00067 POINT_(int x, int y) : x(x), y(y) { }
00068
00069 bool operator == (const POINT_ &v) const { return x == v.x && y == v.y; }
00070 bool operator != (const POINT_ &v) const { return x != v.x || y != v.y; }
00071
00072 POINT_ operator - () const { return POINT_(-x, -y); }
00073 POINT_ operator + (const POINT_ &v) const { return POINT_(x+v.x, y+v.y); }
00074 POINT_ operator - (const POINT_ &v) const { return POINT_(x-v.x, y-v.y); }
00075 POINT_ & operator += (const POINT_ &v) { x += v.x; y += v.y; return *this; }
00076 POINT_ & operator -= (const POINT_ &v) { x -= v.x; y -= v.y; return *this; }
00077 POINT_ & operator *= (int v) { x *= v; y *= v; return *this; }
00078 POINT_ & operator /= (int v) { x /= v; y /= v; return *this; }
00079
00080 int & operator [] (uint4 Index) { return v[Index]; }
00081 const int & operator [] (uint4 Index) const { return v[Index]; }
00082
00083 int * GetArray() { return &x; }
00084 const int * GetArray() const { return &x; }
00085 };
00086
00087 inline POINT_ operator * (const POINT_ pt, int v) { return POINT_(pt.x*v, pt.y*v); }
00088 inline POINT_ operator / (const POINT_ pt, int v) { return POINT_(pt.x/v, pt.y/v); }
00089 inline POINT_ operator * (int v, const POINT_ pt) { return POINT_(pt.x*v, pt.y*v); }
00090 inline POINT_ operator / (int v, const POINT_ pt) { return POINT_(pt.x/v, pt.y/v); }
00091
00092 #ifdef WIN32
00094 template <> inline ::POINT & math_cast<::POINT, POINT_>(const POINT_ &x) { return (::POINT&)(x); }
00096 template <> inline POINT_ & math_cast<POINT_, ::POINT>(const ::POINT &x) { return (POINT_&)(x); }
00097 #endif
00098
00099 inline void swap(POINT_ &v1, POINT_ &v2)
00100 {
00101 std::swap(v1.x, v2.x);
00102 std::swap(v1.y, v2.y);
00103 }
00104
00106
00107
00108
00111
00112 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
00113 typedef D3DXVECTOR2 VEC2;
00114 #else
00116 struct VEC2
00117 {
00118 float x, y;
00119
00120 VEC2() { }
00121 VEC2(float x, float y) : x(x), y(y) { }
00122 VEC2(const float *Array) : x(Array[0]), y(Array[1]) { }
00123
00124 operator float * () { return &x; }
00125 operator const float * () const { return &x; }
00126
00127 bool operator == (const VEC2 &v) const { return x == v.x && y == v.y; }
00128 bool operator != (const VEC2 &v) const { return x != v.x || y != v.y; }
00129
00130 VEC2 operator + () const { return *this; }
00131 VEC2 operator - () const { return VEC2(-x, -y); }
00132 VEC2 operator + (const VEC2 &v) const { return VEC2(x+v.x, y+v.y); }
00133 VEC2 operator - (const VEC2 &v) const { return VEC2(x-v.x, y-v.y); }
00134 VEC2 & operator += (const VEC2 &v) { x += v.x; y += v.y; return *this; }
00135 VEC2 & operator -= (const VEC2 &v) { x -= v.x; y -= v.y; return *this; }
00136 VEC2 & operator *= (float v) { x *= v; y *= v; return *this; }
00137 VEC2 & operator /= (float v) { x /= v; y /= v; return *this; }
00138 };
00139 inline VEC2 operator * (const VEC2 pt, float v) { return VEC2(pt.x*v, pt.y*v); }
00140 inline VEC2 operator / (const VEC2 pt, float v) { return VEC2(pt.x/v, pt.y/v); }
00141 inline VEC2 operator * (float v, const VEC2 pt) { return VEC2(pt.x*v, pt.y*v); }
00142 inline VEC2 operator / (float v, const VEC2 pt) { return VEC2(pt.x/v, pt.y/v); }
00143 #endif
00144
00145 inline void swap(VEC2 &v1, VEC2 &v2)
00146 {
00147 std::swap(v1.x, v2.x);
00148 std::swap(v1.y, v2.y);
00149 }
00150
00151 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
00152 typedef D3DXVECTOR3 VEC3;
00153 #else
00155 struct VEC3
00156 {
00157 float x, y, z;
00158
00159 VEC3() { }
00160 VEC3(float x, float y, float z) : x(x), y(y), z(z) { }
00161 VEC3(const float *Array) : x(Array[0]), y(Array[1]), z(Array[2]) { }
00162
00163 operator float * () { return &x; }
00164 operator const float * () const { return &x; }
00165
00166 bool operator == (const VEC3 &v) const { return x == v.x && y == v.y && z == v.z; }
00167 bool operator != (const VEC3 &v) const { return x != v.x || y != v.y || z != v.z; }
00168
00169 VEC3 operator + () const { return *this; }
00170 VEC3 operator - () const { return VEC3(-x, -y, -z); }
00171 VEC3 operator + (const VEC3 &v) const { return VEC3(x+v.x, y+v.y, z+v.z); }
00172 VEC3 operator - (const VEC3 &v) const { return VEC3(x-v.x, y-v.y, z-v.z); }
00173 VEC3 & operator += (const VEC3 &v) { x += v.x; y += v.y; z += v.z; return *this; }
00174 VEC3 & operator -= (const VEC3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
00175 VEC3 & operator *= (float v) { x *= v; y *= v; z *= v; return *this; }
00176 VEC3 & operator /= (float v) { x /= v; y /= v; z /= v; return *this; }
00177 };
00178 inline VEC3 operator * (const VEC3 pt, float v) { return VEC3(pt.x*v, pt.y*v, pt.z*v); }
00179 inline VEC3 operator / (const VEC3 pt, float v) { return VEC3(pt.x/v, pt.y/v, pt.z/v); }
00180 inline VEC3 operator * (float v, const VEC3 pt) { return VEC3(pt.x*v, pt.y*v, pt.z*v); }
00181 inline VEC3 operator / (float v, const VEC3 pt) { return VEC3(pt.x/v, pt.y/v, pt.z/v); }
00182 #endif
00183
00184 inline void swap(VEC3 &v1, VEC3 &v2)
00185 {
00186 std::swap(v1.x, v2.x);
00187 std::swap(v1.y, v2.y);
00188 std::swap(v1.z, v2.z);
00189 }
00190
00191 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
00192 typedef D3DXVECTOR4 VEC4;
00193 #else
00195 struct VEC4
00196 {
00197 float x, y, z, w;
00198
00199 VEC4() { }
00200 VEC4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
00201 VEC4(const float *Array) : x(Array[0]), y(Array[1]), z(Array[2]), w(Array[3]) { }
00202
00203 operator float * () { return &x; }
00204 operator const float * () const { return &x; }
00205
00206 bool operator == (const VEC4 &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; }
00207 bool operator != (const VEC4 &v) const { return x != v.x || y != v.y || z != v.z || w != v.w; }
00208
00209 VEC4 operator + () const { return *this; }
00210 VEC4 operator - () const { return VEC4(-x, -y, -z, -w); }
00211 VEC4 operator + (const VEC4 &v) const { return VEC4(x+v.x, y+v.y, z+v.z, w+v.w); }
00212 VEC4 operator - (const VEC4 &v) const { return VEC4(x-v.x, y-v.y, z-v.z, w-v.w); }
00213 VEC4 & operator += (const VEC4 &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
00214 VEC4 & operator -= (const VEC4 &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
00215 VEC4 & operator *= (float v) { x *= v; y *= v; z *= v; w *= v; return *this; }
00216 VEC4 & operator /= (float v) { x /= v; y /= v; z /= v; w /= v; return *this; }
00217 };
00218 inline VEC4 operator * (const VEC4 pt, float v) { return VEC4(pt.x*v, pt.y*v, pt.z*v, pt.w*v); }
00219 inline VEC4 operator / (const VEC4 pt, float v) { return VEC4(pt.x/v, pt.y/v, pt.z/v, pt.w/v); }
00220 inline VEC4 operator * (float v, const VEC4 pt) { return VEC4(pt.x*v, pt.y*v, pt.z*v, pt.w*v); }
00221 inline VEC4 operator / (float v, const VEC4 pt) { return VEC4(pt.x/v, pt.y/v, pt.z/v, pt.w/v); }
00222 #endif
00223
00224 inline void swap(VEC4 &v1, VEC4 &v2)
00225 {
00226 std::swap(v1.x, v2.x);
00227 std::swap(v1.y, v2.y);
00228 std::swap(v1.z, v2.z);
00229 std::swap(v1.w, v2.w);
00230 }
00231
00232 extern const VEC2 VEC2_ZERO;
00233 extern const VEC2 VEC2_ONE;
00234 extern const VEC2 VEC2_POSITIVE_X;
00235 extern const VEC2 VEC2_POSITIVE_Y;
00236 extern const VEC2 VEC2_NEGATIVE_X;
00237 extern const VEC2 VEC2_NEGATIVE_Y;
00238
00239 extern const VEC3 VEC3_ZERO;
00240 extern const VEC3 VEC3_ONE;
00241 extern const VEC3 VEC3_POSITIVE_X;
00242 extern const VEC3 VEC3_POSITIVE_Y;
00243 extern const VEC3 VEC3_POSITIVE_Z;
00244 extern const VEC3 VEC3_NEGATIVE_X;
00245 extern const VEC3 VEC3_NEGATIVE_Y;
00246 extern const VEC3 VEC3_NEGATIVE_Z;
00247
00248 extern const VEC4 VEC4_ZERO;
00249 extern const VEC4 VEC4_ONE;
00250 extern const VEC4 VEC4_POSITIVE_X;
00251 extern const VEC4 VEC4_POSITIVE_Y;
00252 extern const VEC4 VEC4_POSITIVE_Z;
00253 extern const VEC4 VEC4_POSITIVE_W;
00254 extern const VEC4 VEC4_NEGATIVE_X;
00255 extern const VEC4 VEC4_NEGATIVE_Y;
00256 extern const VEC4 VEC4_NEGATIVE_Z;
00257 extern const VEC4 VEC4_NEGATIVE_W;
00258
00260 inline float LengthSq(const VEC2 &v)
00261 {
00262 return v.x*v.x + v.y*v.y;
00263 }
00265 inline float LengthSq(const VEC3 &v)
00266 {
00267 return v.x*v.x + v.y*v.y + v.z*v.z;
00268 }
00270 inline float LengthSq(const VEC4 &v)
00271 {
00272 return v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w;
00273 }
00274
00276 inline float Length(const VEC2 &v)
00277 {
00278 return sqrtf(LengthSq(v));
00279 }
00281 inline float Length(const VEC3 &v)
00282 {
00283 return sqrtf(LengthSq(v));
00284 }
00286 inline float Length(const VEC4 &v)
00287 {
00288 return sqrtf(LengthSq(v));
00289 }
00290
00292 inline void Min(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00293 {
00294 Out->x = std::min(v1.x, v2.x);
00295 Out->y = std::min(v1.y, v2.y);
00296 }
00297 inline void Min(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00298 {
00299 Out->x = std::min(v1.x, v2.x);
00300 Out->y = std::min(v1.y, v2.y);
00301 Out->z = std::min(v1.z, v2.z);
00302 }
00303 inline void Min(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00304 {
00305 Out->x = std::min(v1.x, v2.x);
00306 Out->y = std::min(v1.y, v2.y);
00307 Out->z = std::min(v1.z, v2.z);
00308 Out->w = std::min(v1.w, v2.w);
00309 }
00310
00312 inline void Max(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00313 {
00314 Out->x = std::max(v1.x, v2.x);
00315 Out->y = std::max(v1.y, v2.y);
00316 }
00317 inline void Max(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00318 {
00319 Out->x = std::max(v1.x, v2.x);
00320 Out->y = std::max(v1.y, v2.y);
00321 Out->z = std::max(v1.z, v2.z);
00322 }
00323 inline void Max(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00324 {
00325 Out->x = std::max(v1.x, v2.x);
00326 Out->y = std::max(v1.y, v2.y);
00327 Out->z = std::max(v1.z, v2.z);
00328 Out->w = std::max(v1.w, v2.w);
00329 }
00330
00333
00334 inline void Mul(VEC2 *Out, const VEC2 &v, float f)
00335 {
00336 Out->x = v.x * f;
00337 Out->y = v.y * f;
00338 }
00339 inline void Mul(VEC3 *Out, const VEC3 &v, float f)
00340 {
00341 Out->x = v.x * f;
00342 Out->y = v.y * f;
00343 Out->z = v.z * f;
00344 }
00345 inline void Mul(VEC4 *Out, const VEC4 &v, float f)
00346 {
00347 Out->x = v.x * f;
00348 Out->y = v.y * f;
00349 Out->z = v.z * f;
00350 Out->w = v.w * f;
00351 }
00352
00353 inline void Add(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00354 {
00355 Out->x = v1.x + v2.x;
00356 Out->y = v1.y + v2.y;
00357 }
00358 inline void Add(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00359 {
00360 Out->x = v1.x + v2.x;
00361 Out->y = v1.y + v2.y;
00362 Out->z = v1.z + v2.z;
00363 }
00364 inline void Add(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00365 {
00366 Out->x = v1.x + v2.x;
00367 Out->y = v1.y + v2.y;
00368 Out->z = v1.z + v2.z;
00369 Out->w = v1.w + v2.w;
00370 }
00371
00372 inline void Sub(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00373 {
00374 Out->x = v1.x - v2.x;
00375 Out->y = v1.y - v2.y;
00376 }
00377 inline void Sub(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00378 {
00379 Out->x = v1.x - v2.x;
00380 Out->y = v1.y - v2.y;
00381 Out->z = v1.z - v2.z;
00382 }
00383 inline void Sub(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00384 {
00385 Out->x = v1.x - v2.x;
00386 Out->y = v1.y - v2.y;
00387 Out->z = v1.z - v2.z;
00388 Out->w = v1.w - v2.w;
00389 }
00390
00391 inline void Mul(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00392 {
00393 Out->x = v1.x * v2.x;
00394 Out->y = v1.y * v2.y;
00395 }
00396 inline void Mul(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00397 {
00398 Out->x = v1.x * v2.x;
00399 Out->y = v1.y * v2.y;
00400 Out->z = v1.z * v2.z;
00401 }
00402 inline void Mul(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00403 {
00404 Out->x = v1.x * v2.x;
00405 Out->y = v1.y * v2.y;
00406 Out->z = v1.z * v2.z;
00407 Out->w = v1.w * v2.w;
00408 }
00409
00410 inline void Div(VEC2 *Out, const VEC2 &v1, const VEC2 &v2)
00411 {
00412 Out->x = v1.x / v2.x;
00413 Out->y = v1.y / v2.y;
00414 }
00415 inline void Div(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00416 {
00417 Out->x = v1.x / v2.x;
00418 Out->y = v1.y / v2.y;
00419 Out->z = v1.z / v2.z;
00420 }
00421 inline void Div(VEC4 *Out, const VEC4 &v1, const VEC4 &v2)
00422 {
00423 Out->x = v1.x / v2.x;
00424 Out->y = v1.y / v2.y;
00425 Out->z = v1.z / v2.z;
00426 Out->w = v1.w / v2.w;
00427 }
00428
00430
00431
00433 inline float Dot(const VEC2 &v1, const VEC2 &v2)
00434 {
00435 return v1.x*v2.x + v1.y*v2.y;
00436 }
00437 inline float Dot(const VEC3 &v1, const VEC3 &v2)
00438 {
00439 return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
00440 }
00441 inline float Dot(const VEC4 &v1, const VEC4 &v2)
00442 {
00443 return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w;
00444 }
00445
00447 inline void Minus(VEC2 *Out, VEC2 &v) { Out->x = -v.x; Out->y = -v.y; }
00448 inline void Minus(VEC3 *Out, VEC3 &v) { Out->x = -v.x; Out->y = -v.y; Out->z = -v.z; }
00449 inline void Minus(VEC4 *Out, VEC4 &v) { Out->x = -v.x; Out->y = -v.y; Out->z = -v.z; Out->w = -v.w; }
00450 inline void Minus(VEC2 *InOut) { InOut->x = -InOut->x; InOut->y = -InOut->y; }
00451 inline void Minus(VEC3 *InOut) { InOut->x = -InOut->x; InOut->y = -InOut->y; InOut->z = -InOut->z; }
00452 inline void Minus(VEC4 *InOut) { InOut->x = -InOut->x; InOut->y = -InOut->y; InOut->z = -InOut->z; InOut->w = -InOut->w; }
00453
00455
00457 inline float Cross(const VEC2 &v1, const VEC2 &v2)
00458 {
00459 return v1.x*v2.y - v1.y*v2.x;
00460 }
00461
00463 inline void Cross(VEC3 *Out, const VEC3 &v1, const VEC3 &v2)
00464 {
00465 Out->x = v1.y * v2.z - v1.z * v2.y;
00466 Out->y = v1.z * v2.x - v1.x * v2.z;
00467 Out->z = v1.x * v2.y - v1.y * v2.x;
00468 }
00469
00471 inline float DistanceSq(const VEC2 &p1, const VEC2 &p2)
00472 {
00473 return LengthSq(p2-p1);
00474 }
00475 inline float DistanceSq(const VEC3 &p1, const VEC3 &p2)
00476 {
00477 return LengthSq(p2-p1);
00478 }
00479 inline float DistanceSq(const VEC4 &p1, const VEC4 &p2)
00480 {
00481 return LengthSq(p2-p1);
00482 }
00483
00485 inline float Distance(const VEC2 &p1, const VEC2 &p2)
00486 {
00487 return Length(p2-p1);
00488 }
00489 inline float Distance(const VEC3 &p1, const VEC3 &p2)
00490 {
00491 return Length(p2-p1);
00492 }
00493 inline float Distance(const VEC4 &p1, const VEC4 &p2)
00494 {
00495 return Length(p2-p1);
00496 }
00497
00499 inline void Lerp(VEC2 *Out, const VEC2 &v1, const VEC2 &v2, float t)
00500 {
00501 Out->x = v1.x + t*(v2.x-v1.x);
00502 Out->y = v1.y + t*(v2.y-v1.y);
00503 }
00504 inline void Lerp(VEC3 *Out, const VEC3 &v1, const VEC3 &v2, float t)
00505 {
00506 Out->x = v1.x + t*(v2.x-v1.x);
00507 Out->y = v1.y + t*(v2.y-v1.y);
00508 Out->z = v1.z + t*(v2.z-v1.z);
00509 }
00510 inline void Lerp(VEC4 *Out, const VEC4 &v1, const VEC4 &v2, float t)
00511 {
00512 Out->x = v1.x + t*(v2.x-v1.x);
00513 Out->y = v1.y + t*(v2.y-v1.y);
00514 Out->z = v1.z + t*(v2.z-v1.z);
00515 Out->w = v1.w + t*(v2.w-v1.w);
00516 }
00517
00519 inline void Normalize(VEC2 *Out, const VEC2 &v)
00520 {
00521 float l = 1.0f / Length(v);
00522 Out->x = v.x * l;
00523 Out->y = v.y * l;
00524 }
00525 inline void Normalize(VEC3 *Out, const VEC3 &v)
00526 {
00527 float l = 1.0f / Length(v);
00528 Out->x = v.x * l;
00529 Out->y = v.y * l;
00530 Out->z = v.z * l;
00531 }
00532 inline void Normalize(VEC4 *Out, const VEC4 &v)
00533 {
00534 float l = 1.0f / Length(v);
00535 Out->x = v.x * l;
00536 Out->y = v.y * l;
00537 Out->z = v.z * l;
00538 Out->w = v.w * l;
00539 }
00540
00542 inline void Normalize(VEC2 *v)
00543 {
00544 float rcl = 1.0f / Length(*v);
00545 v->x *= rcl;
00546 v->y *= rcl;
00547 }
00548 inline void Normalize(VEC3 *v)
00549 {
00550 float rcl = 1.0f / Length(*v);
00551 v->x *= rcl;
00552 v->y *= rcl;
00553 v->z *= rcl;
00554 }
00555 inline void Normalize(VEC4 *v)
00556 {
00557 float rcl = 1.0f / Length(*v);
00558 v->x *= rcl;
00559 v->y *= rcl;
00560 v->z *= rcl;
00561 v->w *= rcl;
00562 }
00563
00565 inline void Vec3ToVec4(VEC4 *Out, const VEC3 &v)
00566 {
00567 Out->x = v.x;
00568 Out->y = v.y;
00569 Out->z = v.z;
00570 Out->w = 1.0f;
00571 }
00572
00574 inline void Vec4ToVec3_Ignore(VEC3 *Out, const VEC4 &v)
00575 {
00576 Out->x = v.x;
00577 Out->y = v.y;
00578 Out->z = v.z;
00579 }
00581 inline void Vec4ToVec3_Div(VEC3 *Out, const VEC4 &v)
00582 {
00583 float rcw = 1.0f / v.w;
00584 Out->x = v.x * rcw;
00585 Out->y = v.y * rcw;
00586 Out->z = v.z * rcw;
00587 }
00588
00590 inline void MidPoint(VEC2 *Out, const VEC2 &p1, const VEC2 &p2)
00591 {
00592 Out->x = (p1.x+p2.x) * 0.5f;
00593 Out->y = (p1.y+p2.y) * 0.5f;
00594 }
00595 inline void MidPoint(VEC3 *Out, const VEC3 &p1, const VEC3 &p2)
00596 {
00597 Out->x = (p1.x+p2.x) * 0.5f;
00598 Out->y = (p1.y+p2.y) * 0.5f;
00599 Out->z = (p1.z+p2.z) * 0.5f;
00600 }
00601 inline void MidPoint(VEC4 *Out, const VEC4 &p1, const VEC4 &p2)
00602 {
00603 Out->x = (p1.x+p2.x) * 0.5f;
00604 Out->y = (p1.y+p2.y) * 0.5f;
00605 Out->z = (p1.z+p2.z) * 0.5f;
00606 Out->w = (p1.w+p2.w) * 0.5f;
00607 }
00608
00610 inline bool VecEqual(const VEC2 &v1, const VEC2 &v2) {
00611 return float_equal(v1.x, v2.x) && float_equal(v1.y, v2.y);
00612 }
00613 inline bool VecEqual(const VEC3 &v1, const VEC3 &v2) {
00614 return float_equal(v1.x, v2.x) && float_equal(v1.y, v2.y) && float_equal(v1.z, v2.z);
00615 }
00616 inline bool VecEqual(const VEC4 &v1, const VEC4 &v2) {
00617 return float_equal(v1.x, v2.x) && float_equal(v1.y, v2.y) && float_equal(v1.z, v2.z) && float_equal(v1.w, v2.w);
00618 }
00619
00625
00626 inline bool Less(const VEC2 &v1, const VEC2 &v2)
00627 {
00628 return v1.x < v2.x && v1.y < v2.y;
00629 }
00630 inline bool Less(const VEC3 &v1, const VEC3 &v2)
00631 {
00632 return v1.x < v2.x && v1.y < v2.y && v1.z < v2.z;
00633 }
00634 inline bool Less(const VEC4 &v1, const VEC4 &v2)
00635 {
00636 return v1.x < v2.x && v1.y < v2.y && v1.z < v2.z && v1.w < v2.w;
00637 }
00638
00639 inline bool LessOrEqual(const VEC2 &v1, const VEC2 &v2)
00640 {
00641 return v1.x <= v2.x && v1.y <= v2.y;
00642 }
00643 inline bool LessOrEqual(const VEC3 &v1, const VEC3 &v2)
00644 {
00645 return v1.x <= v2.x && v1.y <= v2.y && v1.z <= v2.z;
00646 }
00647 inline bool LessOrEqual(const VEC4 &v1, const VEC4 &v2)
00648 {
00649 return v1.x <= v2.x && v1.y <= v2.y && v1.z <= v2.z && v1.w <= v2.w;
00650 }
00651
00652 inline bool Greater(const VEC2 &v1, const VEC2 &v2)
00653 {
00654 return v1.x > v2.x && v1.y > v2.y;
00655 }
00656 inline bool Greater(const VEC3 &v1, const VEC3 &v2)
00657 {
00658 return v1.x > v2.x && v1.y > v2.y && v1.z > v2.z;
00659 }
00660 inline bool Greater(const VEC4 &v1, const VEC4 &v2)
00661 {
00662 return v1.x > v2.x && v1.y > v2.y && v1.z > v2.z && v1.w > v2.w;
00663 }
00664
00665 inline bool GreaterOrEqual(const VEC2 &v1, const VEC2 &v2)
00666 {
00667 return v1.x >= v2.x && v1.y >= v2.y;
00668 }
00669 inline bool GreaterOrEqual(const VEC3 &v1, const VEC3 &v2)
00670 {
00671 return v1.x >= v2.x && v1.y >= v2.y && v1.z >= v2.z;
00672 }
00673 inline bool GreaterOrEqual(const VEC4 &v1, const VEC4 &v2)
00674 {
00675 return v1.x >= v2.x && v1.y >= v2.y && v1.z >= v2.z && v1.w >= v2.w;
00676 }
00677
00679
00680
00681 inline bool around(const VEC2 &v1, const VEC2 &v2, float Epsilon) {
00682 return around(v1.x, v2.x, Epsilon) && around(v1.y, v2.y, Epsilon);
00683 }
00684 inline bool around(const VEC3 &v1, const VEC3 &v2, float Epsilon) {
00685 return around(v1.x, v2.x, Epsilon) && around(v1.y, v2.y, Epsilon) && around(v1.z, v2.z, Epsilon);
00686 }
00687 inline bool around(const VEC4 &v1, const VEC4 &v2, float Epsilon) {
00688 return around(v1.x, v2.x, Epsilon) && around(v1.y, v2.y, Epsilon) && around(v1.z, v2.z, Epsilon) && around(v1.w, v2.w, Epsilon);
00689 }
00690
00692
00694 inline void Perpedicular(VEC2 *Out, const VEC2 &v)
00695 {
00696 Out->x = -v.y;
00697 Out->y = v.x;
00698 }
00699
00701
00705 inline void Reflect(VEC2 *Out, const VEC2 &v, const VEC2 &PlaneNormal)
00706 {
00707
00708 float f = 2.0f * Dot(v, PlaneNormal);
00709 Out->x = v.x - f * PlaneNormal.x;
00710 Out->y = v.y - f * PlaneNormal.y;
00711 }
00712 inline void Reflect(VEC3 *Out, const VEC3 &v, const VEC3 &PlaneNormal)
00713 {
00714
00715 float f = 2.0f * Dot(v, PlaneNormal);
00716 Out->x = v.x - f * PlaneNormal.x;
00717 Out->y = v.y - f * PlaneNormal.y;
00718 Out->z = v.z - f * PlaneNormal.z;
00719 }
00720
00722
00725 inline void Project(VEC2 *Out, const VEC2 &V, const VEC2 &N)
00726 {
00727
00728
00729
00730 float T = (V.x*N.x + V.y*N.y) / (N.x*N.x + N.y*N.y);
00731 Out->x = N.x * T;
00732 Out->y = N.y * T;
00733 }
00734 inline void Project(VEC3 *Out, const VEC3 &V, const VEC3 &N)
00735 {
00736 float T = (V.x*N.x + V.y*N.y + V.z*N.z) / (N.x*N.x + N.y*N.y + N.z*N.z);
00737 Out->x = N.x * T;
00738 Out->y = N.y * T;
00739 Out->z = N.z * T;
00740 }
00742 inline void Project_N(VEC2 *Out, const VEC2 &V, const VEC2 &N)
00743 {
00744
00745
00746
00747 float T = V.x*N.x + V.y*N.y;
00748 Out->x = N.x * T;
00749 Out->y = N.y * T;
00750 }
00751 inline void Project_N(VEC3 *Out, const VEC3 &V, const VEC3 &N)
00752 {
00753 float T = V.x*N.x + V.y*N.y + V.z*N.z;
00754 Out->x = N.x * T;
00755 Out->y = N.y * T;
00756 Out->z = N.z * T;
00757 }
00758
00765
00766 void Orthogonalize_Fast(VEC3 *OutR1, VEC3 *OutR2, VEC3 *OutR3, const VEC3 &R1, const VEC3 &R2, const VEC3 &R3);
00768 void Orthogonalize(VEC3 *OutR1, VEC3 *OutR2, VEC3 *OutR3, const VEC3 &R1, const VEC3 &R2, const VEC3 &R3);
00770
00772
00774 void PerpedicularVectors(VEC3 *Out1, VEC3 *Out2, const VEC3 &v);
00775
00777
00778
00779
00780
00783
00785
00786 float TriangleArea(const VEC2 &p1, const VEC2 &p2, const VEC2 &p3);
00787 float TriangleArea(const VEC3 &p1, const VEC3 &p2, const VEC3 &p3);
00788
00790 float TrianglePerimeter(const VEC2 &p1, const VEC2 &p2, const VEC2 &p3);
00791 float TrianglePerimeter(const VEC3 &p1, const VEC3 &p2, const VEC3 &p3);
00792
00794
00797 inline void Barycentric(VEC2 *Out, const VEC2 &p1, const VEC2 &p2, const VEC2 &p3, float f, float g)
00798 {
00799 float e = 1.0f-f-g;
00800 Out->x = e*p1.x + f*p2.x + g*p3.x;
00801 Out->y = e*p1.y + f*p2.y + g*p3.y;
00802 }
00803 inline void Barycentric(VEC3 *Out, const VEC3 &p1, const VEC3 &p2, const VEC3 &p3, float f, float g)
00804 {
00805
00806
00807
00808
00809
00810
00811
00812 float e = 1.0f-f-g;
00813 Out->x = e*p1.x + f*p2.x + g*p3.x;
00814 Out->y = e*p1.y + f*p2.y + g*p3.y;
00815 Out->z = e*p1.z + f*p2.z + g*p3.z;
00816 }
00817 inline void Barycentric(VEC4 *Out, const VEC4 &p1, const VEC4 &p2, const VEC4 &p3, float f, float g)
00818 {
00819 float e = 1.0f-f-g;
00820 Out->x = e*p1.x + f*p2.x + g*p3.x;
00821 Out->y = e*p1.y + f*p2.y + g*p3.y;
00822 Out->z = e*p1.z + f*p2.z + g*p3.z;
00823 Out->w = e*p1.w + f*p2.w + g*p3.w;
00824 }
00825
00827
00830 void CalculateBarycentric(const VEC3 &p, const VEC3 &p1, const VEC3 &p2, const VEC3 &p3, const VEC3 *Normal, float *e, float *f, float *g);
00831
00833 void TriangleInscribedCircle(VEC2 *OutCenter, float *OutRadius, const VEC2 &v1, const VEC2 &v2, const VEC2 &v3);
00834 void TriangleInscribedCircle(VEC3 *OutCenter, float *OutRadius, const VEC3 &v1, const VEC3 &v2, const VEC3 &v3);
00836 void TriangleCircumscribedCircle(VEC2 *OutCenter, float *OutRadius, const VEC2 &v1, const VEC2 &v2, const VEC2 &v3);
00837 void TriangleCircumscribedCircle(VEC3 *OutCenter, float *OutRadius, const VEC3 &v1, const VEC3 &v2, const VEC3 &v3);
00838
00840
00841
00842
00843
00846
00848 inline void PointOnRay(VEC2 *Out, const VEC2 &Origin, const VEC2 &Direction, float t)
00849 {
00850 Out->x = Origin.x + t * Direction.x;
00851 Out->y = Origin.y + t * Direction.y;
00852 }
00853 inline void PointOnRay(VEC3 *Out, const VEC3 &Origin, const VEC3 &Direction, float t)
00854 {
00855 Out->x = Origin.x + t * Direction.x;
00856 Out->y = Origin.y + t * Direction.y;
00857 Out->z = Origin.z + t * Direction.z;
00858 }
00859
00861
00862
00863
00864
00867
00869
00875 struct RECTI
00876 {
00877 int left, top, right, bottom;
00878
00879 RECTI() { }
00880 RECTI(int left, int top, int right, int bottom) : left(left), top(top), right(right), bottom(bottom) { }
00881 RECTI(const int *Arr) : left(Arr[0]), top(Arr[1]), right(Arr[2]), bottom(Arr[3]) { }
00882
00883 operator int * () { return &left; }
00884 operator const int * () const { return &left; }
00885
00886 bool operator == (const RECTI &r) const { return left == r.left && top == r.top && right == r.right && bottom == r.bottom; }
00887 bool operator != (const RECTI &r) const { return left != r.left || top != r.top || right != r.right || bottom != r.bottom; }
00888
00889 RECTI operator + () const { return *this; }
00890 RECTI operator - () const { return RECTI(-right, -bottom, -left, -top); }
00891 RECTI operator + (const POINT_ &p) const { return RECTI(left+p.x, top+p.y, right+p.x, bottom+p.y); }
00892 RECTI operator - (const POINT_ &p) const { return RECTI(left-p.x, top-p.y, right-p.x, bottom-p.y); }
00893 RECTI operator * (int s) const { return RECTI(left*s, top*s, right*s, bottom*s); }
00894 RECTI operator * (const POINT_ &s) const { return RECTI(left*s.x, top*s.y, right*s.x, bottom*s.y); }
00895 RECTI & operator += (const POINT_ &p) { left += p.x; top += p.y; right += p.x; bottom += p.y; return *this; }
00896 RECTI & operator -= (const POINT_ &p) { left -= p.x; top -= p.y; right -= p.x; bottom -= p.y; return *this; }
00897 RECTI & operator *= (int s) { left *= s; top *= s; right *= s; bottom *= s; return *this; }
00898 RECTI & operator *= (const POINT_ &s) { left *= s.x; top *= s.y; right *= s.x; bottom *= s.y; return *this; }
00899
00900 bool IsValid() const { return left < right && top < bottom; }
00901 void Repair() { if (right < left) std::swap(left, right); if (bottom < top) std::swap(top, bottom); }
00902
00903 void LeftTop(POINT_ *Out) const { Out->x = left; Out->y = top; }
00904 void RightBottom(POINT_ *Out) const { Out->x = right; Out->y = bottom; }
00905
00907 void Extend(int d) { left -= d; top -= d; right += d; bottom += d; }
00909 int Width() const { return right - left; }
00911 int Height() const { return bottom - top; }
00913 float Diagonal() const { return sqrtf( (float)((right-left)*(right-left)) + (float)((bottom-top)*(bottom-top)) ); }
00915 int Field() const { return (right-left)*(bottom-top); }
00917 void SetWidth(int NewWidth) { right = left + NewWidth; }
00919 void SetHeight(int NewHeight) { bottom = top + NewHeight; }
00921 void SetSize(int NewWidth, int NewHeight) { right = left + NewWidth; bottom = top + NewHeight; }
00922
00923 void GetCenter(POINT_ *Out) const { Out->x = (left+right)/2; Out->y = (top+bottom)/2; }
00924 int GetCenterX() const { return (left+right)/2; }
00925 int GetCenterY() const { return (top+bottom)/2; }
00927 bool Empty() const { return left == 0 && top == 0 && right == 0 && bottom == 0; }
00929 void Clear() { left = top = right = bottom = 0; }
00930 };
00931
00932 extern const RECTI RECTI_ZERO;
00933
00935 struct RECTF
00936 {
00937 float left, top, right, bottom;
00938
00939 operator float * () { return &left; }
00940 operator const float * () const { return &left; }
00941
00942 RECTF() { }
00943 RECTF(float left, float top, float right, float bottom) : left(left), top(top), right(right), bottom(bottom) { }
00944 RECTF(const float *Arr) : left(Arr[0]), top(Arr[1]), right(Arr[2]), bottom(Arr[3]) { }
00945
00946 bool operator == (const RECTF &r) const { return left == r.left && top == r.top && right == r.right && bottom == r.bottom; }
00947 bool operator != (const RECTF &r) const { return left != r.left || top != r.top || right != r.right || bottom != r.bottom; }
00948
00949 RECTF operator + () const { return *this; }
00950 RECTF operator - () const { return RECTF(-right, -bottom, -left, -top); }
00951 RECTF operator + (const VEC2 &p) const { return RECTF(left+p.x, top+p.y, right+p.x, bottom+p.y); }
00952 RECTF operator - (const VEC2 &p) const { return RECTF(left-p.x, top-p.y, right-p.x, bottom-p.y); }
00953 RECTF operator * (float s) const { return RECTF(left*s, top*s, right*s, bottom*s); }
00954 RECTF operator * (const VEC2 &s) const { return RECTF(left*s.x, top*s.y, right*s.x, bottom*s.y); }
00955 RECTF & operator += (const VEC2 &p) { left += p.x; top += p.y; right += p.x; bottom += p.y; return *this; }
00956 RECTF & operator -= (const VEC2 &p) { left -= p.x; top -= p.y; right -= p.x; bottom -= p.y; return *this; }
00957 RECTF & operator *= (float s) { left *= s; top *= s; right *= s; bottom *= s; return *this; }
00958 RECTF & operator *= (const VEC2 &s) { left *= s.x; top *= s.y; right *= s.x; bottom *= s.y; return *this; }
00959
00960 bool IsValid() const { return left < right && top < bottom; }
00961 void Repair() { if (right < left) std::swap(left, right); if (bottom < top) std::swap(top, bottom); }
00962
00963 void LeftTop(VEC2 *Out) const { Out->x = left; Out->y = top; }
00964 void RightBottom(VEC2 *Out) const { Out->x = right; Out->y = bottom; }
00965
00967 void Extend(float d) { left -= d; top -= d; right += d; bottom += d; }
00969 float Width() const { return right - left; }
00971 float Height() const { return bottom - top; }
00973 float Diagonal() const { return sqrtf( (right-left)*(right-left) + (bottom-top)*(bottom-top) ); }
00975 float Field() const { return (right-left)*(bottom-top); }
00977 void SetWidth(float NewWidth) { right = left + NewWidth; }
00979 void SetHeight(float NewHeight) { bottom = top + NewHeight; }
00981 void SetSize(float NewWidth, float NewHeight) { right = left + NewWidth; bottom = top + NewHeight; }
00983 void GetCenter(VEC2 *Out) const { Out->x = (left+right)*0.5f; Out->y = (top+bottom)*0.5f; }
00984 float GetCenterX() const { return (left+right)*0.5f; }
00985 float GetCenterY() const { return (top+bottom)*0.5f; }
00987 bool Empty() const { return left == 0.0f && top == 0.0f && right == 0.0f && bottom == 0.0f; }
00989 void Clear() { left = top = right = bottom = 0.0f; }
00990 };
00991
00992 extern const RECTF RECTF_ZERO;
00993
00994 #ifdef WIN32
00996 template <> inline ::RECT & math_cast<::RECT, RECTI>(const RECTI &x) { return (::RECT&)(x); }
00998 template <> inline RECTI & math_cast<RECTI, ::RECT>(const ::RECT &x) { return (RECTI&)(x); }
00999 #endif
01000
01001 inline void swap(RECTI &r1, RECTI &r2)
01002 {
01003 std::swap(r1.left, r2.left); std::swap(r1.top, r2.top);
01004 std::swap(r1.right, r2.right); std::swap(r1.bottom, r2.bottom);
01005 }
01006
01007 inline void swap(RECTF &r1, RECTF &r2)
01008 {
01009 std::swap(r1.left, r2.left); std::swap(r1.top, r2.top);
01010 std::swap(r1.right, r2.right); std::swap(r1.bottom, r2.bottom);
01011 }
01012
01014 inline bool PointInRect(const POINT_ &p, const RECTI &r)
01015 {
01016 return
01017 (p.x >= r.left) &&
01018 (p.x <= r.right) &&
01019 (p.y >= r.top) &&
01020 (p.y <= r.bottom);
01021 }
01022 inline bool PointInRect(const VEC2 &p, const RECTF &r)
01023 {
01024 return
01025 (p.x >= r.left) &&
01026 (p.x <= r.right) &&
01027 (p.y >= r.top) &&
01028 (p.y <= r.bottom);
01029 }
01030
01032 inline bool RectInRect(const RECTI &sr, const RECTI &r)
01033 {
01034 return
01035 (sr.left >= r.left) &&
01036 (sr.right <= r.right) &&
01037 (sr.top >= r.top) &&
01038 (sr.bottom <= r.bottom);
01039 }
01040 inline bool RectInRect(const RECTF &sr, const RECTF &r)
01041 {
01042 return
01043 (sr.left >= r.left) &&
01044 (sr.right <= r.right) &&
01045 (sr.top >= r.top) &&
01046 (sr.bottom <= r.bottom);
01047 }
01048
01050 inline bool OverlapRect(const RECTI &r1, const RECTI &r2)
01051 {
01052 return
01053 (r1.left <= r2.right) &&
01054 (r1.right >= r2.left) &&
01055 (r1.top <= r2.bottom) &&
01056 (r1.bottom >= r2.top);
01057 }
01058 inline bool OverlapRect(const RECTF &r1, const RECTF &r2)
01059 {
01060 return
01061 (r1.left <= r2.right) &&
01062 (r1.right >= r2.left) &&
01063 (r1.top <= r2.bottom) &&
01064 (r1.bottom >= r2.top);
01065 }
01066
01068 inline bool Intersection(RECTI *Out, const RECTI &r1, const RECTI &r2)
01069 {
01070 *Out = RECTI(
01071 std::max(r1.left, r2.left),
01072 std::max(r1.top, r2.top),
01073 std::min(r1.right, r2.right),
01074 std::min(r1.bottom, r2.bottom));
01075 return Out->IsValid();
01076 }
01077 inline bool Intersection(RECTF *Out, const RECTF &r1, const RECTF &r2)
01078 {
01079 *Out = RECTF(
01080 std::max(r1.left, r2.left),
01081 std::max(r1.top, r2.top),
01082 std::min(r1.right, r2.right),
01083 std::min(r1.bottom, r2.bottom));
01084 return Out->IsValid();
01085 }
01086
01088 inline void Union(RECTI *Out, const RECTI &r1, const RECTI &r2)
01089 {
01090 Out->left = std::min(r1.left, r2.left);
01091 Out->top = std::min(r1.top, r2.top);
01092 Out->right = std::max(r1.right, r2.right);
01093 Out->bottom = std::max(r1.bottom, r2.bottom);
01094 }
01095 inline void Union(RECTF *Out, const RECTF &r1, const RECTF &r2)
01096 {
01097 Out->left = std::min(r1.left, r2.left);
01098 Out->top = std::min(r1.top, r2.top);
01099 Out->right = std::max(r1.right, r2.right);
01100 Out->bottom = std::max(r1.bottom, r2.bottom);
01101 }
01102
01104
01105
01106
01107
01111
01113
01117 struct BOX
01118 {
01119 VEC3 p1, p2;
01120
01121 BOX() { }
01122 BOX(const VEC3 &p1, const VEC3 &p2) : p1(p1), p2(p2) { }
01123 BOX(float p1x, float p1y, float p1z, float p2x, float p2y, float p2z) : p1(p1x, p1y, p1z), p2(p2x, p2y, p2z) { }
01124 BOX(const float *Arr) : p1(&Arr[0]), p2(&Arr[3]) { }
01125
01126 operator float * () { return &p1.x; }
01127 operator const float * () const { return &p1.x; }
01128
01129 bool operator == (const BOX &p) const { return p1 == p.p1 && p2 == p.p2; }
01130 bool operator != (const BOX &p) const { return p1 != p.p1 || p2 != p.p2; }
01131
01132 BOX operator + () const { return *this; }
01133 BOX operator - () const { return BOX(-p2, -p1); }
01134 BOX operator + (const VEC3 &v) const { return BOX(p1+v, p2+v); }
01135 BOX operator - (const VEC3 &v) const { return BOX(p1-v, p2-v); }
01136 BOX operator * (float f) const { return BOX(p1*f, p2*f); }
01137 BOX operator * (const VEC3 &s) const { return BOX(VEC3(p1.x*s.x, p1.y*s.y, p1.z*s.z), VEC3(p2.x*s.x, p2.y*s.y, p2.z*s.z)); }
01138 BOX & operator += (const VEC3 &v) { p1 += v; p2 += v; return *this; }
01139 BOX & operator -= (const VEC3 &v) { p1 -= v; p2 -= v; return *this; }
01140 BOX & operator *= (float f) { p1 *= f; p2 *= f; return *this; }
01141 BOX & operator *= (const VEC3 &s) { p1.x *= s.x; p1.y *= s.y; p1.z *= s.z; p2.x *= s.x; p2.y *= s.y; p2.z *= s.z; return *this; }
01142
01143 bool IsValid() { return Less(p1, p2); }
01144 void Repair() { if (p2.x < p1.x) std::swap(p1.x, p2.x); if (p2.y < p1.y) std::swap(p1.y, p2.y); if (p2.z < p1.z) std::swap(p1.z, p2.z); }
01145
01147 void Extend(float d) { p1.x -= d; p1.y -= d; p1.z -= d; p2.x += d; p2.y += d; p2.z += d; }
01149 void GetSize(VEC3 *Out) const { Out->x = p2.x-p1.x; Out->y = p2.y-p1.y; Out->z = p2.z-p1.z; }
01151 float GetCX() const { return p2.x - p1.x; }
01153 float GetCY() const { return p2.y - p1.y; }
01155 float GetCZ() const { return p2.z - p1.z; }
01157 void SetSize(const VEC3 &NewSize) { p2.x = p1.x + NewSize.x; p2.y = p1.y + NewSize.y; p2.z = p1.z + NewSize.z; }
01159 float Diagonal() const { return sqrtf( (p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y) + (p2.z-p1.z)*(p2.z-p1.z) ); }
01161 float Volume() const { return (p2.x-p1.x)*(p2.y-p1.y)*(p2.z-p1.z); }
01163 void CalcCenter(VEC3 *Out) const { Out->x = (p1.x+p2.x)*0.5f; Out->y = (p1.y+p2.y)*0.5f; Out->z = (p1.z+p2.z)*0.5f; }
01165 bool Empty() const { return *this == BOX(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); }
01167 void Clear() { *this = BOX(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); }
01169 void GetCorner(VEC3 *Out, int i) const
01170 {
01171 Out->x = (i & 1) ? p2.x : p1.x;
01172 Out->y = (i & 2) ? p2.y : p1.y;
01173 Out->z = (i & 4) ? p2.z : p1.z;
01174 }
01176
01183 void GetAllCorners(VEC3 *Out) const
01184 {
01185 Out[0] = VEC3(p1.x, p1.y, p1.z); Out[1] = VEC3(p2.x, p1.y, p1.z); Out[2] = VEC3(p1.x, p2.y, p1.z); Out[3] = VEC3(p2.x, p2.y, p1.z);
01186 Out[4] = VEC3(p1.x, p1.y, p2.z); Out[5] = VEC3(p2.x, p1.y, p2.z); Out[6] = VEC3(p1.x, p2.y, p2.z); Out[7] = VEC3(p2.x, p2.y, p2.z);
01187 }
01189 void AddInternalPoint(const VEC3 &p)
01190 {
01191 p1.x = std::min(p1.x, p.x); p1.y = std::min(p1.y, p.y); p1.z = std::min(p1.z, p.z);
01192 p2.x = std::max(p2.x, p.x); p2.y = std::max(p2.y, p.y); p2.z = std::max(p2.z, p.z);
01193 }
01195
01196 void AddInternalBox(const BOX &b)
01197 {
01198 p1.x = std::min(p1.x, b.p1.x); p1.y = std::min(p1.y, b.p1.y); p1.z = std::min(p1.z, b.p1.z);
01199 p2.x = std::max(p2.x, b.p2.x); p2.y = std::max(p2.y, b.p2.y); p2.z = std::max(p2.z, b.p2.z);
01200 }
01201 };
01202
01203 static const BOX ZERO;
01204
01205 inline void swap(BOX &b1, BOX &b2)
01206 {
01207 std::swap(b1.p1, b2.p1);
01208 std::swap(b1.p2, b2.p2);
01209 }
01210
01212 inline void Scale(BOX *Out, const BOX &b, float s)
01213 {
01214 Out->p1.x = b.p1.x * s; Out->p1.y = b.p1.y * s; Out->p1.z = b.p1.z * s;
01215 Out->p2.x = b.p2.x * s; Out->p2.y = b.p2.y * s; Out->p2.z = b.p2.z * s;
01216 }
01217
01219 inline void Scale(BOX *Out, const BOX &b, const VEC3 &s)
01220 {
01221 Out->p1.x = b.p1.x * s.x; Out->p1.y = b.p1.y * s.y; Out->p1.z = b.p1.z * s.z;
01222 Out->p2.x = b.p2.x * s.x; Out->p2.y = b.p2.y * s.y; Out->p2.z = b.p2.z * s.z;
01223 }
01224
01226 inline bool PointInBox(const VEC3 &p, const BOX &b)
01227 {
01228 return
01229 (p.x >= b.p1.x) && (p.x <= b.p2.x) &&
01230 (p.y >= b.p1.y) && (p.y <= b.p2.y) &&
01231 (p.z >= b.p1.z) && (p.z <= b.p2.z);
01232 }
01233
01235 inline bool BoxInBox(const BOX &sb, const BOX &b)
01236 {
01237 return
01238 (sb.p1.x >= b.p1.x) && (sb.p2.x <= b.p2.x) &&
01239 (sb.p1.y >= b.p1.y) && (sb.p2.y <= b.p2.y) &&
01240 (sb.p1.z >= b.p1.z) && (sb.p2.z <= b.p2.z);
01241 }
01242
01244 inline bool OverlapBox(const BOX &b1, const BOX &b2)
01245 {
01246 return
01247 (b1.p1.x <= b2.p2.x) && (b1.p2.x >= b2.p1.x) &&
01248 (b1.p1.y <= b2.p2.y) && (b1.p2.y >= b2.p1.y) &&
01249 (b1.p1.z <= b2.p2.z) && (b1.p2.z >= b2.p1.z);
01250 }
01251
01253 inline bool Intersection(BOX *Out, const BOX &b1, const BOX &b2)
01254 {
01255 *Out = BOX(
01256 VEC3(
01257 std::max(b1.p1.x, b2.p1.x),
01258 std::max(b1.p1.y, b2.p1.y),
01259 std::max(b1.p1.z, b2.p1.z)),
01260 VEC3(
01261 std::min(b1.p2.x, b2.p2.x),
01262 std::min(b1.p2.y, b2.p2.y),
01263 std::min(b1.p2.z, b2.p2.z)));
01264 return Out->IsValid();
01265 }
01266
01268 inline void Union(BOX *Out, const BOX &b1, const BOX &b2)
01269 {
01270 *Out = BOX(
01271 VEC3(
01272 std::min(b1.p1.x, b2.p1.x),
01273 std::min(b1.p1.y, b2.p1.y),
01274 std::min(b1.p1.z, b2.p1.z)),
01275 VEC3(
01276 std::max(b1.p2.x, b2.p2.x),
01277 std::max(b1.p2.y, b2.p2.y),
01278 std::max(b1.p2.z, b2.p2.z)));
01279 }
01280
01282
01283
01284
01285
01290
01292
01297 struct COLOR
01298 {
01299 union
01300 {
01302 uint4 ARGB;
01304 PACKED struct
01305 {
01306 uint1 B, G, R, A;
01307 };
01308 };
01309
01310 COLOR() { }
01311 COLOR(uint4 c) : ARGB(c) { }
01312 COLOR(unsigned long c) : ARGB((uint4)c) { }
01313 COLOR(uint1 R, uint1 G, uint1 B) : B(B), G(G), R(R), A(0xFF) { }
01314 COLOR(uint1 A, uint1 R, uint1 G, uint1 B) : B(B), G(G), R(R), A(A) { }
01315
01316 bool operator == (COLOR c) const { return ARGB == c.ARGB; }
01317 bool operator != (COLOR c) const { return ARGB != c.ARGB; }
01318
01319
01320 COLOR operator + () const { return *this; }
01321 COLOR operator - () const { return COLOR(~ARGB); }
01322
01323 COLOR operator + (const COLOR &c) const { return COLOR(safe_add(A, c.A), safe_add(R, c.R), safe_add(G, c.G), safe_add(B, c.B)); }
01324 COLOR operator - (const COLOR &c) const { return COLOR(safe_sub(A, c.A), safe_sub(R, c.R), safe_sub(G, c.G), safe_sub(B, c.B)); }
01325 COLOR & operator += (const COLOR &c) { A = safe_add(A, c.A); R = safe_add(R, c.R); G = safe_add(G, c.G); B = safe_add(B, c.B); return *this; }
01326 COLOR & operator -= (const COLOR &c) { A = safe_sub(A, c.A); R = safe_sub(R, c.R); G = safe_sub(G, c.G); B = safe_sub(B, c.B); return *this; }
01327
01328
01329 COLOR operator * (float s) const { return COLOR( (uint1)(minmax(0, (int)(A*s), 255)), (uint1)(minmax(0, (int)(R*s), 255)), (uint1)(minmax(0, (int)(G*s), 255)), (uint1)(minmax(0, (int)(B*s), 255)) ); }
01330 COLOR operator / (float s) const { return COLOR( (uint1)(minmax(0, (int)(A/s), 255)), (uint1)(minmax(0, (int)(R/s), 255)), (uint1)(minmax(0, (int)(G/s), 255)), (uint1)(minmax(0, (int)(B/s), 255)) ); }
01331 COLOR & operator *= (float s) { A = (uint1)(minmax(0, (int)(A*s), 255)); R = (uint1)(minmax(0, (int)(R*s), 255)); G = (uint1)(minmax(0, (int)(G*s), 255)); B = (uint1)(minmax(0, (int)(B*s), 255)); return *this; }
01332 COLOR & operator /= (float s) { A = (uint1)(minmax(0, (int)(A/s), 255)); R = (uint1)(minmax(0, (int)(R/s), 255)); G = (uint1)(minmax(0, (int)(G/s), 255)); B = (uint1)(minmax(0, (int)(B/s), 255)); return *this; }
01333
01334 COLOR operator * (const COLOR &c) const { return COLOR( (uint1)(((int)A*(int)c.A)/255), (uint1)(((int)R*(int)c.R)/255), (uint1)(((int)G*(int)c.G)/255), (uint1)(((int)B*(int)c.B)/255) ); }
01335 COLOR & operator *= (const COLOR &c) { A = (uint1)(((int)A*(int)c.A)/255); R = (uint1)(((int)R*(int)c.R)/255); G = (uint1)(((int)G*(int)c.G)/255); B = (uint1)(((int)B*(int)c.B)/255); return *this; }
01336 };
01337
01338 extern const COLOR COLOR_TRANSPARENT_;
01339 extern const COLOR COLOR_BLACK;
01340 extern const COLOR COLOR_GRAY;
01341 extern const COLOR COLOR_SILVER;
01342 extern const COLOR COLOR_WHITE;
01343 extern const COLOR COLOR_FUCHSIA;
01344 extern const COLOR COLOR_RED;
01345 extern const COLOR COLOR_ORANGE;
01346 extern const COLOR COLOR_YELLOW;
01347 extern const COLOR COLOR_LIME;
01348 extern const COLOR COLOR_AQUA;
01349 extern const COLOR COLOR_BLUE;
01350 extern const COLOR COLOR_PURPLE;
01351 extern const COLOR COLOR_MAROON;
01352 extern const COLOR COLOR_OLIVE;
01353 extern const COLOR COLOR_GREEN;
01354 extern const COLOR COLOR_TEAL;
01355
01357
01362 struct COLORF
01363 {
01364 float R, G, B, A;
01365
01366 COLORF() { }
01367 COLORF(float R, float G, float B) : R(R), G(G), B(B), A(1.0f) { }
01368 COLORF(float A, float R, float G, float B) : R(R), G(G), B(B), A(A) { }
01369 COLORF(const float *Arr) : R(Arr[0]), G(Arr[1]), B(Arr[2]), A(Arr[3]) { }
01370
01371 operator float * () { return &R; }
01372 operator const float * () const { return &R; }
01373
01374 bool operator == (const COLORF &c) const { return A == c.A && R == c.R && G == c.G && B == c.B; }
01375 bool operator != (const COLORF &c) const { return A != c.A || R != c.R || G != c.G || B != c.B; }
01376
01377
01378 COLORF operator + () const { return *this; }
01379 COLORF operator - () const { return COLORF(1.0f-A, 1.0f-R, 1.0f-G, 1.0f-B); }
01380
01381 COLORF operator + (const COLORF &c) const { return COLORF(A+c.A, R+c.R, G+c.G, B+c.B); }
01382 COLORF operator - (const COLORF &c) const { return COLORF(A-c.A, R-c.R, G-c.G, B-c.B); }
01383 COLORF & operator += (const COLORF &c) { A += c.A; R += c.R; G += c.G; B += c.B; return *this; }
01384 COLORF & operator -= (const COLORF &c) { A -= c.A; R -= c.R; G -= c.G; B -= c.B; return *this; }
01385
01386 COLORF operator * (float s) const { return COLORF(A*s, R*s, G*s, B*s); }
01387 COLORF operator / (float s) const { return COLORF(A/s, R/s, G/s, B/s); }
01388 COLORF & operator *= (float s) { A *= s; R *= s; G *= s; B *= s; return *this; }
01389 COLORF & operator /= (float s) { A /= s; R /= s; G /= s; B /= s; return *this; }
01390
01391 COLORF operator * (const COLORF &c) const { return COLORF(A*c.A, R*c.R, G*c.G, B*c.B); }
01392 COLORF & operator *= (const COLORF &c) { A *= c.A; R *= c.R; G *= c.G; B *= c.B; return *this; }
01393
01395 bool IsValid() const { return (A >= 0.0f && A <= 1.0f) && (R >= 0.0f && R <= 1.0f) && (G >= 0.0f && G <= 1.0f) && (B >= 0.0f && B <= 1.0f); }
01397 void Repair()
01398 {
01399 A = minmax(0.0f, A, 1.0f); R = minmax(0.0f, R, 1.0f);
01400 G = minmax(0.0f, G, 1.0f); B = minmax(0.0f, B, 1.0f);
01401 }
01402 };
01403
01404 inline void swap(COLORF &c1, COLORF &c2)
01405 {
01406 std::swap(c1.A, c2.A); std::swap(c1.R, c2.R);
01407 std::swap(c1.G, c2.G); std::swap(c1.B, c2.B);
01408 }
01409
01410 extern const COLORF COLORF_TRANSPARENT_;
01411 extern const COLORF COLORF_BLACK;
01412 extern const COLORF COLORF_GRAY;
01413 extern const COLORF COLORF_SILVER;
01414 extern const COLORF COLORF_WHITE;
01415 extern const COLORF COLORF_FUCHSIA;
01416 extern const COLORF COLORF_RED;
01417 extern const COLORF COLORF_ORANGE;
01418 extern const COLORF COLORF_YELLOW;
01419 extern const COLORF COLORF_LIME;
01420 extern const COLORF COLORF_AQUA;
01421 extern const COLORF COLORF_BLUE;
01422 extern const COLORF COLORF_PURPLE;
01423 extern const COLORF COLORF_MAROON;
01424 extern const COLORF COLORF_OLIVE;
01425 extern const COLORF COLORF_GREEN;
01426 extern const COLORF COLORF_TEAL;
01427
01428 inline COLORF operator * (float s, const COLORF &c) { return COLORF(c.A*s, c.R*s, c.G*s, c.B*s); }
01429 inline COLORF operator / (float s, const COLORF &c) { return COLORF(c.A/s, c.R/s, c.G/s, c.B/s); }
01430
01431 inline COLOR operator * (float s, const COLOR &c) { return COLOR( (uint1)(minmax(0, (int)(c.A*s), 255)), (uint1)(minmax(0, (int)(c.R*s), 255)), (uint1)(minmax(0, (int)(c.G*s), 255)), (uint1)(minmax(0, (int)(c.B*s), 255)) ); }
01432 inline COLOR operator / (float s, const COLOR &c) { return COLOR( (uint1)(minmax(0, (int)(c.A/s), 255)), (uint1)(minmax(0, (int)(c.R/s), 255)), (uint1)(minmax(0, (int)(c.G/s), 255)), (uint1)(minmax(0, (int)(c.B/s), 255)) ); }
01433
01434 template <> inline uint4 & math_cast<uint4, COLOR>(const COLOR &x) { return (uint4&)(x); }
01435 template <> inline unsigned long & math_cast<unsigned long, COLOR>(const COLOR &x) { return (unsigned long&)(x); }
01436 template <> inline COLOR & math_cast<COLOR, uint4>(const uint4 &x) { return (COLOR&)(x); }
01437 template <> inline COLOR & math_cast<COLOR, unsigned long>(const unsigned long &x) { return (COLOR&)(x); }
01438
01439 #ifdef USE_DIRECTX
01440 template <> inline D3DXCOLOR & math_cast<D3DXCOLOR, COLORF>(const COLORF &x) { return (D3DXCOLOR&)(x); }
01441 template <> inline COLORF & math_cast<COLORF, D3DXCOLOR>(const D3DXCOLOR &x) { return (COLORF&)(x); }
01442 #endif
01443
01445 inline void ColorToColorf(COLORF *Out, COLOR c)
01446 {
01447 Out->R = c.R / 255.0f;
01448 Out->G = c.G / 255.0f;
01449 Out->B = c.B / 255.0f;
01450 Out->A = c.A / 255.0f;
01451 }
01453 inline COLOR ColorfToColor(const COLORF &c)
01454 {
01455 return COLOR(
01456 (uint1)(minmax(0.0f, c.A, 1.0f)*255.0f+0.5f),
01457 (uint1)(minmax(0.0f, c.R, 1.0f)*255.0f+0.5f),
01458 (uint1)(minmax(0.0f, c.G, 1.0f)*255.0f+0.5f),
01459 (uint1)(minmax(0.0f, c.B, 1.0f)*255.0f+0.5f));
01460 }
01461
01463
01469 void ColorToStr(tstring *Out, COLOR Color, char Format = 'X');
01470 void ColorToStr(tstring *Out, const COLORF &Color, char Format = 'F');
01472
01480 bool StrToColor(COLOR *Out, const tstring &Str);
01481 bool StrToColor(COLORF *Out, const tstring &Str);
01482
01483 inline void Add(COLORF *Out, const COLORF &c1, const COLORF &c2)
01484 {
01485 Out->A = c1.A + c2.A; Out->R = c1.R + c2.R;
01486 Out->G = c1.G + c2.G; Out->B = c1.B + c2.B;
01487 }
01488 inline void Sub(COLORF *Out, const COLORF &c1, const COLORF &c2)
01489 {
01490 Out->A = c1.A - c2.A; Out->R = c1.R - c2.R;
01491 Out->G = c1.G - c2.G; Out->B = c1.B - c2.B;
01492 }
01493 inline void Mul(COLORF *Out, const COLORF &c1, const COLORF &c2)
01494 {
01495 Out->A = c1.A * c2.A; Out->R = c1.R * c2.R;
01496 Out->G = c1.G * c2.G; Out->B = c1.B * c2.B;
01497 }
01498 inline void Mul(COLORF *Out, const COLORF &c, float s)
01499 {
01500 Out->A = c.A * s; Out->R = c.R * s;
01501 Out->G = c.G * s; Out->B = c.B * s;
01502 }
01503 inline void Div(COLORF *Out, const COLORF &c, float s)
01504 {
01505 Out->A = c.A / s; Out->R = c.R / s;
01506 Out->G = c.G / s; Out->B = c.B / s;
01507 }
01508 inline void Negative(COLORF *Out, const COLORF &c)
01509 {
01510 Out->A = 1.0f - c.A; Out->R = 1.0f - c.R;
01511 Out->G = 1.0f - c.G; Out->B = 1.0f - c.B;
01512 }
01513
01515 inline COLOR ARGB_ABGR(COLOR color)
01516 {
01517 return COLOR(
01518 (color.ARGB & 0xFF00FF00) |
01519 ((color.ARGB >> 16) & 0x000000FF) |
01520 ((color.ARGB & 0x000000FF) << 16)
01521 );
01522 }
01523
01524 inline void Lerp(COLORF *Out, const COLORF &c1, const COLORF &c2, float t)
01525 {
01526 Out->A = Lerp(c1.A, c2.A, t);
01527 Out->R = Lerp(c1.R, c2.R, t);
01528 Out->G = Lerp(c1.G, c2.G, t);
01529 Out->B = Lerp(c1.B, c2.B, t);
01530 }
01531 inline COLOR Lerp(COLOR c1, COLOR c2, float t)
01532 {
01533 return COLOR(
01534 (uint1)(minmax(0, (int)(c1.A + t*((float)c2.A-(float)c1.A)), 255)),
01535 (uint1)(minmax(0, (int)(c1.R + t*((float)c2.R-(float)c1.R)), 255)),
01536 (uint1)(minmax(0, (int)(c1.G + t*((float)c2.G-(float)c1.G)), 255)),
01537 (uint1)(minmax(0, (int)(c1.B + t*((float)c2.B-(float)c1.B)), 255)) );
01538 }
01539
01541
01545 void HsbToRgb(COLORF *Out, float hue, float saturation, float brightness);
01547 void RgbToHsb(float *OutHue, float *OutSaturation, float *OutBrightness, const COLORF &Color);
01548
01550
01551 inline void ColorRainbow(COLORF *Out, float t)
01552 {
01553 HsbToRgb(Out, t*0.75f, 1.0f, 1.0f);
01554 }
01555
01557 inline float ColorToGrayscale(const COLORF &c)
01558 {
01559 return 0.299f * c.R + 0.587f * c.G + 0.114f * c.B;
01560 }
01561 inline float ColorToGrayscale(COLOR &c)
01562 {
01563 return 0.299f * (c.R/255.0f) + 0.587f * (c.G/255.0f) + 0.114f * (c.B/255.0f);
01564 }
01565
01567 inline void GrayscaleToColor(COLORF *Out, float t)
01568 {
01569 Out->A = 1.0f;
01570 Out->R = Out->G = Out->B = t;
01571 }
01572 inline void GrayscaleToColor(COLOR *Out, float t)
01573 {
01574 Out->A = 255;
01575 Out->R = Out->G = Out->B = (uint1)(t*255.0f);
01576 }
01577
01579
01583 inline void AdjustContrast(COLORF *Color, float t)
01584 {
01585 Color->R = 0.5f + t * (Color->R - 0.5f);
01586 Color->G = 0.5f + t * (Color->G - 0.5f);
01587 Color->B = 0.5f + t * (Color->B - 0.5f);
01588 }
01589
01591
01595 inline void AdjustSaturation(COLORF *Color, float t)
01596 {
01597 float gray = ColorToGrayscale(*Color);
01598 Color->R = gray + t * (Color->R - gray);
01599 Color->G = gray + t * (Color->G - gray);
01600 Color->B = gray + t * (Color->B - gray);
01601 }
01602
01604 inline COLOR VectorToColor(const VEC3 &v)
01605 {
01606 int R = minmax(0, (int)(127.0f * v.x + 128.0f), 255);
01607 int G = minmax(0, (int)(127.0f * v.y + 128.0f), 255);
01608 int B = minmax(0, (int)(127.0f * v.z + 128.0f), 255);
01609 return COLOR((uint4)((R << 16) | (G << 8) | B));
01610 }
01611
01613 inline void ColorToVector(VEC3 *Out, COLOR color)
01614 {
01615 const float o = 1.0f / 127.0f;
01616 Out->x = (((color.ARGB >> 16) & 0xFF) - 128.0f) * o;
01617 Out->y = (((color.ARGB >> 8) & 0xFF) - 128.0f) * o;
01618 Out->z = (((color.ARGB ) & 0xFF) - 128.0f) * o;
01619 }
01620
01622 inline uint ColorDistance(COLOR Color1, COLOR Color2)
01623 {
01624 int rd = (int)Color1.R - (int)Color2.R;
01625 int gd = (int)Color1.G - (int)Color2.G;
01626 int bd = (int)Color1.B - (int)Color2.B;
01627 return (uint)(rd*rd + gd*gd + bd*bd);
01628 }
01629
01631
01632
01633
01634
01637
01638 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
01639 typedef D3DXPLANE PLANE;
01640 #else
01642
01651 struct PLANE
01652 {
01653 float a, b, c, d;
01654
01655 PLANE() { }
01656 PLANE(float a, float b, float c, float d) : a(a), b(b), c(c), d(d) { }
01657 PLANE(const float *Arr) : a(Arr[0]), b(Arr[1]), c(Arr[2]), d(Arr[3]) { }
01658
01659 operator float * () { return &a; }
01660 operator const float * () const { return &a; }
01661
01662 bool operator == (const PLANE &p) const { return a == p.a && b == p.b && c == p.c && d == p.d; }
01663 bool operator != (const PLANE &p) const { return a != p.a || b != p.b || c != p.c || d != p.d; }
01664
01665 PLANE operator + () const { return *this; }
01667 PLANE operator - () const { return PLANE(-a, -b, -c, -d); }
01668
01669 PLANE operator * (float s) const { return PLANE(a*s, b*s, c*s, d*s); }
01670 PLANE operator / (float s) const { return PLANE(a/s, b/s, c/s, d/s); }
01671 PLANE & operator *= (float s) { a *= s; b *= s; c *= s; d *= s; return *this; }
01672 PLANE & operator /= (float s) { a /= s; b /= s; c /= s; d /= s; return *this; }
01673 };
01674 inline PLANE operator * (float s, const PLANE &p) { return PLANE(p.a*s, p.b*s, p.c*s, p.d*s); }
01675 #endif
01676
01677 extern const PLANE PLANE_ZERO;
01678 extern const PLANE PLANE_POSITIVE_X;
01679 extern const PLANE PLANE_POSITIVE_Y;
01680 extern const PLANE PLANE_POSITIVE_Z;
01681 extern const PLANE PLANE_NEGATIVE_X;
01682 extern const PLANE PLANE_NEGATIVE_Y;
01683 extern const PLANE PLANE_NEGATIVE_Z;
01684
01685 inline void swap(PLANE &p1, PLANE &p2)
01686 {
01687 std::swap(p1.a, p2.a); std::swap(p1.b, p2.b);
01688 std::swap(p1.c, p2.c); std::swap(p1.d, p2.d);
01689 }
01690
01692 inline VEC3 & GetPlaneNormal(PLANE &Plane) { return (VEC3&)Plane.a; }
01694 inline const VEC3 & GetPlaneNormal(const PLANE &Plane) { return (const VEC3&)Plane.a; }
01695
01697
01698 inline void GetPlaneMemberPoint(VEC3 *Out, const PLANE &Plane)
01699 {
01700 *Out = GetPlaneNormal(Plane) * -Plane.d;
01701 }
01702
01704
01708 inline void RecalculatePlaneD(PLANE *Plane, const VEC3 &p)
01709 {
01710 Plane->d = -Dot(GetPlaneNormal(*Plane), p);
01711 }
01712
01714 inline bool PlaneEqual(const PLANE &p1, const PLANE &p2) {
01715 return float_equal(p1.a, p2.a) && float_equal(p1.b, p2.b) && float_equal(p1.c, p2.c) && float_equal(p1.d, p2.d);
01716 }
01717
01719
01722 inline void PointsToPlane(PLANE *Out, const VEC3 &p1, const VEC3 &p2, const VEC3 &p3) {
01723 Cross(&GetPlaneNormal(*Out), p2-p1, p3-p1);
01724 Normalize(&GetPlaneNormal(*Out));
01725 Out->d = -Dot(p1, GetPlaneNormal(*Out));
01726 }
01728
01729 inline void PointNormalToPlane(PLANE *Out, const VEC3 &Point, const VEC3 &Normal) {
01730 Out->a = Normal.x; Out->b = Normal.y; Out->c = Normal.z;
01731 Out->d = -Dot(Normal, Point);
01732 }
01733
01735 inline void Mul(PLANE *Out, const PLANE &p, float s)
01736 {
01737 Out->a = p.a * s; Out->b = p.b * s;
01738 Out->c = p.c * s; Out->d = p.d * s;
01739 }
01740 inline void Div(PLANE *Out, const PLANE &p, float s)
01741 {
01742 Out->a = p.a / s; Out->b = p.b / s;
01743 Out->c = p.c / s; Out->d = p.d / s;
01744 }
01745
01747
01749 inline float Dot(const PLANE &p, const VEC4 &pt)
01750 {
01751 return p.a*pt.x + p.b*pt.y + p.c*pt.z + p.d*pt.w;
01752 }
01753
01755
01757 inline float DotCoord(const PLANE &p, const VEC3 &pt)
01758 {
01759 return p.a*pt.x + p.b*pt.y + p.c*pt.z + p.d;
01760 }
01761
01763
01764 inline float DotNormal(const PLANE &p, const VEC3 &v)
01765 {
01766 return p.a*v.x + p.b*v.y + p.c*v.z;
01767 }
01768
01770
01772 inline void Normalize(PLANE *Out, const PLANE &p)
01773 {
01774 float nlsq = 1.0f / Length(GetPlaneNormal(p));
01775 Out->a = p.a * nlsq; Out->b = p.b * nlsq;
01776 Out->c = p.c * nlsq; Out->d = p.d * nlsq;
01777 }
01779 inline void Normalize(PLANE *p)
01780 {
01781 float nlsq = 1.0f / Length(GetPlaneNormal(*p));
01782 p->a *= nlsq; p->b *= nlsq;
01783 p->c *= nlsq; p->d *= nlsq;
01784 }
01785
01787
01788
01789
01790
01793
01795
01804 struct LINE2D
01805 {
01806 float a, b, c;
01807
01808 LINE2D() { }
01809 LINE2D(float a, float b, float c) : a(a), b(b), c(c) { }
01810 LINE2D(const VEC2 &Normal, float c) : a(Normal.x), b(Normal.y), c(c) { }
01811 LINE2D(const float *Arr) : a(Arr[0]), b(Arr[1]), c(Arr[2]) { }
01812
01813 operator float * () { return &a; }
01814 operator const float * () const { return &a; }
01815
01816 VEC2 & GetNormal() { return (VEC2&)a; }
01817 const VEC2 & GetNormal() const { return (VEC2&)a; }
01818
01819 bool operator == (const LINE2D &L) const { return a == L.a && b == L.b && c == L.c; }
01820 bool operator != (const LINE2D &L) const { return a != L.a || b != L.b || c != L.c; }
01821
01822 LINE2D operator + () const { return *this; }
01824 LINE2D operator - () const { return LINE2D(-a, -b, -c); }
01825
01826
01827 LINE2D operator * (float s) const { return LINE2D(a*s, b*s, c*s); }
01828 LINE2D operator / (float s) const { return LINE2D(a/s, b/s, c/s); }
01829 LINE2D & operator *= (float s) { a *= s; b *= s; c *= s; return *this; }
01830 LINE2D & operator /= (float s) { a /= s; b /= s; c /= s; return *this; }
01831
01833 void GetTangent(VEC2 *Out) { Out->x = b; Out->y = -a; }
01834
01836
01837 void GetMemberPoint(VEC2 *Out)
01838 {
01839 *Out = GetNormal() * -c;
01840 }
01841
01843
01846 void RecalculateD(const VEC2 &p)
01847 {
01848 c = -Dot(GetNormal(), p);
01849 }
01850 };
01851 inline LINE2D operator * (float s, const LINE2D &p) { return LINE2D(p.a*s, p.b*s, p.c*s); }
01852 inline LINE2D operator / (float s, const LINE2D &p) { return LINE2D(p.a/s, p.b/s, p.c/s); }
01853
01854 extern const LINE2D LINE2D_ZERO;
01855 extern const LINE2D LINE2D_POSITIVE_X;
01856 extern const LINE2D LINE2D_NEGATIVE_X;
01857 extern const LINE2D LINE2D_POSITIVE_Y;
01858 extern const LINE2D LINE2D_NEGATIVE_Y;
01859
01861 inline bool LineEqual(const LINE2D &p1, const LINE2D &p2) {
01862 return float_equal(p1.a, p2.a) && float_equal(p1.b, p2.b) && float_equal(p1.c, p2.c);
01863 }
01864
01865 inline void swap(LINE2D &p1, LINE2D &p2)
01866 {
01867 std::swap(p1.a, p2.a); std::swap(p1.b, p2.b); std::swap(p1.c, p2.c);
01868 }
01869
01871
01872 inline void PointsToLine(LINE2D *Out, const VEC2 &p1, const VEC2 &p2) {
01873 Out->a = p1.y - p2.y;
01874 Out->b = p2.x - p1.x;
01875 Out->c = - Out->a * p1.x - Out->b * p1.y;
01876 }
01877
01879 inline void PointNormalToLine(LINE2D *Out, const VEC2 &Point, const VEC2 &Normal) {
01880 Out->a = Normal.x; Out->b = Normal.y;
01881 Out->c = -Dot(Normal, Point);
01882 }
01883
01885 inline bool LinesParallel(const LINE2D &L1, const LINE2D &L2) {
01886 return FLOAT_ALMOST_ZERO(L1.a*L2.b - L2.a*L1.b);
01887 }
01888
01890 inline bool LinesPerpedicular(const LINE2D &L1, const LINE2D &L2) {
01891 return FLOAT_ALMOST_ZERO(L1.a*L2.a + L1.b*L2.b);
01892 }
01893
01895
01896 inline float Dot(const LINE2D &L1, const LINE2D &L2) {
01897 return L1.a*L2.a + L1.b*L2.b;
01898 }
01899
01901
01902 inline float LineDistance(const LINE2D &L1, const LINE2D &L2) {
01903 return L1.c - L2.c;
01904 }
01905
01907
01908 bool LinesIntersection(VEC2 *Out, const LINE2D &L1, const LINE2D &L2);
01909
01911 bool PointsColinear(const VEC2 &p1, const VEC2 &p2, const VEC2 &p3);
01912
01914 inline void Mul(LINE2D *Out, const LINE2D &p, float s) {
01915 Out->a = p.a * s; Out->b = p.b * s; Out->c = p.c * s;
01916 }
01917 inline void Div(LINE2D *Out, const LINE2D &p, float s) {
01918 Out->a = p.a / s; Out->b = p.b / s; Out->c = p.c / s;
01919 }
01920
01922
01924 inline float Dot(const LINE2D &p, const VEC3 &pt) {
01925 return p.a*pt.x + p.b*pt.y + p.c*pt.z;
01926 }
01927
01929
01930 inline float DotCoord(const LINE2D &p, const VEC2 &pt) {
01931 return p.a*pt.x + p.b*pt.y + p.c;
01932 }
01933
01935
01936 inline float DotNormal(const LINE2D &p, const VEC2 &v) {
01937 return p.a*v.x + p.b*v.y;
01938 }
01939
01941
01943 inline void Normalize(LINE2D *Out, const LINE2D &p) {
01944 float nlsq = 1.f / Length(p.GetNormal());
01945 Out->a = p.a * nlsq; Out->b = p.b * nlsq; Out->c = p.c * nlsq;
01946 }
01948 inline void Normalize(LINE2D *p) {
01949 float nlsq = 1.f / Length(p->GetNormal());
01950 p->a *= nlsq; p->b *= nlsq; p->c *= nlsq;
01951 }
01952
01954
01955
01956
01957
01960
01961 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
01962 typedef D3DXMATRIX MATRIX;
01963 #else
01965
01970 struct MATRIX
01971 {
01972 union
01973 {
01974 struct
01975 {
01976 float _11, _12, _13, _14;
01977 float _21, _22, _23, _24;
01978 float _31, _32, _33, _34;
01979 float _41, _42, _43, _44;
01980 };
01981 float m[4][4];
01982 };
01983
01984 MATRIX() { }
01985 MATRIX(float _11, float _12, float _13, float _14, float _21, float _22, float _23, float _24, float _31, float _32, float _33, float _34, float _41, float _42, float _43, float _44) : _11(_11), _12(_12), _13(_13), _14(_14), _21(_21), _22(_22), _23(_23), _24(_24), _31(_31), _32(_32), _33(_33), _34(_34), _41(_41), _42(_42), _43(_43), _44(_44) { }
01986 MATRIX(const float *Array) : _11(Array[0]), _12(Array[1]), _13(Array[2]), _14(Array[3]), _21(Array[4]), _22(Array[5]), _23(Array[6]), _24(Array[7]), _31(Array[8]), _32(Array[9]), _33(Array[10]), _34(Array[11]), _41(Array[12]), _42(Array[13]), _43(Array[14]), _44(Array[15]) { }
01987
01988 operator float * () { return &_11; }
01989 operator const float * () const { return &_11; }
01990
01991 bool operator == (const MATRIX &m) const { return _11 == m._11 && _12 == m._12 && _13 == m._13 && _14 == m._14 && _21 == m._21 && _22 == m._22 && _23 == m._23 && _24 == m._24 && _31 == m._31 && _32 == m._32 && _33 == m._33 && _34 == m._34 && _41 == m._41 && _42 == m._42 && _43 == m._43 && _44 == m._44; }
01992 bool operator != (const MATRIX &m) const { return _11 != m._11 || _12 != m._12 || _13 != m._13 || _14 != m._14 || _21 != m._21 || _22 != m._22 || _23 != m._23 || _24 != m._24 || _31 != m._31 || _32 != m._32 || _33 != m._33 || _34 != m._34 || _41 != m._41 || _42 != m._42 || _43 != m._43 || _44 != m._44; }
01993
01994 float & operator () (unsigned Row, unsigned Col) { return m[Row][Col]; }
01995 float operator () (unsigned Row, unsigned Col) const { return m[Row][Col]; }
01996
01997 MATRIX operator + () const { return *this; }
01998 MATRIX operator - () const;
01999 MATRIX operator + (const MATRIX &m) const;
02000 MATRIX operator - (const MATRIX &m) const;
02001 MATRIX operator * (const MATRIX &m) const
02002 {
02003 return MATRIX(
02004 _11 * m._11 + _12 * m._21 + _13 * m._31 + _14 * m._41,
02005 _11 * m._12 + _12 * m._22 + _13 * m._32 + _14 * m._42,
02006 _11 * m._13 + _12 * m._23 + _13 * m._33 + _14 * m._43,
02007 _11 * m._14 + _12 * m._24 + _13 * m._34 + _14 * m._44,
02008
02009 _21 * m._11 + _22 * m._21 + _23 * m._31 + _24 * m._41,
02010 _21 * m._12 + _22 * m._22 + _23 * m._32 + _24 * m._42,
02011 _21 * m._13 + _22 * m._23 + _23 * m._33 + _24 * m._43,
02012 _21 * m._14 + _22 * m._24 + _23 * m._34 + _24 * m._44,
02013
02014 _31 * m._11 + _32 * m._21 + _33 * m._31 + _34 * m._41,
02015 _31 * m._12 + _32 * m._22 + _33 * m._32 + _34 * m._42,
02016 _31 * m._13 + _32 * m._23 + _33 * m._33 + _34 * m._43,
02017 _31 * m._14 + _32 * m._24 + _33 * m._34 + _34 * m._44,
02018
02019 _41 * m._11 + _42 * m._21 + _43 * m._31 + _44 * m._41,
02020 _41 * m._12 + _42 * m._22 + _43 * m._32 + _44 * m._42,
02021 _41 * m._13 + _42 * m._23 + _43 * m._33 + _44 * m._43,
02022 _41 * m._14 + _42 * m._24 + _43 * m._34 + _44 * m._44);
02023 }
02024 MATRIX & operator += (const MATRIX &m);
02025 MATRIX & operator -= (const MATRIX &m);
02026 MATRIX & operator *= (const MATRIX &m);
02027
02028 MATRIX operator * (float s) const;
02029 MATRIX operator / (float s) const;
02030 MATRIX & operator *= (float s);
02031 MATRIX & operator /= (float s);
02032 };
02033 #endif
02034
02035 extern const MATRIX MATRIX_ZERO;
02036 extern const MATRIX MATRIX_IDENTITY;
02037
02038 void MatrixToStr(tstring *Out, const MATRIX &m);
02039 bool StrToMatrix(MATRIX *Out, const tstring &Str);
02040
02041 inline void swap(MATRIX &m1, MATRIX &m2)
02042 {
02043 std::swap(m1._11, m2._11); std::swap(m1._12, m2._12); std::swap(m1._13, m2._13); std::swap(m1._14, m2._14);
02044 std::swap(m1._21, m2._21); std::swap(m1._22, m2._22); std::swap(m1._23, m2._23); std::swap(m1._24, m2._24);
02045 std::swap(m1._31, m2._31); std::swap(m1._32, m2._32); std::swap(m1._33, m2._33); std::swap(m1._34, m2._34);
02046 std::swap(m1._41, m2._41); std::swap(m1._42, m2._42); std::swap(m1._43, m2._43); std::swap(m1._44, m2._44);
02047 }
02048
02050 bool MatrixEqual(const MATRIX &m1, const MATRIX &m2);
02052 void Minus(MATRIX *m);
02054 void Add(MATRIX *Out, const MATRIX &m1, const MATRIX &m2);
02056 void Sub(MATRIX *Out, const MATRIX &m1, const MATRIX &m2);
02058 void Mul(MATRIX *Out, const MATRIX &m1, const MATRIX &m2);
02060 void Mul(MATRIX *m, float s);
02062 void Div(MATRIX *m, float s);
02063
02065 void Transform(VEC4 *Out, const VEC2 &v, const MATRIX &m);
02067 void Transform(VEC2 *Out, const VEC2 &v, const MATRIX &m);
02069 void TransformCoord(VEC2 *Out, const VEC2 &v, const MATRIX &m);
02071 void TransformNormal(VEC2 *Out, const VEC2 &v, const MATRIX &m);
02072
02074 void Transform(VEC4 *Out, const VEC3 &v, const MATRIX &m);
02076
02077 void Transform(VEC3 *Out, const VEC3 &v, const MATRIX &m);
02079
02080 void TransformCoord(VEC3 *Out, const VEC3 &v, const MATRIX &m);
02082
02083 void TransformNormal(VEC3 *Out, const VEC3 &v, const MATRIX &m);
02084
02086 void TransformArray(VEC3 OutPoints[], const VEC3 InPoints[], size_t PointCount, const MATRIX &M);
02087 void TransformArray(VEC3 InOutPoints[], size_t PointCount, const MATRIX &M);
02088 void TransformNormalArray(VEC3 OutPoints[], const VEC3 InPoints[], size_t PointCount, const MATRIX &M);
02089 void TransformNormalArray(VEC3 InOutPoints[], size_t PointCount, const MATRIX &M);
02090 void TransformCoordArray(VEC3 OutPoints[], const VEC3 InPoints[], size_t PointCount, const MATRIX &M);
02091 void TransformCoordArray(VEC3 InOutPoints[], size_t PointCount, const MATRIX &M);
02092
02094
02095 void Transform(VEC4 *Out, const VEC4 &v, const MATRIX &m);
02096
02098
02100 void Transform(PLANE *Out, const PLANE &p, const MATRIX &m);
02102 void TransformRay(VEC3 *OutOrigin, VEC3 *OutDir, const VEC3 &RayOrigin, const VEC3 &RayDir, const MATRIX &m);
02103
02105 void TransformBox(BOX *Out, const BOX &In, const MATRIX &M);
02107
02108 void TransformBoxCoord(BOX *Out, const BOX &In, const MATRIX &M);
02109
02111
02112 void AxesToMatrix(MATRIX *Out, const VEC3 &AxisX, const VEC3 &AxisY, const VEC3 &AxisZ);
02114
02115 void AxesToMatrixTranslation(MATRIX *Out, const VEC3 &Origin, const VEC3 &AxisX, const VEC3 &AxisY, const VEC3 &AxisZ);
02116
02118
02119 void LookAtLH(MATRIX *Out, const VEC3 &Eye, const VEC3 &Forward, const VEC3 &Up);
02120 void LookAtRH(MATRIX *Out, const VEC3 &Eye, const VEC3 &Forward, const VEC3 &Up);
02121
02123 void Identity(MATRIX *Out);
02125 void Translation(MATRIX *Out, float x, float y, float z);
02126 void Translation(MATRIX *Out, const VEC3 &v);
02128 void Scaling(MATRIX *Out, float sx, float sy, float sz);
02129 void Scaling(MATRIX *Out, const VEC3 &sv);
02130 void Scaling(MATRIX *Out, float s);
02132
02134 void ScalingAxis(MATRIX *Out, const VEC3 &n, float k);
02135
02137 void Rotation2D(MATRIX *Out, float Angle);
02139 void RotationX(MATRIX *Out, float Angle);
02141 void RotationY(MATRIX *Out, float Angle);
02143 void RotationZ(MATRIX *Out, float Angle);
02145 void RotationAxisLH(MATRIX *Out, const VEC3 &Axis, float Angle);
02146 inline void RotationAxisRH(MATRIX *Out, const VEC3 &Axis, float Angle) { RotationAxisLH(Out, Axis, -Angle); }
02147
02149
02156 void RotationYawPitchRoll(MATRIX *Out, float Yaw, float Pitch, float Roll);
02157 void RotationYawPitchRoll(MATRIX *Out, const VEC3 &EulerAngles);
02159
02160 void RotationYawPitchRollInv(MATRIX *Out, float Yaw, float Pitch, float Roll);
02161 void RotationYawPitchRollInv(MATRIX *Out, const VEC3 &EulerAngles);
02162
02163
02164
02165
02167
02168 void OrthoLH(MATRIX *Out, float Width, float Height, float ZNear, float ZFar);
02169 void OrthoRH(MATRIX *Out, float Width, float Height, float ZNear, float ZFar);
02170 void OrthoOffCenterLH(MATRIX *Out, float Left, float Right, float Bottom, float Top, float ZNear, float ZFar);
02171 void OrthoOffCenterRH(MATRIX *Out, float Left, float Right, float Bottom, float Top, float ZNear, float ZFar);
02173
02177 void PerspectiveLH(MATRIX *Out, float Width, float Height, float ZNear, float ZFar);
02178 void PerspectiveRH(MATRIX *Out, float Width, float Height, float ZNear, float ZFar);
02179 void PerspectiveFovLH(MATRIX *Out, float FovY, float Aspect, float ZNear, float ZFar);
02180 void PerspectiveFovRH(MATRIX *Out, float FovY, float Aspect, float ZNear, float ZFar);
02181 void PerspectiveOffCenterLH(MATRIX *Out, float Left, float Right, float Bottom, float Top, float ZNear, float ZFar);
02182 void PerspectiveOffCenterRH(MATRIX *Out, float Left, float Right, float Bottom, float Top, float ZNear, float ZFar);
02184 void PerspectiveFovLH_Inf(MATRIX *Out, float FovY, float Aspect, float ZNear);
02186
02187 void MatrixShadow(MATRIX *Out, const VEC4 &Light, const PLANE &Plane);
02189
02190 void MatrixReflect(MATRIX *Out, const PLANE &p);
02191
02193 void Transpose(MATRIX *m);
02195 void Lerp(MATRIX *Out, const MATRIX &m1, const MATRIX &m2, float t);
02197 float Det(const MATRIX &m);
02199 bool Inverse(MATRIX *Out, const MATRIX &m);
02200
02202
02203
02204
02205
02208
02209 #if defined(USE_DIRECTX) && !defined(DOXYGEN)
02210 typedef D3DXQUATERNION QUATERNION;
02211 #else
02213
02218 struct QUATERNION
02219 {
02220 float x, y, z, w;
02221
02222 QUATERNION() { }
02223 QUATERNION(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
02224 QUATERNION(const float *Array) : x(Array[0]), y(Array[1]), z(Array[2]), w(Array[3]) { }
02225
02226 operator float * () { return &x; }
02227 operator const float * () const { return &x; }
02228
02229 bool operator == (const QUATERNION &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; }
02230 bool operator != (const QUATERNION &v) const { return x != v.x || y != v.y || z != v.z || w != v.w; }
02231
02232 QUATERNION operator + () const { return *this; }
02233 QUATERNION operator - () const { return QUATERNION(-x, -y, -z, -w); }
02234 QUATERNION operator + (const QUATERNION &q) const { return QUATERNION(x+q.x, y+q.y, z+q.z, w+q.w); }
02235 QUATERNION operator - (const QUATERNION &q) const { return QUATERNION(x-q.x, y-q.y, z-q.z, w-q.w); }
02236 QUATERNION operator * (const QUATERNION &q) const { return QUATERNION(w*q.x + x*q.w + y*q.z - z*q.y, w*q.y + y*q.w + z*q.x - x*q.z, w*q.z + z*q.w + x*q.y - y*q.x, w*q.w - x*q.x - y*q.y - z*q.z); }
02237 QUATERNION & operator += (const QUATERNION &q) { x += q.x; y += q.y; z += q.z; w += q.w; return *this; }
02238 QUATERNION & operator -= (const QUATERNION &q) { x -= q.x; y -= q.y; z -= q.z; w -= q.w; return *this; }
02239 QUATERNION & operator *= (const QUATERNION &q) { QUATERNION R; R.x = w*q.x + x*q.w + y*q.z - z*q.y; R.y = w*q.y + y*q.w + z*q.x - x*q.z; R.z = w*q.z + z*q.w + x*q.y - y*q.x; R.w = w*q.w - x*q.x - y*q.y - z*q.z; *this = R; return *this; }
02240 QUATERNION & operator *= (float v) { x *= v; y *= v; z *= v; w *= v; return *this; }
02241 QUATERNION & operator /= (float v) { x /= v; y /= v; z /= v; w /= v; return *this; }
02242 };
02243 inline QUATERNION operator * (const QUATERNION pt, float v) { return QUATERNION(pt.x*v, pt.y*v, pt.z*v, pt.w*v); }
02244 inline QUATERNION operator / (const QUATERNION pt, float v) { return QUATERNION(pt.x/v, pt.y/v, pt.z/v, pt.w/v); }
02245 inline QUATERNION operator * (float v, const QUATERNION pt) { return QUATERNION(pt.x*v, pt.y*v, pt.z*v, pt.w*v); }
02246 inline QUATERNION operator / (float v, const QUATERNION pt) { return QUATERNION(pt.x/v, pt.y/v, pt.z/v, pt.w/v); }
02247 #endif
02248
02249 extern const QUATERNION QUATERNION_ZERO;
02250 extern const QUATERNION QUATERNION_IDENTITY;
02251
02252 inline void swap(QUATERNION &v1, QUATERNION &v2)
02253 {
02254 std::swap(v1.x, v2.x);
02255 std::swap(v1.y, v2.y);
02256 std::swap(v1.z, v2.z);
02257 std::swap(v1.w, v2.w);
02258 }
02259
02261 inline float CalcQuaternionAngle(const QUATERNION &Q) { return safe_acos(Q.w) * 2.0f; }
02263 void CalcQuaternionAxis(VEC3 *Out, const QUATERNION &Q);
02264
02266 inline bool QuaternionEqual(const QUATERNION &q1, const QUATERNION &q2) {
02267 return float_equal(q1.x, q2.x) && float_equal(q1.y, q2.y) && float_equal(q1.z, q2.z) && float_equal(q1.w, q2.w);
02268 }
02269
02271 void Minus(QUATERNION *q);
02272 inline void Minus(QUATERNION *Out, const QUATERNION &q) { *Out = q; Minus(Out); }
02274 void Add(QUATERNION *Out, const QUATERNION &q1, const QUATERNION &q2);
02275 void Sub(QUATERNION *Out, const QUATERNION &q1, const QUATERNION &q2);
02276 void Mul(QUATERNION *Out, const QUATERNION &q1, const QUATERNION &q2);
02278 void Mul(QUATERNION *q, float v);
02279 void Div(QUATERNION *q, float v);
02280 inline void Mul(QUATERNION *Out, const QUATERNION &q, float v) { *Out = q; Mul(Out, v); }
02281 inline void Div(QUATERNION *Out, const QUATERNION &q, float v) { *Out = q; Div(Out, v); }
02282
02284 void RotationMatrixToQuaternion(QUATERNION *Out, const MATRIX &RotationMatrix);
02286 void QuaternionToRotationMatrix(MATRIX *Out, const QUATERNION &q);
02288
02293 void QuaternionTransform(VEC3 *Out, const VEC3 &p, const QUATERNION &q);
02295 void EulerAnglesToQuaternionO2I(QUATERNION *Out, float Yaw, float Pitch, float Roll);
02297 void EulerAnglesToQuaternionI2O(QUATERNION *Out, float Yaw, float Pitch, float Roll);
02299 void QuaternionO2IToEulerAngles(float *Yaw, float *Pitch, float *Roll, const QUATERNION &q);
02301 void QuaternionI2OToEulerAngles(float *Yaw, float *Pitch, float *Roll, const QUATERNION &q);
02302
02304 void QuaternionRotationX(QUATERNION *Out, float a);
02306 void QuaternionRotationY(QUATERNION *Out, float a);
02308 void QuaternionRotationZ(QUATERNION *Out, float a);
02310 void AxisToQuaternion(QUATERNION *Out, const VEC3 &Axis, float Angle);
02311
02313
02314 void QuaternionDiff(QUATERNION *Out, const QUATERNION &a, const QUATERNION &b);
02316 void Conjugate(QUATERNION *q);
02317 inline void Conjugate(QUATERNION *Out, const QUATERNION &q) { *Out = q; Conjugate(Out); }
02319 void Inverse(QUATERNION *Out, const QUATERNION &q);
02321 void Normalize(QUATERNION *Out, const QUATERNION &q);
02322 void Normalize(QUATERNION *InOut);
02324 float Dot(const QUATERNION &q1, const QUATERNION &q2);
02326 float LengthSq(const QUATERNION &q);
02328 float Length(const QUATERNION &q);
02329 void Log(QUATERNION *Out, const QUATERNION &q);
02330 void Exp(QUATERNION *Out, const QUATERNION &q);
02332
02333 void Pow(QUATERNION *InOut, float t);
02334 inline void Pow(QUATERNION *Out, const QUATERNION &q, float t) { *Out = q; Pow(Out, t); }
02336 void Lerp(QUATERNION *Out, const QUATERNION &q1, const QUATERNION &q2, float t);
02338
02339 void Slerp(QUATERNION *Out, const QUATERNION &q0, const QUATERNION &q1, float t);
02341 void Squad(QUATERNION *Out, const QUATERNION &Q1, const QUATERNION &A, const QUATERNION &B, const QUATERNION &C, float t);
02343 void SquadSetup(QUATERNION *OutA, QUATERNION *OutB, QUATERNION *OutC, const QUATERNION &Q0, const QUATERNION &Q1, const QUATERNION &Q2, const QUATERNION &Q3);
02344
02346
02347
02348
02349
02352
02353 struct FRUSTUM_PLANES;
02354 struct FRUSTUM_POINTS;
02355
02357
02363 struct FRUSTUM_PLANES
02364 {
02369 static const size_t PLANE_LEFT = 0;
02370 static const size_t PLANE_RIGHT = 1;
02371 static const size_t PLANE_TOP = 2;
02372 static const size_t PLANE_BOTTOM = 3;
02373 static const size_t PLANE_NEAR = 4;
02374 static const size_t PLANE_FAR = 5;
02376
02377 PLANE Planes[6];
02378
02380 FRUSTUM_PLANES() { }
02382 FRUSTUM_PLANES(const MATRIX &WorldViewProj) { Set(WorldViewProj); }
02384 FRUSTUM_PLANES(const FRUSTUM_POINTS &FrustumPoints) { Set(FrustumPoints); }
02386 void Set(const MATRIX &WorldViewProj);
02387 void Set(const FRUSTUM_POINTS &FrustumPoints);
02389 void Normalize();
02390
02391 PLANE & operator [] (size_t Index) { return Planes[Index]; }
02392 const PLANE & operator [] (size_t Index) const { return Planes[Index]; }
02393 };
02394
02396
02401 struct FRUSTUM_POINTS
02402 {
02406 static const size_t NEAR_LEFT_BOTTOM = 0;
02407 static const size_t NEAR_RIGHT_BOTTOM = 1;
02408 static const size_t NEAR_LEFT_TOP = 2;
02409 static const size_t NEAR_RIGHT_TOP = 3;
02410 static const size_t FAR_LEFT_BOTTOM = 4;
02411 static const size_t FAR_RIGHT_BOTTOM = 5;
02412 static const size_t FAR_LEFT_TOP = 6;
02413 static const size_t FAR_RIGHT_TOP = 7;
02415
02416 VEC3 Points[8];
02417
02419 FRUSTUM_POINTS() { }
02421 FRUSTUM_POINTS(const FRUSTUM_PLANES &FrustumPlanes) { Set(FrustumPlanes); }
02423 FRUSTUM_POINTS(const MATRIX &WorldViewProjInv) { Set(WorldViewProjInv); }
02425 void Set(const FRUSTUM_PLANES &FrustumPlanes);
02426 void Set(const MATRIX &WorldViewProjInv);
02427
02428 VEC3 & operator [] (size_t Index) { return Points[Index]; }
02429 const VEC3 & operator [] (size_t Index) const { return Points[Index]; }
02430
02432 void CalcCenter(VEC3 *Out) const;
02434 void CalcBoundingBox(BOX *Box) const;
02436
02437 void CalcBoundingSphere(VEC3 *SphereCenter, float *SphereRadius) const;
02438 };
02439
02441
02448 class FRUSTUM_RADAR
02449 {
02450 private:
02451 VEC3 m_Eye;
02452 VEC3 m_Forward;
02453 VEC3 m_Up;
02454 VEC3 m_Right;
02455 float m_RFactor;
02456 float m_UFactor;
02457 float m_RSphereFactor;
02458 float m_USphereFactor;
02459 float m_ZNear;
02460 float m_ZFar;
02461
02462 public:
02464 FRUSTUM_RADAR() { }
02466 FRUSTUM_RADAR(const VEC3 &Eye, const VEC3 &Forward, const VEC3 &Up, const VEC3 &Right, float FovY, float Aspect, float ZNear, float ZFar) { Set(Eye, Forward, Up, Right, FovY, Aspect, ZNear, ZFar); }
02467
02472 const VEC3 & GetEye() const { return m_Eye; }
02473 const VEC3 & GetForward() const { return m_Forward; }
02474 const VEC3 & GetUp() const { return m_Up; }
02475 const VEC3 & GetRight() const { return m_Right; }
02476 float GetZNear() const { return m_ZNear; }
02477 float GetZFar() const { return m_ZFar; }
02479
02484 float GetRFactor() const { return m_RFactor; }
02485 float GetUFactor() const { return m_UFactor; }
02486 float GetRSphereFactor() const { return m_RSphereFactor; }
02487 float GetUSphereFactor() const { return m_USphereFactor; }
02489
02492 void SetEye (const VEC3 &Eye) { m_Eye = Eye; }
02493 void SetForward(const VEC3 &Forward) { m_Forward = Forward; }
02494 void SetUp (const VEC3 &Up) { m_Up = Up; }
02495 void SetRight (const VEC3 &Right) { m_Right = Right; }
02496 void SetZNear(float ZNear) { m_ZNear = ZNear; }
02497 void SetZFor (float ZFar) { m_ZFar = ZFar; }
02498 void SetFovAndAspect(float FovY, float Aspect);
02500
02502 void Set(const VEC3 &Eye, const VEC3 &Forward, const VEC3 &Up, const VEC3 &Right, float FovY, float Aspect, float ZNear, float ZFar) { SetProjection(FovY, Aspect, ZNear, ZFar); SetView(Eye, Forward, Up, Right); }
02504 void SetProjection(float FovY, float Aspect, float ZNear, float ZFar);
02506 void SetView(const VEC3 &Eye, const VEC3 &Forward, const VEC3 &Up, const VEC3 &Right);
02507 };
02508
02510
02511
02512
02513
02516
02518 float CapsuleVolume(const VEC3 &p1, const VEC3 &p2, float R);
02520 void RandomPointInCapsule(VEC3 *Out, const VEC3 &p1, const VEC3 &p2, float R, RandomGenerator &Rand);
02521 void RandomPointInCapsule(VEC3 *Out, const VEC3 &p1, const VEC3 &p2, float R);
02522
02524
02525
02526
02527
02528
02534
02535 template <typename T>
02536 inline void SmoothCD_T(T *InOutPos, const T &Dest, T *InOutVel, float SmoothTime, float TimeDelta)
02537 {
02538 assert(0 && "SmoothCD_T for invalid template type.");
02539 }
02540
02541 template <>
02542 inline void SmoothCD_T<float>(float *InOutPos, const float &Dest, float *InOutVel, float SmoothTime, float TimeDelta)
02543 {
02544 SmoothCD(InOutPos, Dest, InOutVel, SmoothTime, TimeDelta);
02545 }
02546
02547 template <>
02548 inline void SmoothCD_T<VEC2>(VEC2 *InOutPos, const VEC2 &Dest, VEC2 *InOutVel, float SmoothTime, float TimeDelta)
02549 {
02550 SmoothCD(&InOutPos->x, Dest.x, &InOutVel->x, SmoothTime, TimeDelta);
02551 SmoothCD(&InOutPos->y, Dest.y, &InOutVel->y, SmoothTime, TimeDelta);
02552 }
02553
02554 template <>
02555 inline void SmoothCD_T<VEC3>(VEC3 *InOutPos, const VEC3 &Dest, VEC3 *InOutVel, float SmoothTime, float TimeDelta)
02556 {
02557 SmoothCD(&InOutPos->x, Dest.x, &InOutVel->x, SmoothTime, TimeDelta);
02558 SmoothCD(&InOutPos->y, Dest.y, &InOutVel->y, SmoothTime, TimeDelta);
02559 SmoothCD(&InOutPos->z, Dest.z, &InOutVel->z, SmoothTime, TimeDelta);
02560 }
02561
02562 template <typename T>
02563 class SmoothCD_obj
02564 {
02565 public:
02566 T Pos;
02567 T Dest;
02568 T Vel;
02569 float SmoothTime;
02570
02572 SmoothCD_obj() { }
02574 SmoothCD_obj(const T &Pos, float SmoothTime, const T &Vel) : Pos(Pos), Dest(Pos), Vel(Vel), SmoothTime(SmoothTime) { }
02576 void Set(const T &Pos, const T &Vel) { this->Pos = Pos; this->Dest = Pos; this->Vel = Vel; }
02577
02579 void Update(const T &Dest, float TimeDelta) {
02580 this->Dest = Dest;
02581 SmoothCD_T<T>(&Pos, Dest, &Vel, SmoothTime, TimeDelta);
02582 }
02583 };
02584
02586
02587
02588
02594
02596 void SphericalToCartesian(VEC3 *Out, float Yaw, float Pitch, float R);
02597
02611 void CartesianToSpherical(float *OutYaw, float *OutPitch, float *OutR, const VEC3 &Pos);
02612
02614
02615
02617
02623 void ConvexHull2D(std::vector<VEC2> *OutPoints, const VEC2 InPoints[], size_t InPointCount);
02624
02625
02626
02629
02631
02635 float ClosestPointOnLine(const VEC3 &p, const VEC3 &RayOrig, const VEC3 &RayDir);
02637
02638 float PointToLineDistance(const VEC3 &P, const VEC3 &LineOrig, const VEC3 &LineDir);
02640
02641 bool PointOnLine(const VEC3 &P, const VEC3 &LineOrig, const VEC3 &LineDir);
02643
02644 float PointToLine(const VEC3 &P, const VEC3 &LineOrig, const VEC3 &LineDir);
02646
02647 bool PointInLineSegment(const VEC3 &P, const VEC3 &SegmentBeg, const VEC3 &SegmentEnd);
02649 void ClosestPointOnLineSegment(VEC3 *Out, const VEC3 &P, const VEC3 &P1, const VEC3 &P2);
02651
02652 void ClosestPointInBox(VEC3 *Out, const BOX &Box, const VEC3 &p);
02654
02655 float PointToBoxDistance(const VEC3 &p, const BOX &box);
02657 bool PointInSphere(const VEC3 &p, const VEC3 &SphereCenter, float SphereRadius);
02659
02660 float PointToSphereDistance(const VEC3 &p, const VEC3 &SphereCenter, float SphereRadius);
02662
02664 void ClosestPointOnSphere(VEC3 *Out, const VEC3 &SphereCenter, float SphereRadius, const VEC3 &p);
02666
02667 bool PointOnPlane(const VEC3 &p, const PLANE &plane);
02669 void ClosestPointOnPlane(VEC3 *Out, const PLANE &Plane, const VEC3 &p);
02671 bool PointOnTriangle(const VEC3 &point, const VEC3 &pa, const VEC3 &pb, const VEC3 &pc);
02673 bool PointInFrustum(const VEC3 &p, const FRUSTUM_PLANES &Frustum);
02674 bool PointInFrustum(const VEC3 &p, const FRUSTUM_RADAR &Frustum);
02676
02681 bool ClosestPointsOnLines(float *OutT1, float *OutT2, const VEC3 &RayOrig1, const VEC3 &RayDir1, const VEC3 &RayOrig2, const VEC3 &RayDir2);
02683
02687 bool RayToBox(float *OutT, const VEC3 &RayOrig, const VEC3 &RayDir, const BOX &Box);
02689
02693 bool RayToSphere(const VEC3 &RayOrig, const VEC3 &RayDir, const VEC3 &SphereCenter, float SphereRadius, float *OutT);
02695
02699 bool RayToPlane(const VEC3 &RayOrig, const VEC3 &RayDir, const PLANE &Plane, float *OutT, float *OutVD);
02701
02704 bool RayToTriangle(
02705 const VEC3 &RayOrig, const VEC3 &RayDir,
02706 const VEC3 &p0, const VEC3 &p1, const VEC3 &p2,
02707 bool BackfaceCulling,
02708 float *OutT);
02710 bool RayToFrustum(const VEC3 &RayOrig, const VEC3 &RayDir, const FRUSTUM_PLANES &Frustum, float *t_near, float *t_far);
02712 bool SphereToBox(const VEC3 &SphereCenter, float SphereRadius, const BOX &Box);
02714 bool SphereInBox(const VEC3 &SphereCenter, float SphereRadius, const BOX &Box);
02716 bool BoxInSphere(const BOX &Box, const VEC3 &SphereCenter, float SphereRadius);
02718 bool PlaneToBox(const PLANE &plane, const BOX &box);
02720
02725 int ClassifyBoxToPlane(const PLANE &plane, const BOX &box);
02727 bool TriangleInBox(const VEC3 &p1, const VEC3 &p2, const VEC3 &p3, const BOX &Box);
02729
02731 bool TriangleToBox(const VEC3 &p1, const VEC3 &p2, const VEC3 &p3, const BOX &Box, const PLANE *OptTrianglePlane = NULL);
02733
02734 bool BoxToFrustum_Fast(const BOX &Box, const FRUSTUM_PLANES &Frustum);
02736
02739 bool BoxToFrustum(const BOX &Box, const FRUSTUM_PLANES &FrustumPlanes, const FRUSTUM_POINTS *OptFrustumPoints = NULL);
02740 bool BoxToFrustum(const BOX &Box, const FRUSTUM_RADAR &Frustum);
02742 bool BoxInFrustum(const BOX &Box, const FRUSTUM_PLANES &Frustum);
02744 bool SphereToSphere(const VEC3 &Center1, float Radius1, const VEC3 &Center2, float Radius2);
02746
02747 bool SphereToPlane(const VEC3 &SphereCenter, float SphereRadius, const PLANE &Plane);
02749
02754 int ClassifySphereToPlane(const VEC3 &SphereCenter, float SphereRadius, const PLANE &Plane);
02756
02757 bool SphereToFrustum_Fast(const VEC3 &SphereCenter, float SphereRadius, const FRUSTUM_PLANES &Frustum);
02759
02761 bool SphereToFrustum(
02762 const VEC3 &SphereCenter, float SphereRadius,
02763 const FRUSTUM_PLANES &FrustumPlanes, const FRUSTUM_POINTS *OptFrustumPoints = NULL);
02765
02769 bool SphereToFrustum(const VEC3 &SphereCenter, float SphereRadius, const FRUSTUM_RADAR &Frustum);
02771 bool SphereInFrustum(const VEC3 &SphereCenter, float SphereRadius, const FRUSTUM_PLANES &Frustum);
02773
02775 bool Intersect2Planes(const PLANE &Plane1, const PLANE &Plane2, VEC3 *LineOrig, VEC3 *LineDir);
02777 bool Intersect3Planes(const PLANE &P1, const PLANE &P2, const PLANE &P3, VEC3 *OutP);
02779 bool PlaneToTriangle(const PLANE &Plane, const VEC3 &p0, const VEC3 &p1, const VEC3 &p2);
02781
02786 int ClassifyPlaneToTriangle(const PLANE &Plane, const VEC3 &p0, const VEC3 &p1, const VEC3 &p2);
02788 int ClassifyFrustumToPlane(const FRUSTUM_POINTS &Frustum, const PLANE &Plane);
02790 bool IntersectLines(const VEC2 &p1, const VEC2 &p2, const VEC2 &p3, const VEC2 &p4);
02792
02793 bool TriangleToTriangle(
02794 const VEC3 &V0,const VEC3 &V1,const VEC3 &V2,
02795 const VEC3 &U0,const VEC3 &U1,const VEC3 &U2);
02797 bool TriangleInFrustum(const VEC3 &t1, const VEC3 &t2, const VEC3 &t3, const FRUSTUM_PLANES &Frustum);
02799
02801 bool TriangleToFrustum(
02802 const VEC3 &t1, const VEC3 &t2, const VEC3 &t3, const PLANE *OptTrianglePlane,
02803 const FRUSTUM_PLANES &FrustumPlanes, const FRUSTUM_POINTS *OptFrustumPoints);
02805 bool FrustumToFrustum(
02806 const FRUSTUM_PLANES &Frustum1_Planes, const FRUSTUM_POINTS &Frustum1_Points,
02807 const FRUSTUM_PLANES &Frustum2_Planes, const FRUSTUM_POINTS &Frustum2_Points);
02809
02811 bool PointInPolygon(const VEC2 &Point, const VEC2 PolygonPoints[], uint PolygonPointCount);
02813
02816 bool RayToPolygon(const VEC3 &RayOrig, const VEC3 &RayDir, const VEC3 PolygonPoints[], uint PolygonPointCount, bool BackfaceCulling, float *OutT);
02817
02819
02825 bool SweptSphereToPlane(const VEC3 &SphereCenter, float SphereRadius, const VEC3 &SphereSweepDir, const PLANE &Plane, float *OutT0, float *OutT1);
02827
02831 bool SweptSphereToFrustum(const VEC3 &SphereCenter, float SphereRadius, const VEC3 &SphereSweepDir, const FRUSTUM_PLANES &Frustum);
02833
02840 bool SweptSphereToSphere(
02841 const VEC3 &SphereCenter1, float SphereRadius1,
02842 const VEC3 &SphereCenter2, float SphereRadius2,
02843 const VEC3 &SphereSweepDir1,
02844 float *OutT1, float *OutT2);
02846
02854 bool SweptBoxToBox(const BOX &Box1, const BOX &Box2, const VEC3 &SweepDirBox1, float *OutT);
02855
02857
02858
02859
02861
02862 void SphereBoundingPoints(VEC3 *OutSphereCenter, float *OutSphereRadius, const VEC3 Points[], size_t PointCount);
02864 void BoxBoundingPoints(BOX *box, const VEC3 points[], size_t PointCount);
02866 void BoxBoundingSphere(VEC3 *SphereCenter, float *SphereRadius, const BOX &Box);
02868 void SphereBoundingBox(BOX *Out, const VEC3 &SphereCenter, float SphereRadius);
02870
02871 void BoxBoundingSpheres(BOX *OutBox, const VEC3 SpheresCenter[], const float SpheresRadius[], size_t SphereCount);
02872
02874 void RandomPointInUnitSphere(VEC3 *Out, RandomGenerator &Rand);
02875 void RandomPointInUnitSphere(VEC3 *Out);
02877 void RandomPointInUnitCircle(VEC2 *Out, RandomGenerator &Rand);
02878 void RandomPointInUnitCircle(VEC2 *Out);
02879
02880
02881
02884
02885 extern const float POISSON_DISC_1D[];
02886 const uint4 POISSON_DISC_1D_COUNT = 100;
02887
02888 extern const VEC2 POISSON_DISC_2D[];
02889 const uint4 POISSON_DISC_2D_COUNT = 100;
02890
02891 extern const VEC3 POISSON_DISC_3D[];
02892 const uint4 POISSON_DISC_3D_COUNT = 100;
02893
02895
02896
02898
02899
02900 }
02901
02902
02903
02904
02905
02908
02909 template <>
02910 struct SthToStr_obj<common::POINT_>
02911 {
02912 void operator () (tstring *Str, const common::POINT_ &Sth)
02913 {
02914 *Str = common::Format(_T("#,#")) % Sth.x % Sth.y;
02915 }
02916 static inline bool IsSupported() { return true; }
02917 };
02918
02919 template <>
02920 struct StrToSth_obj<common::POINT_>
02921 {
02922 bool operator () (common::POINT_ *Sth, const tstring &Str)
02923 {
02924 size_t CommaPos = Str.find(_T(','));
02925 if (CommaPos == tstring::npos) return false;
02926 if (!StrToSth<int>(&Sth->x, Str.substr(0, CommaPos))) return false;
02927 if (!StrToSth<int>(&Sth->y, Str.substr(CommaPos+1))) return false;
02928 return true;
02929 }
02930 static inline bool IsSupported() { return true; }
02931 };
02932
02933 template <>
02934 struct SthToStr_obj<common::VEC2>
02935 {
02936 void operator () (tstring *Str, const common::VEC2 &Sth)
02937 {
02938 *Str = common::Format(_T("#,#")) % Sth.x % Sth.y;
02939 }
02940 static inline bool IsSupported() { return true; }
02941 };
02942
02943 template <>
02944 struct StrToSth_obj<common::VEC2>
02945 {
02946 bool operator () (common::VEC2 *Sth, const tstring &Str)
02947 {
02948 size_t CommaPos = Str.find(_T(','));
02949 if (CommaPos == tstring::npos) return false;
02950 if (!StrToSth<float>(&Sth->x, Str.substr(0, CommaPos))) return false;
02951 if (!StrToSth<float>(&Sth->y, Str.substr(CommaPos+1))) return false;
02952 return true;
02953 }
02954 static inline bool IsSupported() { return true; }
02955 };
02956
02957 template <>
02958 struct SthToStr_obj<common::VEC3>
02959 {
02960 void operator () (tstring *Str, const common::VEC3 &Sth)
02961 {
02962 *Str = common::Format(_T("#,#,#")) % Sth.x % Sth.y % Sth.z;
02963 }
02964 static inline bool IsSupported() { return true; }
02965 };
02966
02967 template <>
02968 struct StrToSth_obj<common::VEC3>
02969 {
02970 bool operator () (common::VEC3 *Sth, const tstring &Str)
02971 {
02972 size_t CommaPos1 = Str.find(_T(','));
02973 if (CommaPos1 == tstring::npos) return false;
02974 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
02975 if (CommaPos2 == tstring::npos) return false;
02976 if (!StrToSth<float>(&Sth->x, Str.substr(0, CommaPos1))) return false;
02977 if (!StrToSth<float>(&Sth->y, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
02978 if (!StrToSth<float>(&Sth->z, Str.substr(CommaPos2+1))) return false;
02979 return true;
02980 }
02981 static inline bool IsSupported() { return true; }
02982 };
02983
02984 template <>
02985 struct SthToStr_obj<common::VEC4>
02986 {
02987 void operator () (tstring *Str, const common::VEC4 &Sth)
02988 {
02989 *Str = common::Format(_T("#,#,#,#")) % Sth.x % Sth.y % Sth.z % Sth.w;
02990 }
02991 static inline bool IsSupported() { return true; }
02992 };
02993
02994 template <>
02995 struct StrToSth_obj<common::VEC4>
02996 {
02997 bool operator () (common::VEC4 *Sth, const tstring &Str)
02998 {
02999 size_t CommaPos1 = Str.find(_T(','));
03000 if (CommaPos1 == tstring::npos) return false;
03001 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03002 if (CommaPos2 == tstring::npos) return false;
03003 size_t CommaPos3 = Str.find(_T(','), CommaPos2+1);
03004 if (CommaPos3 == tstring::npos) return false;
03005 if (!StrToSth<float>(&Sth->x, Str.substr(0, CommaPos1))) return false;
03006 if (!StrToSth<float>(&Sth->y, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03007 if (!StrToSth<float>(&Sth->z, Str.substr(CommaPos2+1, CommaPos3-(CommaPos2+1)))) return false;
03008 if (!StrToSth<float>(&Sth->w, Str.substr(CommaPos3+1))) return false;
03009 return true;
03010 }
03011 static inline bool IsSupported() { return true; }
03012 };
03013
03014 template <>
03015 struct SthToStr_obj<common::RECTI>
03016 {
03017 void operator () (tstring *Str, const common::RECTI &Sth)
03018 {
03019 *Str = common::Format(_T("#,#,#,#")) % Sth.left % Sth.top % Sth.right % Sth.bottom;
03020 }
03021 static inline bool IsSupported() { return true; }
03022 };
03023
03024 template <>
03025 struct StrToSth_obj<common::RECTI>
03026 {
03027 bool operator () (common::RECTI *Sth, const tstring &Str)
03028 {
03029 size_t CommaPos1 = Str.find(_T(','));
03030 if (CommaPos1 == tstring::npos) return false;
03031 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03032 if (CommaPos2 == tstring::npos) return false;
03033 size_t CommaPos3 = Str.find(_T(','), CommaPos2+1);
03034 if (CommaPos3 == tstring::npos) return false;
03035 if (!StrToSth<int>(&Sth->left, Str.substr(0, CommaPos1))) return false;
03036 if (!StrToSth<int>(&Sth->top, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03037 if (!StrToSth<int>(&Sth->right, Str.substr(CommaPos2+1, CommaPos3-(CommaPos2+1)))) return false;
03038 if (!StrToSth<int>(&Sth->bottom, Str.substr(CommaPos3+1))) return false;
03039 return true;
03040 }
03041 static inline bool IsSupported() { return true; }
03042 };
03043
03044 template <>
03045 struct SthToStr_obj<common::RECTF>
03046 {
03047 void operator () (tstring *Str, const common::RECTF &Sth)
03048 {
03049 *Str = common::Format(_T("#,#,#,#")) % Sth.left % Sth.top % Sth.right % Sth.bottom;
03050 }
03051 static inline bool IsSupported() { return true; }
03052 };
03053
03054 template <>
03055 struct StrToSth_obj<common::RECTF>
03056 {
03057 bool operator () (common::RECTF *Sth, const tstring &Str)
03058 {
03059 size_t CommaPos1 = Str.find(_T(','));
03060 if (CommaPos1 == tstring::npos) return false;
03061 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03062 if (CommaPos2 == tstring::npos) return false;
03063 size_t CommaPos3 = Str.find(_T(','), CommaPos2+1);
03064 if (CommaPos3 == tstring::npos) return false;
03065 if (!StrToSth<float>(&Sth->left, Str.substr(0, CommaPos1))) return false;
03066 if (!StrToSth<float>(&Sth->top, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03067 if (!StrToSth<float>(&Sth->right, Str.substr(CommaPos2+1, CommaPos3-(CommaPos2+1)))) return false;
03068 if (!StrToSth<float>(&Sth->bottom, Str.substr(CommaPos3+1))) return false;
03069 return true;
03070 }
03071 static inline bool IsSupported() { return true; }
03072 };
03073
03074 template <>
03075 struct SthToStr_obj<common::BOX>
03076 {
03077 void operator () (tstring *Str, const common::BOX &Sth)
03078 {
03079 *Str = common::Format(_T("#;#")) % Sth.p1 % Sth.p2;
03080 }
03081 static inline bool IsSupported() { return true; }
03082 };
03083
03084 template <>
03085 struct StrToSth_obj<common::BOX>
03086 {
03087 bool operator () (common::BOX *Sth, const tstring &Str)
03088 {
03089 size_t SemicolonPos = Str.find(_T(';'));
03090 if (SemicolonPos == tstring::npos) return false;
03091 if (!StrToSth<common::VEC3>(&Sth->p1, Str.substr(0, SemicolonPos))) return false;
03092 if (!StrToSth<common::VEC3>(&Sth->p2, Str.substr(SemicolonPos+1))) return false;
03093 return true;
03094 }
03095 static inline bool IsSupported() { return true; }
03096 };
03097
03098 template <> struct SthToStr_obj<common::COLOR> {
03099 void operator () (tstring *Str, const common::COLOR &Sth) { common::ColorToStr(Str, Sth); }
03100 static inline bool IsSupported() { return true; }
03101 };
03102 template <> struct StrToSth_obj<common::COLOR> {
03103 bool operator () (common::COLOR *Sth, const tstring &Str) { return common::StrToColor(Sth, Str); }
03104 static inline bool IsSupported() { return true; }
03105 };
03106
03107 template <> struct SthToStr_obj<common::COLORF> {
03108 void operator () (tstring *Str, const common::COLORF &Sth) { common::ColorToStr(Str, Sth); }
03109 static inline bool IsSupported() { return true; }
03110 };
03111 template <> struct StrToSth_obj<common::COLORF> {
03112 bool operator () (common::COLORF *Sth, const tstring &Str) { return common::StrToColor(Sth, Str); }
03113 static inline bool IsSupported() { return true; }
03114 };
03115
03116 template <>
03117 struct SthToStr_obj<common::PLANE>
03118 {
03119 void operator () (tstring *Str, const common::PLANE &Sth)
03120 {
03121 *Str = common::Format(_T("#,#,#,#")) % Sth.a % Sth.b % Sth.c % Sth.d;
03122 }
03123 static inline bool IsSupported() { return true; }
03124 };
03125
03126 template <>
03127 struct StrToSth_obj<common::PLANE>
03128 {
03129 bool operator () (common::PLANE *Sth, const tstring &Str)
03130 {
03131 size_t CommaPos1 = Str.find(_T(','));
03132 if (CommaPos1 == tstring::npos) return false;
03133 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03134 if (CommaPos2 == tstring::npos) return false;
03135 size_t CommaPos3 = Str.find(_T(','), CommaPos2+1);
03136 if (CommaPos3 == tstring::npos) return false;
03137 if (!StrToSth<float>(&Sth->a, Str.substr(0, CommaPos1))) return false;
03138 if (!StrToSth<float>(&Sth->b, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03139 if (!StrToSth<float>(&Sth->c, Str.substr(CommaPos2+1, CommaPos3-(CommaPos2+1)))) return false;
03140 if (!StrToSth<float>(&Sth->d, Str.substr(CommaPos3+1))) return false;
03141 return true;
03142 }
03143 static inline bool IsSupported() { return true; }
03144 };
03145
03146 template <>
03147 struct SthToStr_obj<common::LINE2D>
03148 {
03149 void operator () (tstring *Str, const common::LINE2D &Sth)
03150 {
03151 *Str = common::Format(_T("#,#,#")) % Sth.a % Sth.b % Sth.c;
03152 }
03153 static inline bool IsSupported() { return true; }
03154 };
03155
03156 template <>
03157 struct StrToSth_obj<common::LINE2D>
03158 {
03159 bool operator () (common::LINE2D *Sth, const tstring &Str)
03160 {
03161 size_t CommaPos1 = Str.find(_T(','));
03162 if (CommaPos1 == tstring::npos) return false;
03163 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03164 if (CommaPos2 == tstring::npos) return false;
03165 if (!StrToSth<float>(&Sth->a, Str.substr(0, CommaPos1))) return false;
03166 if (!StrToSth<float>(&Sth->b, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03167 if (!StrToSth<float>(&Sth->c, Str.substr(CommaPos2+1))) return false;
03168 return true;
03169 }
03170 static inline bool IsSupported() { return true; }
03171 };
03172
03173 template <> struct SthToStr_obj<common::MATRIX> {
03174 void operator () (tstring *Str, const common::MATRIX &Sth) { common::MatrixToStr(Str, Sth); }
03175 static inline bool IsSupported() { return true; }
03176 };
03177 template <> struct StrToSth_obj<common::MATRIX> {
03178 bool operator () (common::MATRIX *Sth, const tstring &Str) { return common::StrToMatrix(Sth, Str); }
03179 static inline bool IsSupported() { return true; }
03180 };
03181
03182 template <>
03183 struct SthToStr_obj<common::QUATERNION>
03184 {
03185 void operator () (tstring *Str, const common::QUATERNION &Sth)
03186 {
03187 *Str = common::Format(_T("#,#,#,#")) % Sth.x % Sth.y % Sth.z % Sth.w;
03188 }
03189 static inline bool IsSupported() { return true; }
03190 };
03191
03192 template <>
03193 struct StrToSth_obj<common::QUATERNION>
03194 {
03195 bool operator () (common::QUATERNION *Sth, const tstring &Str)
03196 {
03197 size_t CommaPos1 = Str.find(_T(','));
03198 if (CommaPos1 == tstring::npos) return false;
03199 size_t CommaPos2 = Str.find(_T(','), CommaPos1+1);
03200 if (CommaPos2 == tstring::npos) return false;
03201 size_t CommaPos3 = Str.find(_T(','), CommaPos2+1);
03202 if (CommaPos3 == tstring::npos) return false;
03203 if (!StrToSth<float>(&Sth->x, Str.substr(0, CommaPos1))) return false;
03204 if (!StrToSth<float>(&Sth->y, Str.substr(CommaPos1+1, CommaPos2-(CommaPos1+1)))) return false;
03205 if (!StrToSth<float>(&Sth->z, Str.substr(CommaPos2+1, CommaPos3-(CommaPos2+1)))) return false;
03206 if (!StrToSth<float>(&Sth->w, Str.substr(CommaPos3+1))) return false;
03207 return true;
03208 }
03209 static inline bool IsSupported() { return true; }
03210 };
03211
03213
03214 #endif