// ============================================================== // This file is part of Glest Shared Library (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #ifndef _SHARED_GRAPHICS_MATHUTIL_H_ #define _SHARED_GRAPHICS_MATHUTIL_H_ #include "math_wrapper.h" #include "vec.h" #include "data_types.h" #include "leak_dumper.h" using namespace std; using namespace Shared::Platform; namespace Shared { namespace Graphics { const float pi = 3.1415926f; const float sqrt2 = 1.41421356f; const float zero = 1e-6f; const float infinity = 1e6f; // ===================================================== // class Rect // ===================================================== // 0 +-+ // | | // +-+ 1 template class Rect2 { public: Vec2 p[2]; public: Rect2() { }; Rect2(const Vec2 &p0, const Vec2 &p1) { this->p[0] = p0; this->p[1] = p1; } Rect2(T p0x, T p0y, T p1x, T p1y) { p[0].x = p0x; p[0].y = p0y; p[1].x = p1x; p[1].y = p1y; } Rect2 operator*(T scalar) { return Rect2( p[0] * scalar, p[1] * scalar); } Rect2 operator/(T scalar) { return Rect2( p[0] / scalar, p[1] / scalar); } bool isInside(const Vec2 &p) const { return p.x >= this->p[0].x && p.y >= this->p[0].y && p.x < this->p[1].x && p.y < this->p[1].y; } void clamp(T minX, T minY, T maxX, T maxY) { for (int i = 0; i < 2; ++i) { if (p[i].x < minX) { p[i].x = minX; } if (p[i].y < minY) { p[i].y = minY; } if (p[i].x > maxX) { p[i].x = maxX; } if (p[i].y > maxY) { p[i].y = maxY; } } } std::string getString() const { std::ostringstream streamOut; streamOut << "#1: " << this->p[0].getString(); streamOut << "#2: " << this->p[1].getString(); std::string result = streamOut.str(); streamOut.str(std::string()); return result; } }; typedef Rect2 Rect2i; typedef Rect2 Rect2c; typedef Rect2 Rect2f; typedef Rect2 Rect2d; // ===================================================== // class Quad // ===================================================== // 0 +-+ 2 // | | // 1 +-+ 3 template class Quad2 { public: Vec2 p[4]; public: Quad2() { }; Quad2(const Vec2 &p0, const Vec2 &p1, const Vec2 &p2, const Vec2 &p3) { this->p[0] = p0; this->p[1] = p1; this->p[2] = p2; this->p[3] = p3; } explicit Quad2(const Rect2 &rect) { this->p[0] = rect.p[0]; this->p[1] = Vec2(rect.p[0].x, rect.p[1].y); this->p[2] = rect.p[1]; this->p[3] = Vec2(rect.p[1].x, rect.p[0].y); } Quad2 operator*(T scalar) { return Quad2( p[0] * scalar, p[1] * scalar, p[2] * scalar, p[3] * scalar); } Quad2 operator/(T scalar) { return Quad2( p[0] / scalar, p[1] / scalar, p[2] / scalar, p[3] / scalar); } bool operator <(const Quad2 &v) const { if (p[0] < v.p[0]) { return true; } if (p[1] < v.p[1]) { return true; } if (p[2] < v.p[2]) { return true; } if (p[3] < v.p[3]) { return true; } return false; } bool operator !=(const Quad2 &v) const { if (p[0] != v.p[0]) { return true; } if (p[1] != v.p[1]) { return true; } if (p[2] != v.p[2]) { return true; } if (p[3] != v.p[3]) { return true; } return false; } Rect2 computeBoundingRect() const { return Rect2i( #ifdef WIN32 min(p[0].x, p[1].x), min(p[0].y, p[2].y), max(p[2].x, p[3].x), max(p[1].y, p[3].y)); #else std::min(p[0].x, p[1].x), std::min(p[0].y, p[2].y), std::max(p[2].x, p[3].x), std::max(p[1].y, p[3].y)); #endif } bool isInside(const Vec2 &pt) const { if (!computeBoundingRect().isInside(pt)) return false; bool left[4]; left[0] = (pt.y - p[0].y)*(p[1].x - p[0].x) - (pt.x - p[0].x)*(p[1].y - p[0].y) < 0; left[1] = (pt.y - p[1].y)*(p[3].x - p[1].x) - (pt.x - p[1].x)*(p[3].y - p[1].y) < 0; left[2] = (pt.y - p[3].y)*(p[2].x - p[3].x) - (pt.x - p[3].x)*(p[2].y - p[3].y) < 0; left[3] = (pt.y - p[2].y)*(p[0].x - p[2].x) - (pt.x - p[2].x)*(p[0].y - p[2].y) < 0; return left[0] && left[1] && left[2] && left[3]; } void clamp(T minX, T minY, T maxX, T maxY) { for (int i = 0; i < 4; ++i) { if (p[i].x < minX) { p[i].x = minX; } if (p[i].y < minY) { p[i].y = minY; } if (p[i].x > maxX) { p[i].x = maxX; } if (p[i].y > maxY) { p[i].y = maxY; } } } float area() { Vec2i v0 = p[3] - p[0]; Vec2i v1 = p[1] - p[2]; return 0.5f * ((v0.x * v1.y) - (v0.y * v1.x)); } std::string getString() const { std::ostringstream streamOut; streamOut << "#1: " << this->p[0].getString(); streamOut << "#2: " << this->p[1].getString(); streamOut << "#3: " << this->p[2].getString(); streamOut << "#4: " << this->p[3].getString(); std::string result = streamOut.str(); streamOut.str(std::string()); return result; } }; typedef Quad2 Quad2i; typedef Quad2 Quad2c; typedef Quad2 Quad2f; typedef Quad2 Quad2d; // ===================================================== // Misc // ===================================================== inline int next2Power(int n) { int i; for (i = 1; i < n; i *= 2); return i; } template inline T degToRad(T deg) { return (deg * 2 * pi) / 360; } template inline T radToDeg(T rad) { return (rad * 360) / (2 * pi); } // ==================================================================================================================== // ==================================================================================================================== // Inline implementation // ==================================================================================================================== // ==================================================================================================================== //#if _xs_BigEndian_ // #define _xs_iexp_ 0 // #define _xs_iman_ 1 //#else // #define _xs_iexp_ 1 //intel is little endian // #define _xs_iman_ 0 //#endif //BigEndian_ // ////#define finline __forceinline //#define finline inline // //#ifndef _xs_DEFAULT_CONVERSION //#define _xs_DEFAULT_CONVERSION 0 //#endif // ////typedef long int32; //typedef double real64; //const real64 _xs_doublemagic = real64 (6755399441055744.0); //2^52 * 1.5, uses limited precisicion to floor // //finline int32 xs_CRoundToInt(real64 val, real64 dmr = _xs_doublemagic) { //#if _xs_DEFAULT_CONVERSION==0 // val = val + dmr; // return ((int32*)&val)[_xs_iman_]; // //return 0; //#else // return int32(floor(val+.5)); //#endif //} } }//end namespace #endif