mirror of https://github.com/bjornbytes/lovr.git
Meshes use mapped buffers;
This commit is contained in:
parent
b417df1de9
commit
94a5dab7b5
|
@ -575,15 +575,17 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
|
|||
Mesh* mesh = lovrMeshCreate(size, format.length ? &format : NULL, *drawMode, *usage);
|
||||
|
||||
if (dataIndex) {
|
||||
int count = lua_objlen(L, dataIndex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
|
||||
char* vertex = lovrMeshMap(mesh, 0, count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, dataIndex, i + 1);
|
||||
if (!lua_istable(L, -1)) {
|
||||
return luaL_error(L, "Vertex information should be specified as a table");
|
||||
}
|
||||
|
||||
int component = 0;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
for (int j = 0; j < format.length; j++) {
|
||||
MeshAttribute attribute = format.data[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
|
@ -598,7 +600,6 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
|
|||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, i, lovrMeshGetScratchVertex(mesh));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,8 +82,7 @@ int l_lovrMeshGetVertexCount(lua_State* L) {
|
|||
int l_lovrMeshGetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, index, vertex);
|
||||
char* vertex = lovrMeshMap(mesh, index, 1);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
int total = 0;
|
||||
|
@ -107,13 +106,14 @@ int l_lovrMeshGetVertex(lua_State* L) {
|
|||
int l_lovrMeshSetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
|
||||
if (index < 0 || index >= mesh->size) {
|
||||
if (index < 0 || index >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", index + 1);
|
||||
}
|
||||
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
char* vertex = lovrMeshMap(mesh, index, 1);
|
||||
|
||||
// Unwrap table
|
||||
int arg = 3;
|
||||
if (lua_istable(L, 3)) {
|
||||
|
@ -136,7 +136,6 @@ int l_lovrMeshSetVertex(lua_State* L) {
|
|||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, index, lovrMeshGetScratchVertex(mesh));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -144,16 +143,16 @@ int l_lovrMeshGetVertexAttribute(lua_State* L) {
|
|||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, vertexIndex, vertex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
|
||||
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
char* vertex = lovrMeshMap(mesh, vertexIndex, 1);
|
||||
|
||||
MeshAttribute attribute;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
attribute = format.data[i];
|
||||
|
@ -178,16 +177,16 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
|||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, vertexIndex, vertex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
|
||||
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
char* vertex = lovrMeshMap(mesh, vertexIndex, 1);
|
||||
|
||||
int arg = 4;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
MeshAttribute attribute = format.data[i];
|
||||
|
@ -205,7 +204,6 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
|||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, vertexIndex, lovrMeshGetScratchVertex(mesh));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,12 +212,9 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int vertexCount = lua_objlen(L, 2);
|
||||
int start = luaL_optnumber(L, 3, 1) - 1;
|
||||
|
||||
if (vertexCount > lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Too many vertices for Mesh (max is %d, got %d)\n", lovrMeshGetVertexCount(mesh), vertexCount);
|
||||
}
|
||||
|
||||
char* vertices = malloc(mesh->stride * vertexCount);
|
||||
void* vertices = lovrMeshMap(mesh, start, vertexCount);
|
||||
char* vertex = vertices;
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
|
@ -241,8 +236,6 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrMeshSetVertices(mesh, vertices, mesh->stride * vertexCount);
|
||||
free(vertices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -285,7 +278,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
}
|
||||
|
||||
int index = lua_tointeger(L, -1);
|
||||
if (index > mesh->size || index < 0) {
|
||||
if (index > lovrMeshGetVertexCount(mesh) || index < 0) {
|
||||
free(indices);
|
||||
return luaL_error(L, "Invalid vertex map value: %d", index);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
|
|||
mesh->attributesDirty = 0;
|
||||
}
|
||||
|
||||
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||
Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||
Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy);
|
||||
if (!mesh) return NULL;
|
||||
|
||||
|
@ -65,10 +65,8 @@ Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUs
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mesh->size = size;
|
||||
mesh->count = count;
|
||||
mesh->stride = stride;
|
||||
mesh->data = malloc(mesh->size * mesh->stride);
|
||||
mesh->scratchVertex = malloc(mesh->stride);
|
||||
mesh->enabledAttributes = ~0;
|
||||
mesh->attributesDirty = 1;
|
||||
mesh->drawMode = drawMode;
|
||||
|
@ -78,13 +76,13 @@ Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUs
|
|||
mesh->ibo = 0;
|
||||
mesh->isRangeEnabled = 0;
|
||||
mesh->rangeStart = 0;
|
||||
mesh->rangeCount = mesh->size;
|
||||
mesh->rangeCount = mesh->count;
|
||||
mesh->texture = NULL;
|
||||
mesh->lastShader = NULL;
|
||||
|
||||
glGenBuffers(1, &mesh->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->count * mesh->stride, NULL, mesh->usage);
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
glGenBuffers(1, &mesh->ibo);
|
||||
|
||||
|
@ -100,12 +98,14 @@ void lovrMeshDestroy(const Ref* ref) {
|
|||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
vec_deinit(&mesh->map);
|
||||
vec_deinit(&mesh->format);
|
||||
free(mesh->scratchVertex);
|
||||
free(mesh->data);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
||||
if (mesh->isMapped) {
|
||||
lovrMeshUnmap(mesh);
|
||||
}
|
||||
|
||||
int usingIbo = mesh->map.length > 0;
|
||||
|
||||
lovrGraphicsPush();
|
||||
|
@ -116,17 +116,15 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
|||
glBindVertexArray(mesh->vao);
|
||||
lovrMeshBindAttributes(mesh);
|
||||
|
||||
// Determine range of vertices to be rendered and whether we're using an IBO or not
|
||||
int start, count;
|
||||
if (mesh->isRangeEnabled) {
|
||||
start = mesh->rangeStart;
|
||||
count = mesh->rangeCount;
|
||||
} else {
|
||||
start = 0;
|
||||
count = usingIbo ? mesh->map.length : mesh->size;
|
||||
count = usingIbo ? mesh->map.length : mesh->count;
|
||||
}
|
||||
|
||||
// Render! Use the IBO if a draw range is set
|
||||
if (usingIbo) {
|
||||
uintptr_t startAddress = (uintptr_t) start;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
|
||||
|
@ -152,41 +150,13 @@ int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode) {
|
|||
}
|
||||
|
||||
int lovrMeshGetVertexCount(Mesh* mesh) {
|
||||
return mesh->size;
|
||||
return mesh->count;
|
||||
}
|
||||
|
||||
int lovrMeshGetVertexSize(Mesh* mesh) {
|
||||
return mesh->stride;
|
||||
}
|
||||
|
||||
void* lovrMeshGetScratchVertex(Mesh* mesh) {
|
||||
return mesh->scratchVertex;
|
||||
}
|
||||
|
||||
void lovrMeshGetVertex(Mesh* mesh, int index, void* dest) {
|
||||
if (index >= mesh->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(dest, (char*) mesh->data + index * mesh->stride, mesh->stride);
|
||||
}
|
||||
|
||||
void lovrMeshSetVertex(Mesh* mesh, int index, void* vertex) {
|
||||
memcpy((char*) mesh->data + index * mesh->stride, vertex, mesh->stride);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
}
|
||||
|
||||
void lovrMeshSetVertices(Mesh* mesh, void* vertices, int size) {
|
||||
if (size > mesh->size * mesh->stride) {
|
||||
error("Mesh is not big enough");
|
||||
}
|
||||
|
||||
memcpy(mesh->data, vertices, size);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
}
|
||||
|
||||
unsigned int* lovrMeshGetVertexMap(Mesh* mesh, int* count) {
|
||||
*count = mesh->map.length;
|
||||
return mesh->map.data;
|
||||
|
@ -248,7 +218,7 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) {
|
|||
}
|
||||
|
||||
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count) {
|
||||
if (start < 0 || count < 0 || start + count > mesh->size) {
|
||||
if (start < 0 || count < 0 || start + count > mesh->count) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -273,3 +243,25 @@ void lovrMeshSetTexture(Mesh* mesh, Texture* texture) {
|
|||
lovrRetain(&mesh->texture->ref);
|
||||
}
|
||||
}
|
||||
|
||||
void* lovrMeshMap(Mesh* mesh, int start, int count) {
|
||||
|
||||
// Unmap because the mapped ranges aren't necessarily the same. Could be improved.
|
||||
if (mesh->isMapped && (mesh->mapStart != start || mesh->mapCount != count)) {
|
||||
lovrMeshUnmap(mesh);
|
||||
}
|
||||
|
||||
mesh->isMapped = 1;
|
||||
mesh->mapStart = start;
|
||||
mesh->mapCount = count;
|
||||
GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
return glMapBufferRange(GL_ARRAY_BUFFER, start * mesh->stride, count * mesh->stride, access);
|
||||
}
|
||||
|
||||
void lovrMeshUnmap(Mesh* mesh) {
|
||||
if (mesh->isMapped) {
|
||||
mesh->isMapped = 0;
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,13 @@ typedef vec_t(MeshAttribute) MeshFormat;
|
|||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
int size;
|
||||
int count;
|
||||
int stride;
|
||||
void* data;
|
||||
void* scratchVertex;
|
||||
int enabledAttributes;
|
||||
int attributesDirty;
|
||||
int isMapped;
|
||||
int mapStart;
|
||||
int mapCount;
|
||||
MeshFormat format;
|
||||
MeshDrawMode drawMode;
|
||||
MeshUsage usage;
|
||||
|
@ -55,7 +56,7 @@ typedef struct {
|
|||
Shader* lastShader;
|
||||
} Mesh;
|
||||
|
||||
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
void lovrMeshDestroy(const Ref* ref);
|
||||
void lovrMeshDraw(Mesh* mesh, mat4 transform);
|
||||
MeshFormat lovrMeshGetVertexFormat(Mesh* mesh);
|
||||
|
@ -63,10 +64,6 @@ MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);
|
|||
int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode);
|
||||
int lovrMeshGetVertexCount(Mesh* mesh);
|
||||
int lovrMeshGetVertexSize(Mesh* mesh);
|
||||
void* lovrMeshGetScratchVertex(Mesh* mesh);
|
||||
void lovrMeshGetVertex(Mesh* mesh, int index, void* dest);
|
||||
void lovrMeshSetVertex(Mesh* mesh, int index, void* vertex);
|
||||
void lovrMeshSetVertices(Mesh* mesh, void* vertices, int size);
|
||||
unsigned int* lovrMeshGetVertexMap(Mesh* mesh, int* count);
|
||||
void lovrMeshSetVertexMap(Mesh* mesh, unsigned int* map, int count);
|
||||
int lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name);
|
||||
|
@ -77,3 +74,5 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count);
|
|||
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count);
|
||||
Texture* lovrMeshGetTexture(Mesh* mesh);
|
||||
void lovrMeshSetTexture(Mesh* mesh, Texture* texture);
|
||||
void* lovrMeshMap(Mesh* mesh, int start, int count);
|
||||
void lovrMeshUnmap(Mesh* mesh);
|
||||
|
|
|
@ -91,7 +91,8 @@ Model* lovrModelCreate(ModelData* modelData) {
|
|||
}
|
||||
|
||||
model->mesh = lovrMeshCreate(vertices.length / components, &format, MESH_TRIANGLES, MESH_STATIC);
|
||||
lovrMeshSetVertices(model->mesh, (void*) vertices.data, vertices.length * sizeof(float));
|
||||
void* data = lovrMeshMap(model->mesh, 0, vertices.length / components);
|
||||
memcpy(data, vertices.data, vertices.length * sizeof(float));
|
||||
lovrMeshSetVertexMap(model->mesh, indices.data, indices.length);
|
||||
|
||||
model->texture = NULL;
|
||||
|
|
Loading…
Reference in New Issue