diff --git a/src/modules/graphics/Geometry.cpp b/src/modules/graphics/Geometry.cpp index dd0c36abb..0e3354b30 100644 --- a/src/modules/graphics/Geometry.cpp +++ b/src/modules/graphics/Geometry.cpp @@ -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 &p) - : polygon(p) - , vertexArray(NULL) +Geometry::Geometry(const std::vector &polygon) + : vertexArray(NULL) , x_min(std::numeric_limits::max()) , x_max(std::numeric_limits::min()) , y_min(std::numeric_limits::max()) , y_max(std::numeric_limits::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 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 diff --git a/src/modules/graphics/Geometry.h b/src/modules/graphics/Geometry.h index 1aa460503..7610f0cf3 100644 --- a/src/modules/graphics/Geometry.h +++ b/src/modules/graphics/Geometry.h @@ -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 polygon; - vertex *vertexArray; size_t vertexCount; diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index cb52a0e84..ac34aa686 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -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()) { diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index ba45adc35..f36ad71b5 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -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()) { diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index 7019f94e2..218473ea1 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -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++) diff --git a/src/modules/graphics/opengl/wrap_Geometry.cpp b/src/modules/graphics/opengl/wrap_Geometry.cpp index cfe6f74ee..863429d8a 100644 --- a/src/modules/graphics/opengl/wrap_Geometry.cpp +++ b/src/modules/graphics/opengl/wrap_Geometry.cpp @@ -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; }