diff --git a/changes.txt b/changes.txt index eadd6f8c2..b0c9f616d 100644 --- a/changes.txt +++ b/changes.txt @@ -53,7 +53,7 @@ Released: N/A * Removed the "canvas", "shader", "npot", "subtractive", and "mipmap" Graphics Feature constant (the features always have guaranteed support now.) * Removed Canvas:getPixel (use Canvas:newImageData instead.) * Removed Canvas:clear (use love.graphics.clear instead.) - * Removed Mesh:setVertices and Mesh:getVertices. + * Removed Mesh:getVertices. * Removed Mesh:setVertexColors and Mesh:hasVertexColors (use Mesh:setAttributeEnabled("VertexColor", enable) instead.) * Removed functions deprecated in LOVE 0.9.x: * Removed Canvas:getType (replaced by Canvas:getFormat.) diff --git a/src/modules/graphics/opengl/Mesh.cpp b/src/modules/graphics/opengl/Mesh.cpp index 1294ef890..f157b3815 100644 --- a/src/modules/graphics/opengl/Mesh.cpp +++ b/src/modules/graphics/opengl/Mesh.cpp @@ -134,7 +134,7 @@ Mesh::~Mesh() delete ibo; delete vertexScratchBuffer; - for (const auto attrib : attachedAttributes) + for (const auto &attrib : attachedAttributes) { if (attrib.second.mesh != this) attrib.second.mesh->release(); @@ -367,6 +367,21 @@ void Mesh::attachAttribute(const std::string &name, Mesh *mesh) oldattrib.mesh->release(); } +void *Mesh::mapVertexData() +{ + GLBuffer::Bind bind(*vbo); + return vbo->map(); +} + +void Mesh::unmapVertexData() +{ + // Assume the whole buffer was modified. + GLBuffer::Bind bind(*vbo); + vbo->unmap(); + + vboUsedOffset = vboUsedSize = 0; +} + void Mesh::flush() { { diff --git a/src/modules/graphics/opengl/Mesh.h b/src/modules/graphics/opengl/Mesh.h index 9e3f4398f..ab608ea11 100644 --- a/src/modules/graphics/opengl/Mesh.h +++ b/src/modules/graphics/opengl/Mesh.h @@ -139,6 +139,9 @@ public: **/ void attachAttribute(const std::string &name, Mesh *mesh); + void *mapVertexData(); + void unmapVertexData(); + /** * Flushes all modified data to the GPU. **/ diff --git a/src/modules/graphics/opengl/wrap_Mesh.cpp b/src/modules/graphics/opengl/wrap_Mesh.cpp index 1825d1774..67dc6e35d 100644 --- a/src/modules/graphics/opengl/wrap_Mesh.cpp +++ b/src/modules/graphics/opengl/wrap_Mesh.cpp @@ -54,16 +54,12 @@ static inline char *writeAttributeData(lua_State *L, int startidx, Mesh::DataTyp switch (type) { case Mesh::DATA_BYTE: - data += writeData(L, startidx, components, data); - break; + return data + writeData(L, startidx, components, data); case Mesh::DATA_FLOAT: - data += writeData(L, startidx, components, data); - break; + return data + writeData(L, startidx, components, data); default: - break; + return data; } - - return data; } template @@ -81,16 +77,56 @@ static inline const char *readAttributeData(lua_State *L, Mesh::DataType type, i switch (type) { case Mesh::DATA_BYTE: - data += readData(L, components, data); - break; + return data + readData(L, components, data); case Mesh::DATA_FLOAT: - data += readData(L, components, data); - break; + return data + readData(L, components, data); default: - break; + return data; + } +} + +int w_Mesh_setVertices(lua_State *L) +{ + Mesh *t = luax_checkmesh(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + + size_t nvertices = lua_objlen(L, 2); + if (nvertices != t->getVertexCount()) + return luaL_error(L, "Invalid number of vertices (expected %d, got %d)", (int) t->getVertexCount(), (int) nvertices); + + const std::vector &vertexformat = t->getVertexFormat(); + + int ncomponents = 0; + for (const Mesh::AttribFormat &format : vertexformat) + ncomponents += format.components; + + char *data = (char *) t->mapVertexData(); + + for (size_t i = 0; i < nvertices; i++) + { + // get vertices[vertindex] + lua_rawgeti(L, 2, i + 1); + luaL_checktype(L, -1, LUA_TTABLE); + + // get vertices[vertindex][j] + for (int j = 1; j <= ncomponents; j++) + lua_rawgeti(L, -j, j); + + int idx = -ncomponents; + + for (const Mesh::AttribFormat &format : vertexformat) + { + // Fetch the values from Lua and store them in data buffer. + data = writeAttributeData(L, idx, format.type, format.components, data); + + idx += format.components; + } + + lua_pop(L, ncomponents + 1); } - return data; + t->unmapVertexData(); + return 0; } int w_Mesh_setVertex(lua_State *L) @@ -414,6 +450,7 @@ int w_Mesh_getDrawRange(lua_State *L) static const luaL_Reg functions[] = { + { "setVertices", w_Mesh_setVertices }, { "setVertex", w_Mesh_setVertex }, { "getVertex", w_Mesh_getVertex }, { "setVertexAttribute", w_Mesh_setVertexAttribute }, diff --git a/src/modules/graphics/opengl/wrap_Mesh.h b/src/modules/graphics/opengl/wrap_Mesh.h index e63882e03..5ba254cad 100644 --- a/src/modules/graphics/opengl/wrap_Mesh.h +++ b/src/modules/graphics/opengl/wrap_Mesh.h @@ -33,6 +33,7 @@ namespace opengl { Mesh *luax_checkmesh(lua_State *L, int idx); +int w_Mesh_setVertices(lua_State *L); int w_Mesh_setVertex(lua_State *L); int w_Mesh_getVertex(lua_State *L); int w_Mesh_setVertexAttribute(lua_State *L);