Newer
Older
/*
* Copyright (c) 2015 Tricoire Sebastien 3dsman@free.fr
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
3dsman
committed
#include <GL/gl.h>
struct vector_2d
{
float x, y;
vector_2d( float _x, float _y)
{
x = _x;
y = _y;
}
void persist(Pakal::Archive* archive)
{
archive->value("x", x);
archive->value("y", y);
}
inline vector_2d operator *(const vector_2d& pt) const
{
return {pt.x*x, pt.y*y};
inline vector_2d operator *( const float val)
{
return {val*x, val*y};
inline vector_2d operator /(const vector_2d& pt) const
{
return {x/pt.x, y/pt.y};
inline vector_2d operator /( const float val)
{
return {x/val, y/val};
inline vector_2d operator +(const vector_2d pt) const
{
return {pt.x+x, pt.y+y};
inline vector_2d operator +(const float val) const
{
return {val+x, val+y};
inline void operator +=(const vector_2d pt)
{
x+=pt.x;
y+=pt.y;
}
inline vector_2d operator -(const vector_2d pt) const
{
return {x-pt.x, y-pt.y};
inline vector_2d operator -(const float val) const
{
return {x-val, y-val};
inline vector_2d operator -() const
{
return {-x, -y};
inline void operator -=(const vector_2d pt)
{
x-=pt.x;
y-=pt.y;
}
inline bool operator ==(const vector_2d pt) const
{
return x == pt.x && y == pt.y;
}
double dot(const vector_2d pt) const
{
return x*pt.x+y*pt.y;
3dsman
committed
}
inline bool operator !=(const vector_2d pt) const
{
return x!=pt.x || y!=pt.y;
3dsman
committed
}
/** \brief normalise the vector (his length become 1)
*/
if (len()==0)
{
return;
}
float length = 1/len();
x *= length;
y *= length;
}
class BoundingBox
{
private:
/** \brief The bounding box values. */
vector_2d min;
vector_2d max;
public:
bool init;
BoundingBox() : init(false)
{
}
BoundingBox(float minX, float minY, float maxX, float maxY);
~BoundingBox(){}
const vector_2d& getMin();
const vector_2d& getMax();
const vector_2d getCenter();
BoundingBox operator+ (const BoundingBox& box);
BoundingBox operator+ (const vector_2d& point);
void operator+= (const BoundingBox& box);
void operator+= (const vector_2d& point);
};
GLfloat rgba[4];
OE_color()
rgba[0] = rgba[1] = rgba[2] = 0.0f;
rgba[3] = 1.0f;
OE_color(float r, float g, float b, float a = 1.0)
rgba[0] = r;
rgba[1] = g;
rgba[2] = b;
rgba[3] = a;
operator QColor() const
{
return QColor(rgba[0]*255,rgba[1]*255,rgba[2]*255,rgba[3]*255);
}
inline OE_color operator *( const OE_color& color)
return OE_color(rgba[0]*color.rgba[0], rgba[1]*color.rgba[1], rgba[2]*color.rgba[2], rgba[3]*color.rgba[3]);
inline bool operator ==( const OE_color& color)
{
return memcmp(&rgba[0], &color.rgba[0], sizeof(rgba)) == 0;
}
inline bool operator !=( const OE_color& color)
{
return !(*this == color);
}
archive->value("r", rgba[0]);
archive->value("g", rgba[1]);
archive->value("b", rgba[2]);
archive->value("a", rgba[3]);
inline std::vector<vector_2d> normals(const std::vector<vector_2d> segments)
vector_2d tmpNormal;
vector_2d normal;
std::vector<vector_2d> out;
for(unsigned i=0; i<segments.size()-1; i++)
{
normal = segments.at(i+1)-segments.at(i);
normal.turnRight();
if (i==0)
{
tmpNormal = normal;
}
tmpNormal =tmpNormal + normal;
tmpNormal.normalize();
out.push_back(tmpNormal);
tmpNormal = normal;
}
tmpNormal.normalize();
out.push_back(tmpNormal);
return out;
inline std::vector<vector_2d> subd(const vector_2d pt1, const vector_2d pt2, float maxlen)
{
std::vector<vector_2d> out;
vector_2d tmpvec = pt2 - pt1;
float len = tmpvec.len();
if (len<maxlen)
{
return out;
}
int nbsub = ceilf(len / maxlen);
len /= (float)nbsub;
tmpvec.normalize();
tmpvec = tmpvec*len;
tmppos = tmppos + tmpvec;
out.push_back( tmppos);
}
return out;
}
/*inline vector_2d operator* ( const vector_2d vect, const float val)
{
return {val*vect.x,val*vect.y};
}*/
inline vector_2d operator* (const float val, const vector_2d vect)
{
return {val*vect.x, val*vect.y};
/*inline vector_2d operator- ( const vector_2d vect1, const vector_2d vect2)
{
return {vect1.x-vect2.x,vect1.y-vect2.y};
}*/
inline vector_2d operator- (const float val, const vector_2d vect)
{
return {val-vect.x, val-vect.y};
inline vector_2d operator- (const vector_2d vect, const float val)
{
return {vect.x-val, vect.y-val};
vector_2dt( vector_2d _v, float _t)
{
v = _v;
t = _t;
}
inline vector_2dt operator+ (const vector_2dt pt) const
{
return {pt.v+v, pt.t+t};
}
inline vector_2dt operator- (const vector_2dt pt) const
{
return {v-pt.v, t-pt.t};
}
};
inline std::vector<vector_2d> normals(const std::vector<vector_2dt> segments)
{
vector_2d tmpNormal;
vector_2d normal;
std::vector<vector_2d> out;
for (unsigned i=0; i<segments.size()-1; i++)
{
normal = segments.at(i+1).v-segments.at(i).v;
normal.turnRight();
if (i==0)
{
tmpNormal = normal;
}
tmpNormal = tmpNormal + normal;
tmpNormal.normalize();
out.push_back(tmpNormal);
tmpNormal = normal;
}
tmpNormal.normalize();
out.push_back(tmpNormal);
return out;
}
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
struct OE_Matrix
{
float a, b, c, d, e, f;
OE_Matrix() : a(1.0), b(0), c(0), d(1.0), e(0), f(0) {}
OE_Matrix(float a, float b, float c, float d, float e, float f) : a(a), b(b), c(c), d(d), e(e), f(f) {}
OE_Matrix(float* arr) : a(arr[0]), b(arr[1]), c(arr[2]), d(arr[3]), e(arr[4]), f(arr[5]) {}
OE_Matrix operator*(const OE_Matrix& m)
{
return OE_Matrix(a*m.a+b*c, a*m.b+m.d*b, c*m.a+c*d, m.b*c+m.d*d, e*m.a+c*f+m.e, m.b*e+m.d*f+m.f);
}
void apply(float x, float y, float* newx, float* newy)
{
if(newx && newy)
{
*newx = a*x+c*y+e;
*newy = b*x+d*y+f;
}
}
void apply(float& x, float& y) const
{
float oldx = x;
float oldy = y;
x = a*oldx+c*oldy+e;
y = b*oldx+d*oldy+f;
}
};
inline float sign (const vector_2d p1, const vector_2d p2, const vector_2d p3)
{
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}
inline bool PointInTriangle (const vector_2d pt, const vector_2d v1, const vector_2d v2, const vector_2d v3)
{
bool b1, b2, b3;
b1 = sign(pt, v1, v2) < 0.0f;
b2 = sign(pt, v2, v3) < 0.0f;
b3 = sign(pt, v3, v1) < 0.0f;
//inline vector_2d* intersect(vector_2d p1, vector_2d p2, vector_2d p3, vector_2d p4);
/*
inline bool intersect(vector_2d p1, vector_2d p2, vector_2d p3, vector_2d p4, vector_2d &intersectPt)
{
// Store the values for fast access and easy
// equations-to-code conversion
float x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x;
float y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y;
float minx12 = minf(x1, x2) , minx34 = minf(x3, x4), miny12 = minf(y1, y2) , miny34 = minf(y3, y4);
float maxx12 = maxf(x1, x2) , maxx34 = maxf(x3, x4), maxy12 = maxf(y1, y2) , maxy34 = maxf(y3, y4);
//if ( maxx12<minx34 || maxx34<minx12 || maxy12<miny34 || maxy34<miny12)
//{
// return false;
//}
double lenx12 = (x1 - x2) , lenx34 = x3 - x4, leny12 = y1 - y2 , leny34 = y3 - y4;
double d = lenx12 * leny34 - leny12 * lenx34;
// If d is zero, there is no intersection
// Get the x and y
double pre = (x1*y2 - y1*x2), post = (x3*y4 - y3*x4);
double x = ( pre * lenx34 - lenx12 * post ) / d;
double y = ( pre * leny34 - leny12 * post ) / d;
// Check if the x and y coordinates are within both lines (use only the longer axis to avoid precision problems on vertical or horizontal segments)
if (abs(lenx12)>abs(leny12))
{
if( x < minx12 || x > maxx12 )
{
return false;
}
}
else
if( y < miny12 || y > maxy12 )
{
return false;
}
if(x < minx34 || x > maxx34 )
{
return false;
}
}
else
//if (x < minx12 || x > maxx12 || x < minx34 || x > maxx34)
//{
// return nullptr;
//}
//if (y < miny12 || y > maxy12 || y < miny34 || y > maxy34)
//{
// return nullptr;
//}
intersectPt.x = x;
intersectPt.y = y;
return true;
}
*/
3dsman
committed
inline bool intersect(vector_2d p1, vector_2d p2, vector_2d p3, vector_2d p4, vector_2d& intersectPt, float& intersectP1P2, float &intersectP3P4, bool extremity = true)
{
vector_2d CmP = p3 - p1;
vector_2d r = p2 - p1;
vector_2d s = p4 - p3;
float CmPxr = CmP.x * r.y - CmP.y * r.x;
float CmPxs = CmP.x * s.y - CmP.y * s.x;
float rxs = r.x * s.y - r.y * s.x;
if (CmPxr == 0.0f)
{
// Lines are collinear, and so intersect if they have any overlap
return ((p3.x - p1.x < 0.0f) != (p3.x - p2.x < 0.0f)) ||
((p3.y - p1.y < 0.0f) != (p3.y - p2.y < 0.0f));
}
if (rxs == 0.0f)
return false; // Lines are parallel.
float rxsr = 1.0f / rxs;
float t = CmPxs * rxsr;
float u = CmPxr * rxsr;
intersectPt = r * t + p1;
3dsman
committed
return (extremity||(t != 0.0f && t != 1.0f && u != 0.0f && u != 1.0f));
}
return false;
}