mirror of
https://github.com/love2d/love.git
synced 2026-08-19 12:14:20 +02:00
Disallow concave shapes as geometry.
This commit is contained in:
@@ -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> &polygon)
|
||||||
Geometry::Geometry(const std::vector<vertex> &p)
|
: vertexArray(NULL)
|
||||||
: polygon(p)
|
|
||||||
, 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);
|
vertexArray[0] = vertex(0,0, s0,t0);
|
||||||
polygon[0] = vertex(0,0, s0,t0);
|
vertexArray[1] = vertex(w,0, s1,t0);
|
||||||
polygon[1] = vertex(w,0, s1,t0);
|
vertexArray[2] = vertex(w,h, s1,t1);
|
||||||
polygon[2] = vertex(w,h, s1,t1);
|
vertexArray[3] = vertex(0,h, s0,t1);
|
||||||
polygon[3] = vertex(0,h, s0,t1);
|
|
||||||
|
|
||||||
triangulate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
love::Vector p(vertexArray[i].x, vertexArray[i].y);
|
||||||
float oldy = polygon[i].y;
|
|
||||||
|
|
||||||
polygon[i] = v;
|
if (p.x != v.x || p.y != v.y)
|
||||||
|
|
||||||
if (oldx != v.x || oldy != 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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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++)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user