Przeglądaj źródła

Geometries now automatically use per-vertex colors when drawing if any vertex has a custom color set, otherwise the constant color is used.
Still not a perfect solution, but it works better than before

Alex Szpakowski 12 lat temu
rodzic
commit
3b05ec0635

+ 10 - 0
src/modules/graphics/Geometry.cpp

@@ -42,6 +42,7 @@ Geometry::Geometry(const std::vector<vertex> &p)
 	, 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)
 	{
@@ -61,6 +62,7 @@ Geometry::Geometry(float x, float y, float w, float h, float sw, float sh)
 	, x_max(x+w)
 	, y_min(y)
 	, y_max(y+h)
+	, vertexColors(false)
 {
 	float s0 = x/sw, s1 = (x+w)/sw, t0 = y/sh, t1 = (y+h)/sh;
 	polygon.resize(4);
@@ -79,6 +81,7 @@ Geometry::Geometry(const Geometry &other)
 	, x_max(other.x_max)
 	, y_min(other.y_min)
 	, y_max(other.y_max)
+	, vertexColors(other.vertexColors)
 {
 	vertexArray = new vertex[vertexCount];
 	memcpy(vertexArray, other.vertexArray, vertexCount * sizeof(vertex));
@@ -97,6 +100,8 @@ Geometry &Geometry::operator=(const Geometry &other)
 		x_max       = temp.x_max;
 		y_min       = temp.y_min;
 		y_max       = temp.y_max;
+
+		vertexColors = other.vertexColors;
 	}
 	return *this;
 }
@@ -155,6 +160,11 @@ void Geometry::flip(bool x, bool y)
 	}
 }
 
+void Geometry::setVertexColors(bool on)
+{
+	vertexColors = on;
+}
+
 void Geometry::triangulate()
 {
 	const std::vector<Triangle> triangles = Math::instance.triangulate(polygon);

+ 15 - 0
src/modules/graphics/Geometry.h

@@ -86,6 +86,19 @@ public:
 		return vertexCount;
 	}
 
+	/**
+	 * Sets whether this Geometry will use custom per-vertex colors.
+	 **/
+	void setVertexColors(bool on);
+
+	/**
+	 * Returns whether this Geometry is using custom per-vertex colors.
+	 **/
+	bool hasVertexColors() const
+	{
+		return vertexColors;
+	};
+
 private:
 	void triangulate();
 
@@ -99,6 +112,8 @@ private:
 
 	float y_min;
 	float y_max;
+
+	bool vertexColors;
 };
 
 } // graphics

+ 13 - 3
src/modules/graphics/opengl/Canvas.cpp

@@ -600,10 +600,20 @@ void Canvas::drawg(love::graphics::Geometry *geom, float x, float y, float angle
 	}
 
 	// use colors stored in geometry (horrible, horrible hack)
-	glEnableClientState(GL_COLOR_ARRAY);
-	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *)&v->r);
+	if (geom->hasVertexColors())
+	{
+		glEnableClientState(GL_COLOR_ARRAY);
+		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *)&v->r);
+	}
+
 	drawv(t, v, vcount, GL_TRIANGLES);
-	glDisableClientState(GL_COLOR_ARRAY);
+
+	if (geom->hasVertexColors())
+	{
+		glDisableClientState(GL_COLOR_ARRAY);
+		gl.setColor(gl.getColor());
+	}
+
 	delete[] v;
 }
 

+ 13 - 4
src/modules/graphics/opengl/Image.cpp

@@ -106,13 +106,22 @@ void Image::drawg(love::graphics::Geometry *geom, float x, float y, float angle,
 	static Matrix t;
 	t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
 
-	// use colors stored in geometry (horrible, horrible hack)
 	const vertex *v = geom->getVertexArray();
 
-	glEnableClientState(GL_COLOR_ARRAY);
-	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *)&v->r);
+	// use colors stored in geometry (horrible, horrible hack)
+	if (geom->hasVertexColors())
+	{
+		glEnableClientState(GL_COLOR_ARRAY);
+		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), (GLvoid *) &v[0].r);
+	}
+
 	drawv(t, v, geom->getVertexArraySize(), GL_TRIANGLES);
-	glDisableClientState(GL_COLOR_ARRAY);
+
+	if (geom->hasVertexColors())
+	{
+		glDisableClientState(GL_COLOR_ARRAY);
+		gl.setColor(gl.getColor());
+	}
 }
 
 void Image::uploadCompressedMipmaps()

+ 7 - 14
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -101,7 +101,7 @@ int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, fl
 	memcpy(sprite, image->getVertices(), sizeof(vertex)*4);
 
 	// Transform.
