Disallow concave shapes as geometry.

This commit is contained in:
vrld
2013-05-12 13:01:05 +02:00
parent d454be7025
commit e9d0204cdc
6 changed files with 40 additions and 71 deletions
+34 -53
View File
@@ -20,6 +20,7 @@
#include "Geometry.h"
#include "common/Exception.h"
#include "common/Vector.h"
#include "modules/math/MathModule.h"
using love::math::Math;
@@ -34,49 +35,49 @@ namespace love
namespace graphics
{
Geometry::Geometry(const std::vector<vertex> &p)
: polygon(p)
, vertexArray(NULL)
Geometry::Geometry(const std::vector<vertex> &polygon)
: vertexArray(NULL)
, x_min(std::numeric_limits<float>::max())
, x_max(std::numeric_limits<float>::min())
, y_min(std::numeric_limits<float>::max())
, y_max(std::numeric_limits<float>::min())
, vertexColors(false)
{
for (size_t i = 0; i < polygon.size(); ++i)
if (!Math::instance.isConvex(polygon))
throw love::Exception("Geometry must be convex");
vertexCount = polygon.size();
vertexArray = new vertex[vertexCount];
for (size_t i = 0; i < vertexCount; ++i)
{
const vertex &v = polygon[i];
vertexArray[i] = v;
x_min = v.x < x_min ? v.x : x_min;
x_max = v.x > x_max ? v.x : x_max;
y_min = v.y < y_min ? v.y : y_min;
y_max = v.y > y_max ? v.y : y_max;
}
triangulate();
}
Geometry::Geometry(float x, float y, float w, float h, float sw, float sh)
: vertexArray(NULL)
, vertexCount(4)
, x_min(x)
, x_max(x+w)
, y_min(y)
, y_max(y+h)
, vertexColors(false)
{
vertexArray = new vertex[4];
float s0 = x/sw, s1 = (x+w)/sw, t0 = y/sh, t1 = (y+h)/sh;
polygon.resize(4);
polygon[0] = vertex(0,0, s0,t0);
polygon[1] = vertex(w,0, s1,t0);
polygon[2] = vertex(w,h, s1,t1);
polygon[3] = vertex(0,h, s0,t1);
triangulate();
vertexArray[0] = vertex(0,0, s0,t0);
vertexArray[1] = vertex(w,0, s1,t0);
vertexArray[2] = vertex(w,h, s1,t1);
vertexArray[3] = vertex(0,h, s0,t1);
}
Geometry::Geometry(const Geometry &other)
: polygon(other.polygon)
, vertexCount(other.vertexCount)
: vertexCount(other.vertexCount)
, x_min(other.x_min)
, x_max(other.x_max)
, y_min(other.y_min)
@@ -92,7 +93,6 @@ Geometry &Geometry::operator=(const Geometry &other)
if (this != &other)
{
Geometry temp(other);
std::swap(polygon, temp.polygon);
std::swap(vertexArray, temp.vertexArray);
vertexCount = temp.vertexCount;
@@ -117,41 +117,41 @@ Geometry::~Geometry()
const vertex &Geometry::getVertex(size_t i) const
{
if (i >= polygon.size())
if (i >= vertexCount)
throw Exception("Invalid vertex index");
return polygon[i];
return vertexArray[i];
}
void Geometry::setVertex(size_t i, const vertex &v)
{
if (i >= polygon.size())
if (i >= vertexCount)
throw Exception("Invalid vertex index");
float oldx = polygon[i].x;
float oldy = polygon[i].y;
love::Vector p(vertexArray[i].x, vertexArray[i].y);
polygon[i] = v;
if (oldx != v.x || oldy != v.y)
if (p.x != v.x || p.y != v.y)
{
size_t j = (i+1) % vertexCount, k = (i+2) % vertexCount;
Vector q(vertexArray[j].x, vertexArray[j].y);
Vector r(vertexArray[k].x, vertexArray[k].y);
Vector p_new(v.x, v.y);
float winding_old = (p-q) ^ (q-r);
float winding_new = (p_new-q) ^ (q-r);
if (winding_old * winding_new < 0)
throw Exception("Invalid vertex position: Makes geometry concave.");
x_min = v.x < x_min ? v.x : x_min;
x_max = v.x > x_max ? v.x : x_max;
y_min = v.y < y_min ? v.y : y_min;
y_max = v.y > y_max ? v.y : y_max;
triangulate();
}
vertexArray[i] = v;
}
void Geometry::flip(bool x, bool y)
{
for (size_t i = 0; i < polygon.size(); ++i)
{
vertex &v = polygon[i];
if (x) v.x = x_max + x_min - v.x;
if (y) v.y = y_max + y_min - v.y;
}
for (size_t i = 0; i < vertexCount; ++i)
{
vertex &v = vertexArray[i];
@@ -165,24 +165,5 @@ void Geometry::setVertexColors(bool on)
vertexColors = on;
}
void Geometry::triangulate()
{
const std::vector<Triangle> triangles = Math::instance.triangulate(polygon);
if (vertexArray)
delete[] vertexArray;
vertexCount = triangles.size() * 3;
vertexArray = new vertex[vertexCount];
for (size_t i = 0; i < triangles.size(); ++i)
{
const Triangle &t = triangles[i];
vertexArray[i*3] = t.a;
vertexArray[i*3+1] = t.b;
vertexArray[i*3+2] = t.c;
}
}
} // graphics
} // love
+1 -13
View File
@@ -57,14 +57,6 @@ public:
Geometry &operator=(const Geometry &other);
virtual ~Geometry();
/**
* Returns number of vertices in the *polygon* defining the geometry.
**/
size_t getNumVertices() const
{
return polygon.size();
}
const vertex &getVertex(size_t i) const;
void setVertex(size_t i, const vertex &v);
@@ -81,7 +73,7 @@ public:
/**
* Returns the size of the vertex array.
**/
size_t getVertexArraySize() const
size_t getVertexCount() const
{
return vertexCount;
}
@@ -100,10 +92,6 @@ public:
};
private:
void triangulate();
std::vector<vertex> polygon;
vertex *vertexArray;
size_t vertexCount;
+2 -2
View File
@@ -592,7 +592,7 @@ void Canvas::drawg(love::graphics::Geometry *geom, float x, float y, float angle
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
// flip texture coordinates vertically
size_t vcount = geom->getVertexArraySize();
size_t vcount = geom->getVertexCount();
const vertex *w = geom->getVertexArray();
vertex *v = new vertex[vcount];
for (size_t i = 0; i < vcount; ++i)
@@ -608,7 +608,7 @@ void Canvas::drawg(love::graphics::Geometry *geom, float x, float y, float angle
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *)&v->r);
}
drawv(t, v, vcount, GL_TRIANGLES);
drawv(t, v, vcount, GL_TRIANGLE_FAN);
if (geom->hasVertexColors())
{
+1 -1
View File
@@ -115,7 +115,7 @@ void Image::drawg(love::graphics::Geometry *geom, float x, float y, float angle,
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *) &v[0].r);
}
drawv(t, v, geom->getVertexArraySize(), GL_TRIANGLES);
drawv(t, v, geom->getVertexCount(), GL_TRIANGLE_FAN);
if (geom->hasVertexColors())
{
+1 -1
View File
@@ -123,7 +123,7 @@ int SpriteBatch::addg(Geometry *geom, float x, float y, float a, float sx, float
if ((index == -1 && next >= size) || index < -1 || index >= next)
return -1;
if (geom->getNumVertices() != 4)
if (geom->getVertexCount() != 4)
throw love::Exception("Can only add quadliteral geometries to SpriteBatch");
for (size_t i = 0; i < 4; i++)
@@ -38,7 +38,7 @@ Geometry *luax_checkgeometry(lua_State *L, int idx)
int w_Geometry_getVertexCount(lua_State *L)
{
Geometry *geom = luax_checkgeometry(L, 1);
lua_pushinteger(L, geom->getNumVertices());
lua_pushinteger(L, geom->getVertexCount());
return 1;
}