Browse Source

Added Mesh:setDrawRange(min, max) and Mesh:getDrawRange().
If no vertex map is set, this restricts the drawn vertices to those whose indices in the vertex array are between [min, max] inclusive.
If a vertex map is set, this restricts the values used in the vertex map to those whose indices in the vertex map array are between [min, max] inclusive.

Added Mesh constructor variant: love.graphics.newMesh(vertexcount, texture, drawmode). Creates a Mesh with a certain number of vertices with x,y,u,v,r,g,b,a values of (0,0,0,0,255,255,255,255).

Alex Szpakowski 11 years ago
parent
commit
ba7e69d776

+ 5 - 0
src/modules/graphics/opengl/Graphics.cpp

@@ -460,6 +460,11 @@ Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode
 	return new Mesh(vertices, mode);
 	return new Mesh(vertices, mode);
 }
 }
 
 
+Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode mode)
+{
+	return new Mesh(vertexcount, mode);
+}
+
 void Graphics::setColor(const Color &c)
 void Graphics::setColor(const Color &c)
 {
 {
 	gl.setColor(c);
 	gl.setColor(c);

+ 1 - 0
src/modules/graphics/opengl/Graphics.h

@@ -213,6 +213,7 @@ public:
 	Shader *newShader(const Shader::ShaderSources &sources);
 	Shader *newShader(const Shader::ShaderSources &sources);
 
 
 	Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
 	Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
+	Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
 
 
 	/**
 	/**
 	 * Sets the foreground color.
 	 * Sets the foreground color.

+ 78 - 11
src/modules/graphics/opengl/Mesh.cpp

@@ -23,6 +23,9 @@
 #include "common/Matrix.h"
 #include "common/Matrix.h"
 #include "common/Exception.h"
 #include "common/Exception.h"
 
 
+// C++
+#include <algorithm>
+
 namespace love
 namespace love
 {
 {
 namespace graphics
 namespace graphics
@@ -37,6 +40,8 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
 	, element_count(0)
 	, element_count(0)
 	, instance_count(1)
 	, instance_count(1)
 	, draw_mode(mode)
 	, draw_mode(mode)
+	, range_min(-1)
+	, range_max(-1)
 	, texture(nullptr)
 	, texture(nullptr)
 	, colors_enabled(false)
 	, colors_enabled(false)
 	, wireframe(false)
 	, wireframe(false)
@@ -44,6 +49,35 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
 	setVertices(verts);
 	setVertices(verts);
 }
 }
 
 
+Mesh::Mesh(int vertexcount, Mesh::DrawMode mode)
+	: vbo(nullptr)
+	, vertex_count(0)
+	, ibo(nullptr)
+	, element_count(0)
+	, draw_mode(mode)
+	, range_min(-1)
+	, range_max(-1)
+	, texture(nullptr)
+	, colors_enabled(false)
+	, wireframe(false)
+{
+	if (vertexcount < 1)
+		throw love::Exception("Invalid number of vertices.");
+
+	std::vector<Vertex> verts(vertexcount);
+
+	// Default-initialized vertices should have a white opaque color.
+	for (size_t i = 0; i < verts.size(); i++)
+	{
+		verts[i].r = 255;
+		verts[i].g = 255;
+		verts[i].b = 255;
+		verts[i].a = 255;
+	}
+
+	setVertices(verts);
+}
+
 Mesh::~Mesh()
 Mesh::~Mesh()
 {
 {
 	delete vbo;
 	delete vbo;
@@ -163,7 +197,7 @@ const uint32 *Mesh::getVertexMap() const
 		return (uint32 *) ibo->map();
 		return (uint32 *) ibo->map();
 	}
 	}
 
 
-	return 0;
+	return nullptr;
 }
 }
 
 
 size_t Mesh::getVertexMapCount() const
 size_t Mesh::getVertexMapCount() const
@@ -173,10 +207,7 @@ size_t Mesh::getVertexMapCount() const
 
 
 void Mesh::setInstanceCount(int count)
 void Mesh::setInstanceCount(int count)
 {
 {
-	if (count < 1)
-		count = 1;
-
-	instance_count = count;
+	instance_count = std::max(count, 1);
 }
 }
 
 
 int Mesh::getInstanceCount() const
 int Mesh::getInstanceCount() const
@@ -217,6 +248,26 @@ Mesh::DrawMode Mesh::getDrawMode() const
 	return draw_mode;
 	return draw_mode;
 }
 }
 
 
+void Mesh::setDrawRange(int min, int max)
+{
+	if (min < 0 || max < 0 || min > max)
+		throw love::Exception("Invalid draw range.");
+
+	range_min = min;
+	range_max = max;
+}
+
+void Mesh::setDrawRange()
+{
+	range_min = range_max = -1;
+}
+
+void Mesh::getDrawRange(int &min, int &max) const
+{
+	min = range_min;
+	max = range_max;
+}
+
 void Mesh::setVertexColors(bool enable)
 void Mesh::setVertexColors(bool enable)
 {
 {
 	colors_enabled = enable;
 	colors_enabled = enable;
@@ -290,21 +341,37 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
 		// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
 		// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
 		ibo->unmap();
 		ibo->unmap();
 
 
-		const void *indices = ibo->getPointer(0);
-		const GLenum type = GL_UNSIGNED_INT;
+		int max = element_count - 1;
+		if (range_max >= 0)
+			max = std::min(std::max(range_max, 0), (int) element_count - 1);
+
+		int min = 0;
+		if (range_min >= 0)
+			min = std::min(std::max(range_min, 0), max);
+
+		const void *indices = ibo->getPointer(min * sizeof(uint32));
+		GLenum type = GL_UNSIGNED_INT;
 
 
 		if (instance_count > 1)
 		if (instance_count > 1)
-			gl.drawElementsInstanced(mode, element_count, type, indices, instance_count);
+			gl.drawElementsInstanced(mode, max - min + 1, type, indices, instance_count);
 		else
 		else
-			glDrawElements(mode, element_count, type, indices);
+			glDrawElements(mode, max - min + 1, type, indices);
 	}
 	}
 	else
 	else
 	{
 	{
+		int max = vertex_count - 1;
+		if (range_max >= 0)
+			max = std::min(std::max(range_max, 0), (int) vertex_count - 1);
+
+		int min = 0;
+		if (range_min >= 0)
+			min = std::min(std::max(range_min, 0), max);
+
 		// Normal non-indexed drawing (no custom vertex map.)
 		// Normal non-indexed drawing (no custom vertex map.)
 		if (instance_count > 1)
 		if (instance_count > 1)
-			gl.drawArraysInstanced(mode, 0, vertex_count, instance_count);
+			gl.drawArraysInstanced(mode, min, max - min + 1, instance_count);
 		else
 		else
-			glDrawArrays(mode, 0, vertex_count);
+			glDrawArrays(mode, min, max - min + 1);
 	}
 	}
 
 
 	if (wireframe)
 	if (wireframe)

+ 18 - 0
src/modules/graphics/opengl/Mesh.h

@@ -22,6 +22,7 @@
 #define LOVE_GRAPHICS_OPENGL_MESH_H
 #define LOVE_GRAPHICS_OPENGL_MESH_H
 
 
 // LOVE
 // LOVE
+#include "common/config.h"
 #include "common/int.h"
 #include "common/int.h"
 #include "common/math.h"
 #include "common/math.h"
 #include "common/StringMap.h"
 #include "common/StringMap.h"
@@ -64,6 +65,16 @@ public:
 	 * @param mode The draw mode to use when drawing the Mesh.
 	 * @param mode The draw mode to use when drawing the Mesh.
 	 **/
 	 **/
 	Mesh(const std::vector<Vertex> &verts, DrawMode mode = DRAW_MODE_FAN);
 	Mesh(const std::vector<Vertex> &verts, DrawMode mode = DRAW_MODE_FAN);
+
+	/**
+	 * Constructor.
+	 * Creates a Mesh with a certain number of default-initialized (hidden)
+	 * vertices.
+	 * @param vertexcount The number of vertices to use in the Mesh.
+	 * @param mode The draw mode to use when drawing the Mesh.
+	 **/
+	Mesh(int vertexcount, DrawMode mode = DRAW_MODE_FAN);
+
 	virtual ~Mesh();
 	virtual ~Mesh();
 
 
 	/**
 	/**
@@ -140,6 +151,10 @@ public:
 	void setDrawMode(DrawMode mode);
 	void setDrawMode(DrawMode mode);
 	DrawMode getDrawMode() const;
 	DrawMode getDrawMode() const;
 
 
+	void setDrawRange(int min, int max);
+	void setDrawRange();
+	void getDrawRange(int &min, int &max) const;
+
 	/**
 	/**
 	 * Sets whether per-vertex colors are enabled. If this is disabled, the
 	 * Sets whether per-vertex colors are enabled. If this is disabled, the
 	 * global color (love.graphics.setColor) will be used for the entire Mesh.
 	 * global color (love.graphics.setColor) will be used for the entire Mesh.
@@ -178,6 +193,9 @@ private:
 
 
 	DrawMode draw_mode;
 	DrawMode draw_mode;
 
 
+	int range_min;
+	int range_max;
+
 	Texture *texture;
 	Texture *texture;
 
 
 	// Whether the per-vertex colors are used when drawing.
 	// Whether the per-vertex colors are used when drawing.

+ 43 - 33
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -440,8 +440,10 @@ int w_newShader(lua_State *L)
 
 
 int w_newMesh(lua_State *L)
 int w_newMesh(lua_State *L)
 {
 {
-	// Check first argument: mandatory table of vertices.
-	luaL_checktype(L, 1, LUA_TTABLE);
+	// Check first argument: table of vertices or number of vertices.
+	int ttype = lua_type(L, 1);
+	if (ttype != LUA_TTABLE && ttype != LUA_TNUMBER)
+		luaL_argerror(L, 1, "table or number expected");
 
 
 	// Second argument: optional texture.
 	// Second argument: optional texture.
 	Texture *tex = nullptr;
 	Texture *tex = nullptr;
@@ -456,52 +458,60 @@ int w_newMesh(lua_State *L)
 	if (str && !Mesh::getConstant(str, mode))
 	if (str && !Mesh::getConstant(str, mode))
 		return luaL_error(L, "Invalid mesh draw mode: %s", str);
 		return luaL_error(L, "Invalid mesh draw mode: %s", str);
 
 
-	size_t vertex_count = lua_objlen(L, 1);
-	std::vector<Vertex> vertices;
-	vertices.reserve(vertex_count);
-
-	bool use_colors = false;
+	Mesh *t = nullptr;
 
 
-	// Get the vertices from the table.
-	for (size_t i = 1; i <= vertex_count; i++)
+	if (ttype == LUA_TTABLE)
 	{
 	{
-		lua_rawgeti(L, 1, i);
+		size_t vertex_count = lua_objlen(L, 1);
+		std::vector<Vertex> vertices;
+		vertices.reserve(vertex_count);
 
 
-		if (lua_type(L, -1) != LUA_TTABLE)
-			return luax_typerror(L, 1, "table of tables");
+		bool use_colors = false;
 
 
-		for (int j = 1; j <= 8; j++)
-			lua_rawgeti(L, -j, j);
+		// Get the vertices from the table.
+		for (size_t i = 1; i <= vertex_count; i++)
+		{
+			lua_rawgeti(L, 1, i);
 
 
-		Vertex v;
+			if (lua_type(L, -1) != LUA_TTABLE)
+				return luax_typerror(L, 1, "table of tables");
 
 
-		v.x = (float) luaL_checknumber(L, -8);
-		v.y = (float) luaL_checknumber(L, -7);
+			for (int j = 1; j <= 8; j++)
+				lua_rawgeti(L, -j, j);
 
 
-		v.s = (float) luaL_checknumber(L, -6);
-		v.t = (float) luaL_checknumber(L, -5);
+			Vertex v;
 
 
-		v.r = (unsigned char) luaL_optinteger(L, -4, 255);
-		v.g = (unsigned char) luaL_optinteger(L, -3, 255);
-		v.b = (unsigned char) luaL_optinteger(L, -2, 255);
-		v.a = (unsigned char) luaL_optinteger(L, -1, 255);
+			v.x = (float) luaL_checknumber(L, -8);
+			v.y = (float) luaL_checknumber(L, -7);
 
 
-		// Enable per-vertex coloring if any color is not the default.
-		if (!use_colors && (v.r != 255 || v.g != 255 || v.b != 255 || v.a != 255))
-			use_colors = true;
+			v.s = (float) luaL_checknumber(L, -6);
+			v.t = (float) luaL_checknumber(L, -5);
 
 
-		lua_pop(L, 9);
-		vertices.push_back(v);
-	}
+			v.r = (unsigned char) luaL_optinteger(L, -4, 255);
+			v.g = (unsigned char) luaL_optinteger(L, -3, 255);
+			v.b = (unsigned char) luaL_optinteger(L, -2, 255);
+			v.a = (unsigned char) luaL_optinteger(L, -1, 255);
 
 
-	Mesh *t = nullptr;
-	EXCEPT_GUARD(t = instance->newMesh(vertices, mode);)
+			// Enable per-vertex coloring if any color is not the default.
+			if (!use_colors && (v.r != 255 || v.g != 255 || v.b != 255 || v.a != 255))
+				use_colors = true;
+
+			lua_pop(L, 9);
+			vertices.push_back(v);
+		}
+
+		EXCEPT_GUARD(t = instance->newMesh(vertices, mode);)
+		t->setVertexColors(use_colors);
+	}
+	else
+	{
+		int count = luaL_checkint(L, 1);
+		EXCEPT_GUARD(t = instance->newMesh(count, mode);)
+	}
 
 
 	if (tex)
 	if (tex)
 		t->setTexture(tex);
 		t->setTexture(tex);
 
 
-	t->setVertexColors(use_colors);
-
 	luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
 	luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
 	return 1;
 	return 1;
 }
 }

+ 34 - 0
src/modules/graphics/opengl/wrap_Mesh.cpp

@@ -315,6 +315,38 @@ int w_Mesh_getDrawMode(lua_State *L)
 	return 1;
 	return 1;
 }
 }
 
 
+int w_Mesh_setDrawRange(lua_State *L)
+{
+	Mesh *t = luax_checkmesh(L, 1);
+
+	if (lua_isnoneornil(L, 2))
+		t->setDrawRange();
+	else
+	{
+		int rangemin = luaL_checkint(L, 2) - 1;
+		int rangemax = luaL_checkint(L, 3) - 1;
+		EXCEPT_GUARD(t->setDrawRange(rangemin, rangemax);)
+	}
+
+	return 0;
+}
+
+int w_Mesh_getDrawRange(lua_State *L)
+{
+	Mesh *t = luax_checkmesh(L, 1);
+
+	int rangemin = -1;
+	int rangemax = -1;
+	t->getDrawRange(rangemin, rangemax);
+
+	if (rangemin < 0 || rangemax < 0)
+		return 0;
+
+	lua_pushinteger(L, rangemin + 1);
+	lua_pushinteger(L, rangemax + 1);
+	return 2;
+}
+
 int w_Mesh_setVertexColors(lua_State *L)
 int w_Mesh_setVertexColors(lua_State *L)
 {
 {
 	Mesh *t = luax_checkmesh(L, 1);
 	Mesh *t = luax_checkmesh(L, 1);
@@ -358,6 +390,8 @@ static const luaL_Reg functions[] =
 	{ "getTexture", w_Mesh_getTexture },
 	{ "getTexture", w_Mesh_getTexture },
 	{ "setDrawMode", w_Mesh_setDrawMode },
 	{ "setDrawMode", w_Mesh_setDrawMode },
 	{ "getDrawMode", w_Mesh_getDrawMode },
 	{ "getDrawMode", w_Mesh_getDrawMode },
+	{ "setDrawRange", w_Mesh_setDrawRange },
+	{ "getDrawRange", w_Mesh_getDrawRange },
 	{ "setVertexColors", w_Mesh_setVertexColors },
 	{ "setVertexColors", w_Mesh_setVertexColors },
 	{ "hasVertexColors", w_Mesh_hasVertexColors },
 	{ "hasVertexColors", w_Mesh_hasVertexColors },
 	{ "setWireframe", w_Mesh_setWireframe },
 	{ "setWireframe", w_Mesh_setWireframe },

+ 2 - 0
src/modules/graphics/opengl/wrap_Mesh.h

@@ -47,6 +47,8 @@ int w_Mesh_setTexture(lua_State *L);
 int w_Mesh_getTexture(lua_State *L);
 int w_Mesh_getTexture(lua_State *L);
 int w_Mesh_setDrawMode(lua_State *L);
 int w_Mesh_setDrawMode(lua_State *L);
 int w_Mesh_getDrawMode(lua_State *L);
 int w_Mesh_getDrawMode(lua_State *L);
+int w_Mesh_setDrawRange(lua_State *L);
+int w_Mesh_getDrawRange(lua_State *L);
 int w_Mesh_setVertexColors(lua_State *L);
 int w_Mesh_setVertexColors(lua_State *L);
 int w_Mesh_hasVertexColors(lua_State *L);
 int w_Mesh_hasVertexColors(lua_State *L);
 int w_Mesh_setWireframe(lua_State *L);
 int w_Mesh_setWireframe(lua_State *L);