-	Matrix t;
+	static Matrix t;
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.transform(sprite, sprite, 4);
 
@@ -126,24 +126,17 @@ int SpriteBatch::addg(Geometry *geom, float x, float y, float a, float sx, float
 	if (geom->getNumVertices() != 4)
 		throw love::Exception("Can only add quadliteral geometries to SpriteBatch");
 
-	sprite[0] = geom->getVertex(0);
-	sprite[1] = geom->getVertex(1);
-	sprite[2] = geom->getVertex(2);
-	sprite[3] = geom->getVertex(3);
+	for (size_t i = 0; i < 4; i++)
+		sprite[i] = geom->getVertex(i);
 
 	// Transform.
-	Matrix t;
+	static Matrix t;
 	t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
 	t.transform(sprite, sprite, 4);
 
-	// color modulation
-	for (size_t i = 0; color && (i < 4); ++i)
-	{
-		sprite[i].r = (unsigned char)(double(sprite[i].r) * color->r / 255.);
-		sprite[i].g = (unsigned char)(double(sprite[i].g) * color->g / 255.);
-		sprite[i].b = (unsigned char)(double(sprite[i].b) * color->b / 255.);
-		sprite[i].a = (unsigned char)(double(sprite[i].a) * color->a / 255.);
-	}
+	// Set vertex colors to the constant color, if Geometry has no custom colors.
+	if (color && !geom->hasVertexColors())
+		setColorv(sprite, *color);
 
 	addv(sprite, (index == -1) ? next : index);
 

+ 3 - 0
src/modules/graphics/opengl/wrap_Geometry.cpp

@@ -90,6 +90,9 @@ int w_Geometry_setVertex(lua_State *L)
 		return luaL_error(L, e.what());
 	}
 
+	if (lua_gettop(L) > 6)
+		geom->setVertexColors(true);
+
 	return 0;
 }
 

+ 17 - 20
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -375,13 +375,14 @@ int w_newImage(lua_State *L)
 int w_newGeometry(lua_State *L)
 {
 	std::vector<vertex> vertices;
-	if (!lua_istable(L, 1))
-		return luaL_typerror(L, 1, "table");
+	luaL_checktype(L, 1, LUA_TTABLE);
 
 	size_t n = lua_objlen(L, 1);
 	if (n < 3)
 		return luaL_error(L, "Need at least three points to construct a geometry.");
 
+	bool hasvertexcolors = false;
+
 	vertices.reserve(n);
 	for (size_t i = 0; i < n; ++i)
 	{
@@ -390,31 +391,25 @@ int w_newGeometry(lua_State *L)
 		if (!lua_istable(L, -1))
 			return luaL_typerror(L, 1, "table of tables");
 
-		lua_rawgeti(L, -1, 1);
-		v.x = luaL_checknumber(L, -1);
-
-		lua_rawgeti(L, -2, 2);
-		v.y = luaL_checknumber(L, -1);
-
-		lua_rawgeti(L, -3, 3);
-		v.s = luaL_checknumber(L, -1);
+		if (lua_objlen(L, -1) > 4)
+			hasvertexcolors = true;
 
-		lua_rawgeti(L, -4, 4);
-		v.t = luaL_checknumber(L, -1);
+		for (int j = 1; j <= 8; j++)
+			lua_rawgeti(L, -j, j);
 
-		lua_rawgeti(L, -5, 5);
-		v.r = luaL_optint(L, -1, 255);
+		v.x = luaL_checknumber(L, -8);
+		v.y = luaL_checknumber(L, -7);
 
-		lua_rawgeti(L, -6, 6);
-		v.g = luaL_optint(L, -1, 255);
+		v.s = luaL_checknumber(L, -6);
+		v.t = luaL_checknumber(L, -5);
 
-		lua_rawgeti(L, -7, 7);
-		v.b = luaL_optint(L, -1, 255);
-
-		lua_rawgeti(L, -8, 8);
+		v.r = luaL_optint(L, -4, 255);
+		v.g = luaL_optint(L, -3, 255);
+		v.b = luaL_optint(L, -2, 255);
 		v.a = luaL_optint(L, -1, 255);
 
 		lua_pop(L, 9);
+
 		vertices.push_back(v);
 	}
 
@@ -431,6 +426,8 @@ int w_newGeometry(lua_State *L)
 	if (geom == 0)
 		return luaL_error(L, "Could not create geometry.");
 
+	geom->setVertexColors(hasvertexcolors);
+
 	luax_newtype(L, "Geometry", GRAPHICS_GEOMETRY_T, (void *)geom);
 	return 1;
 }