Browse Source

Add a variant of Mesh:setVertexMap which takes a Data object, an index data type (“uint16” or “uint32”), and an optional index count. Thanks Shell32!

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
734be1afad

+ 38 - 29
src/modules/graphics/opengl/Mesh.cpp

@@ -69,7 +69,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size
 	, ibo(nullptr)
 	, ibo(nullptr)
 	, useIndexBuffer(false)
 	, useIndexBuffer(false)
 	, elementCount(0)
 	, elementCount(0)
-	, elementDataType(0)
+	, elementDataType(INDEX_UINT16)
 	, drawMode(drawmode)
 	, drawMode(drawmode)
 	, rangeStart(-1)
 	, rangeStart(-1)
 	, rangeCount(-1)
 	, rangeCount(-1)
@@ -78,7 +78,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, const void *data, size
 	calculateAttributeSizes();
 	calculateAttributeSizes();
 
 
 	vertexCount = datasize / vertexStride;
 	vertexCount = datasize / vertexStride;
-	elementDataType = getGLDataTypeFromMax(vertexCount);
+	elementDataType = getIndexTypeFromMax(vertexCount);
 
 
 	if (vertexCount == 0)
 	if (vertexCount == 0)
 		throw love::Exception("Data size is too small for specified vertex attribute formats.");
 		throw love::Exception("Data size is too small for specified vertex attribute formats.");
