mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Disallow concave shapes as geometry.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user