Browse Source

Disallow concave shapes as geometry.

vrld 12 years ago
parent
commit
e9d0204cdc

+ 34 - 53
src/modules/graphics/Geometry.cpp

@@ -20,6 +20,7 @@
 
 
 #include "Geometry.h"
 #include "Geometry.h"
 #include "common/Exception.h"
 #include "common/Exception.h"
+#include "common/Vector.h"
 #include "modules/math/MathModule.h"
 #include "modules/math/MathModule.h"
 
 
 using love::math::Math;
 using love::math::Math;
@@ -34,49 +35,49 @@ namespace love
 namespace graphics
 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_min(std::numeric_limits<float>::max())
 	, x_max(std::numeric_limits<float>::min())
 	, x_max(std::numeric_limits<float>::min())
 	, y_min(std::numeric_limits<float>::max())
 	, y_min(std::numeric_limits<float>::max())
 	, y_max(std::numeric_limits<float>::min())
 	, y_max(std::numeric_limits<float>::min())
 	, vertexColors(false)
 	, 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];
 		const vertex &v = polygon[i];
+		vertexArray[i] = v;
 		x_min = v.x < x_min ? v.x : x_min;
 		x_min = v.x < x_min ? v.x : x_min;
 		x_max = v.x > x_max ? v.x : x_max;
 		x_max = v.x > x_max ? v.x : x_max;
 		y_min = v.y < y_min ? v.y : y_min;
 		y_min = v.y < y_min ? v.y : y_min;
 		y_max = v.y > y_max ? v.y : y_max;
 		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)
 Geometry::Geometry(float x, float y, float w, float h, float sw, float sh)
 	: vertexArray(NULL)
 	: vertexArray(NULL)
+	, vertexCount(4)
 	, x_min(x)
 	, x_min(x)
 	, x_max(x+w)
 	, x_max(x+w)
 	, y_min(y)
 	, y_min(y)
 	, y_max(y+h)
 	, y_max(y+h)
 	, vertexColors(false)
 	, vertexColors(false)
 {
 {
+	vertexArray = new vertex[4];
 	float s0 = x/sw, s1 = (x+w)/sw, t0 = y/sh, t1 = (y+h)/sh;
 	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)
 Geometry::Geometry(const Geometry &other)
-	: polygon(other.polygon)
-	, vertexCount(other.vertexCount)
+	: vertexCount(other.vertexCount)
 	, x_min(other.x_min)
 	, x_min(other.x_min)
 	, x_max(other.x_max)
 	, x_max(other.x_max)
 	, y_min(other.y_min)
 	, y_min(other.y_min)
@@ -92,7 +93,6 @@ Geometry &Geometry::operator=(const Geometry &other)
 	if (this != &other)
 	if (this != &other)
 	{
 	{
 		Geometry temp(other);
 		Geometry temp(other);
-		std::swap(polygon, temp.polygon);
 		std::swap(vertexArray, temp.vertexArray);
 		std::swap(vertexArray, temp.vertexArray);
 
 
 		vertexCount = temp.vertexCount;
 		vertexCount = temp.vertexCount;
@@ -117,41 +117,41 @@ Geometry::~Geometry()
 
 
 const vertex &Geometry::getVertex(size_t i) const
 const vertex &Geometry::getVertex(size_t i) const
 {
 {
-	if (i >= polygon.size())
+	if (i >= vertexCount)
 		throw Exception("Invalid vertex index");
 		throw Exception("Invalid vertex index");
-	return polygon[i];
+	return vertexArray[i];
 }
 }
 
 
 void Geometry::setVertex(size_t i, const vertex &v)
 void Geometry::setVertex(size_t i, const vertex &v)
 {
 {
-	if (i >= polygon.size())
+	if (i >= vertexCount)
 		throw Exception("Invalid vertex index");
 		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_min = v.x < x_min ? v.x : x_min;
 		x_max = v.x > x_max ? v.x : x_max;
 		x_max = v.x > x_max ? v.x : x_max;
 		y_min = v.y < y_min ? v.y : y_min;
 		y_min = v.y < y_min ? v.y : y_min;
 		y_max = v.y > y_max ? v.y : y_max;
 		y_max = v.y > y_max ? v.y : y_max;
-
-		triangulate();
 	}
 	}
+
+	vertexArray[i] = v;
 }
 }
 
 
 void Geometry::flip(bool x, bool y)
 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)
 	for (size_t i = 0; i < vertexCount; ++i)
 	{
 	{
 		vertex &v = vertexArray[i];
 		vertex &v = vertexArray[i];
@@ -165,24 +165,5 @@ void Geometry::setVertexColors(bool on)
 	vertexColors = 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
 } // graphics
 } // love
 } // love

+ 1 - 13
src/modules/graphics/Geometry.h

@@ -57,14 +57,6 @@ public:
 	Geometry &operator=(const Geometry &other);
 	Geometry &operator=(const Geometry &other);
 	virtual ~Geometry();
 	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;
 	const vertex &getVertex(size_t i) const;
 	void setVertex(size_t i, const vertex &v);
 	void setVertex(size_t i, const vertex &v);
 
 
@@ -81,7 +73,7 @@ public:
 	/**
 	/**
 	 * Returns the size of the vertex array.
 	 * Returns the size of the vertex array.
 	 **/
 	 **/
-	size_t getVertexArraySize() const
+	size_t getVertexCount() const
 	{
 	{
 		return vertexCount;
 		return vertexCount;
 	}
 	}
@@ -100,10 +92,6 @@ public:
 	};
 	};
 
 
 private:
 private:
-	void triangulate();
-
-	std::vector<vertex> polygon;
-
 	vertex *vertexArray;
 	vertex *vertexArray;
 	size_t vertexCount;
 	size_t vertexCount;
 
 

+ 2 - 2
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);
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
 
 	// flip texture coordinates vertically
 	// flip texture coordinates vertically
-	size_t vcount = geom->getVertexArraySize();
+	size_t vcount = geom->getVertexCount();
 	const vertex *w = geom->getVertexArray();
 	const vertex *w = geom->getVertexArray();
 	vertex *v = new vertex[vcount];
 	vertex *v = new vertex[vcount];
 	for (size_t i = 0; i < vcount; ++i)
 	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);
 		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())
 	if (geom->hasVertexColors())
 	{
 	{

+ 1 - 1
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);
 		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())
 	if (geom->hasVertexColors())
 	{
 	{

+ 1 - 1
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)
 	if ((index == -1 && next >= size) || index < -1 || index >= next)
 		return -1;
 		return -1;
 
 
-	if (geom->getNumVertices() != 4)
+	if (geom->getVertexCount() != 4)
 		throw love::Exception("Can only add quadliteral geometries to SpriteBatch");
 		throw love::Exception("Can only add quadliteral geometries to SpriteBatch");
 
 
 	for (size_t i = 0; i < 4; i++)
 	for (size_t i = 0; i < 4; i++)

+ 1 - 1
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)
 int w_Geometry_getVertexCount(lua_State *L)
 {
 {
 	Geometry *geom = luax_checkgeometry(L, 1);
 	Geometry *geom = luax_checkgeometry(L, 1);
-	lua_pushinteger(L, geom->getNumVertices());
+	lua_pushinteger(L, geom->getVertexCount());
 	return 1;
 	return 1;
 }
 }