@@ -96,7 +96,7 @@ Mesh::Mesh(const std::vector<AttribFormat> &vertexformat, int vertexcount, DrawM
 	, ibo(nullptr)
 	, ibo(nullptr)
 	, useIndexBuffer(false)
 	, useIndexBuffer(false)
 	, elementCount(0)
 	, elementCount(0)
-	, elementDataType(getGLDataTypeFromMax(vertexcount))
+	, elementDataType(getIndexTypeFromMax(vertexcount))
 	, drawMode(drawmode)
 	, drawMode(drawmode)
 	, rangeStart(-1)
 	, rangeStart(-1)
 	, rangeCount(-1)
 	, rangeCount(-1)
@@ -406,10 +406,10 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
 {
 {
 	size_t maxval = getVertexCount();
 	size_t maxval = getVertexCount();
 
 
-	GLenum datatype = getGLDataTypeFromMax(maxval);
+	IndexDataType datatype = getIndexTypeFromMax(maxval);
 
 
 	// Calculate the size in bytes of the index buffer data.
 	// Calculate the size in bytes of the index buffer data.
-	size_t size = map.size() * getGLDataTypeSize(datatype);
+	size_t size = map.size() * vertex::getIndexDataSize(datatype);
 
 
 	if (ibo && size > ibo->getSize())
 	if (ibo && size > ibo->getSize())
 	{
 	{
@@ -431,10 +431,10 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
 	// Fill the buffer with the index values from the vector.
 	// Fill the buffer with the index values from the vector.
 	switch (datatype)
 	switch (datatype)
 	{
 	{
-	case GL_UNSIGNED_SHORT:
+	case INDEX_UINT16:
 		copyToIndexBuffer<uint16>(map, ibomap, maxval);
 		copyToIndexBuffer<uint16>(map, ibomap, maxval);
 		break;
 		break;
-	case GL_UNSIGNED_INT:
+	case INDEX_UINT32:
 	default:
 	default:
 		copyToIndexBuffer<uint32>(map, ibomap, maxval);
 		copyToIndexBuffer<uint32>(map, ibomap, maxval);
 		break;
 		break;
@@ -443,6 +443,29 @@ void Mesh::setVertexMap(const std::vector<uint32> &map)
 	elementDataType = datatype;
 	elementDataType = datatype;
 }
 }
 
 
+void Mesh::setVertexMap(IndexDataType datatype, const void *data, size_t datasize)
+{
+	if (ibo && datasize > ibo->getSize())
+	{
+		delete ibo;
+		ibo = nullptr;
+	}
+
+	if (!ibo && datasize > 0)
+		ibo = new GLBuffer(datasize, nullptr, BUFFER_INDEX, vbo->getUsage());
+
+	elementCount = datasize / vertex::getIndexDataSize(datatype);
+
+	if (!ibo || elementCount == 0)
+		return;
+
+	GLBuffer::Mapper ibomap(*ibo);
+	memcpy(ibomap.get(), data, datasize);
+
+	useIndexBuffer = true;
+	elementDataType = datatype;
+}
+
 void Mesh::setVertexMap()
 void Mesh::setVertexMap()
 {
 {
 	useIndexBuffer = false;
 	useIndexBuffer = false;
@@ -476,10 +499,10 @@ bool Mesh::getVertexMap(std::vector<uint32> &map) const
 	// Fill the vector from the buffer.
 	// Fill the vector from the buffer.
 	switch (elementDataType)
 	switch (elementDataType)
 	{
 	{
-	case GL_UNSIGNED_SHORT:
+	case INDEX_UINT16:
 		copyFromIndexBuffer<uint16>(buffer, elementCount, map);
 		copyFromIndexBuffer<uint16>(buffer, elementCount, map);
 		break;
 		break;
-	case GL_UNSIGNED_INT:
+	case INDEX_UINT32:
 	default:
 	default:
 		copyFromIndexBuffer<uint32>(buffer, elementCount, map);
 		copyFromIndexBuffer<uint32>(buffer, elementCount, map);
 		break;
 		break;
@@ -626,8 +649,9 @@ void Mesh::draw(Graphics *gfx, const Matrix4 &m)
 
 
 		count = std::min(count, (int) elementCount - start);
 		count = std::min(count, (int) elementCount - start);
 
 
-		GLenum type = elementDataType;
-		const void *indices = ibo->getPointer(start * getGLDataTypeSize(type));
+		size_t elementsize = vertex::getIndexDataSize(elementDataType);
+		const void *indices = ibo->getPointer(start * elementsize);
+		GLenum type = OpenGL::getGLIndexDataType(elementDataType);
 
 
 		if (count > 0)
 		if (count > 0)
 			gl.drawElements(getGLDrawMode(drawMode), count, type, indices);
 			gl.drawElements(getGLDrawMode(drawMode), count, type, indices);
@@ -690,27 +714,12 @@ GLenum Mesh::getGLDataType(DataType type)
 	}
 	}
 }
 }
 
 
-GLenum Mesh::getGLDataTypeFromMax(size_t maxvalue)
+IndexDataType Mesh::getIndexTypeFromMax(size_t maxvalue)
 {
 {
 	if (maxvalue > LOVE_UINT16_MAX)
 	if (maxvalue > LOVE_UINT16_MAX)
-		return GL_UNSIGNED_INT;
+		return INDEX_UINT32;
 	else
 	else
-		return GL_UNSIGNED_SHORT;
-}
-
-size_t Mesh::getGLDataTypeSize(GLenum datatype)
-{
-	switch (datatype)
-	{
-	case GL_UNSIGNED_BYTE:
-		return sizeof(uint8);
-	case GL_UNSIGNED_SHORT:
-		return sizeof(uint16);
-	case GL_UNSIGNED_INT:
-		return sizeof(uint32);
-	default:
-		return 0;
-	}
+		return INDEX_UINT16;
 }
 }
 
 
 bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)
 bool Mesh::getConstant(const char *in, Mesh::DrawMode &out)

+ 4 - 3
src/modules/graphics/opengl/Mesh.h

@@ -150,6 +150,7 @@ public:
 	 * {0, 1, 2, 3, 4, ...}
 	 * {0, 1, 2, 3, 4, ...}
 	 **/
 	 **/
 	void setVertexMap(const std::vector<uint32> &map);
 	void setVertexMap(const std::vector<uint32> &map);
+	void setVertexMap(IndexDataType datatype, const void *data, size_t datasize);
 	void setVertexMap();
 	void setVertexMap();
 
 
 	/**
 	/**
@@ -215,10 +216,10 @@ private:
 
 
 	static size_t getAttribFormatSize(const AttribFormat &format);
 	static size_t getAttribFormatSize(const AttribFormat &format);
 
 
+	static IndexDataType getIndexTypeFromMax(size_t maxvalue);
+
 	static GLenum getGLDrawMode(DrawMode mode);
 	static GLenum getGLDrawMode(DrawMode mode);
 	static GLenum getGLDataType(DataType type);
 	static GLenum getGLDataType(DataType type);
-	static GLenum getGLDataTypeFromMax(size_t maxvalue);
-	static size_t getGLDataTypeSize(GLenum datatype);
 
 
 	std::vector<AttribFormat> vertexFormat;
 	std::vector<AttribFormat> vertexFormat;
 	std::vector<size_t> attributeSizes;
 	std::vector<size_t> attributeSizes;
@@ -238,7 +239,7 @@ private:
 	GLBuffer *ibo;
 	GLBuffer *ibo;
 	bool useIndexBuffer;
 	bool useIndexBuffer;
 	size_t elementCount;
 	size_t elementCount;
-	GLenum elementDataType;
+	IndexDataType elementDataType;
 
 
 	DrawMode drawMode;
 	DrawMode drawMode;
 
 

+ 13 - 0
src/modules/graphics/opengl/OpenGL.cpp

@@ -379,6 +379,19 @@ GLenum OpenGL::getGLBufferType(BufferType type)
 	}
 	}
 }
 }
 
 
+GLenum OpenGL::getGLIndexDataType(IndexDataType type)
+{
+	switch (type)
+	{
+	case INDEX_UINT16:
+		return GL_UNSIGNED_SHORT;
+	case INDEX_UINT32:
+		return GL_UNSIGNED_INT;
+	default:
+		return GL_ZERO;
+	}
+}
+
 GLenum OpenGL::getGLBufferUsage(vertex::Usage usage)
 GLenum OpenGL::getGLBufferUsage(vertex::Usage usage)
 {
 {
 	switch (usage)
 	switch (usage)

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

@@ -361,6 +361,7 @@ public:
 	Vendor getVendor() const;
 	Vendor getVendor() const;
 
 
 	static GLenum getGLBufferType(BufferType type);
 	static GLenum getGLBufferType(BufferType type);
+	static GLenum getGLIndexDataType(IndexDataType type);
 	static GLenum getGLBufferUsage(vertex::Usage usage);
 	static GLenum getGLBufferUsage(vertex::Usage usage);
 	static GLint getGLWrapMode(Texture::WrapMode wmode);
 	static GLint getGLWrapMode(Texture::WrapMode wmode);
 
 

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

@@ -371,6 +371,26 @@ int w_Mesh_setVertexMap(lua_State *L)
 		return 0;
 		return 0;
 	}
 	}
 
 
+	if (luax_istype(L, 2, Data::type))
+	{
+		Data *d = luax_totype<Data>(L, 2, Data::type);
+
+		const char *indextypestr = luaL_checkstring(L, 3);
+		IndexDataType indextype;
+		if (!vertex::getConstant(indextypestr, indextype))
+			return luaL_error(L, "Invalid index data type: %s", indextypestr);
+
+		size_t datatypesize = vertex::getIndexDataSize(indextype);
+
+		int indexcount = (int) luaL_optnumber(L, 4, d->getSize() / datatypesize);
+
+		if (indexcount < 1 || indexcount * datatypesize > d->getSize())
+			return luaL_error(L, "Invalid index count: %d", indexcount);
+
+		luax_catchexcept(L, [&]() { t->setVertexMap(indextype, d->getData(), indexcount * datatypesize); });
+		return 0;
+	}
+
 	bool is_table = lua_istable(L, 2);
 	bool is_table = lua_istable(L, 2);
 	int nargs = is_table ? (int) luax_objlen(L, 2) : lua_gettop(L) - 1;
 	int nargs = is_table ? (int) luax_objlen(L, 2) : lua_gettop(L) - 1;
 
 

+ 31 - 0
src/modules/graphics/vertex.cpp

@@ -53,6 +53,19 @@ size_t getFormatStride(CommonFormat format)
 	}
 	}
 }
 }
 
 
+size_t getIndexDataSize(IndexDataType type)
+{
+	switch (type)
+	{
+	case INDEX_UINT16:
+		return sizeof(uint16);
+	case INDEX_UINT32:
+		return sizeof(uint32);
+	default:
+		return 0;
+	}
+}
+
 int getIndexCount(TriangleIndexMode mode, int vertexCount)
 int getIndexCount(TriangleIndexMode mode, int vertexCount)
 {
 {
 	switch (mode)
 	switch (mode)
@@ -130,6 +143,14 @@ void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount,
 	fillIndicesT(mode, vertexStart, vertexCount, indices);
 	fillIndicesT(mode, vertexStart, vertexCount, indices);
 }
 }
 
 
+static StringMap<IndexDataType, INDEX_MAX_ENUM>::Entry indexTypeEntries[] =
+{
+	{ "uint16", INDEX_UINT16 },
+	{ "uint32", INDEX_UINT32 },
+};
+
+static StringMap<IndexDataType, INDEX_MAX_ENUM> indexTypes(indexTypeEntries, sizeof(indexTypeEntries));
+
 static StringMap<Usage, USAGE_MAX_ENUM>::Entry usageEntries[] =
 static StringMap<Usage, USAGE_MAX_ENUM>::Entry usageEntries[] =
 {
 {
 	{ "stream",  USAGE_STREAM  },
 	{ "stream",  USAGE_STREAM  },
@@ -139,6 +160,16 @@ static StringMap<Usage, USAGE_MAX_ENUM>::Entry usageEntries[] =
 
 
 static StringMap<Usage, USAGE_MAX_ENUM> usages(usageEntries, sizeof(usageEntries));
 static StringMap<Usage, USAGE_MAX_ENUM> usages(usageEntries, sizeof(usageEntries));
 
 
+bool getConstant(const char *in, IndexDataType &out)
+{
+	return indexTypes.find(in, out);
+}
+
+bool getConstant(IndexDataType in, const char *&out)
+{
+	return indexTypes.find(in, out);
+}
+
 bool getConstant(const char *in, Usage &out)
 bool getConstant(const char *in, Usage &out)
 {
 {
 	return usages.find(in, out);
 	return usages.find(in, out);

+ 11 - 0
src/modules/graphics/vertex.h

@@ -58,6 +58,13 @@ enum BufferType
 	BUFFER_MAX_ENUM
 	BUFFER_MAX_ENUM
 };
 };
 
 
+enum IndexDataType
+{
+	INDEX_UINT16,
+	INDEX_UINT32,
+	INDEX_MAX_ENUM
+};
+
 namespace vertex
 namespace vertex
 {
 {
 
 
@@ -115,12 +122,16 @@ struct XYf_STus_RGBAub
 };
 };
 
 
 size_t getFormatStride(CommonFormat format);
 size_t getFormatStride(CommonFormat format);
+size_t getIndexDataSize(IndexDataType type);
 
 
 int getIndexCount(TriangleIndexMode mode, int vertexCount);
 int getIndexCount(TriangleIndexMode mode, int vertexCount);
 
 
 void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, uint16 *indices);
 void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, uint16 *indices);
 void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices);
 void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices);
 
 
+bool getConstant(const char *in, IndexDataType &out);
+bool getConstant(IndexDataType in, const char *&out);
+
 bool getConstant(const char *in, Usage &out);
 bool getConstant(const char *in, Usage &out);
 bool getConstant(Usage in, const char *&out);
 bool getConstant(Usage in, const char *&out);