From 2c0d85a84a73c0957c447887a28b896d9992e998 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 22 Oct 2017 07:04:52 -0700 Subject: [PATCH] Use UNSIGNED_SHORT for indices when possible; --- src/api/types/mesh.c | 13 ++++++++----- src/graphics/mesh.c | 41 +++++++++++++++++++++++------------------ src/graphics/mesh.h | 8 +++++--- src/loaders/model.c | 16 +++++++++++++--- src/loaders/model.h | 2 +- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/api/types/mesh.c b/src/api/types/mesh.c index 33029fdb..317c9b55 100644 --- a/src/api/types/mesh.c +++ b/src/api/types/mesh.c @@ -273,27 +273,30 @@ int l_lovrMeshSetVertexMap(lua_State* L) { luaL_checktype(L, 2, LUA_TTABLE); int count = lua_objlen(L, 2); - unsigned int* indices = malloc(count * sizeof(unsigned int)); + int indexSize = mesh->indexSize; + void* indices = realloc(lovrMeshGetVertexMap(mesh, NULL), indexSize * count); for (int i = 0; i < count; i++) { lua_rawgeti(L, 2, i + 1); if (!lua_isnumber(L, -1)) { - free(indices); return luaL_error(L, "Mesh vertex map index #%d must be numeric", i); } int index = lua_tointeger(L, -1); if (index > lovrMeshGetVertexCount(mesh) || index < 1) { - free(indices); return luaL_error(L, "Invalid vertex map value: %d", index); } - indices[i] = index - 1; + if (indexSize == sizeof(uint16_t)) { + *(((uint16_t*) indices) + i) = index - 1; + } else if (indexSize == sizeof(uint32_t)) { + *(((uint32_t*) indices) + i) = index - 1; + } + lua_pop(L, 1); } lovrMeshSetVertexMap(mesh, indices, count); - free(indices); return 0; } diff --git a/src/graphics/mesh.c b/src/graphics/mesh.c index fa38710f..ca45c28f 100644 --- a/src/graphics/mesh.c +++ b/src/graphics/mesh.c @@ -1,5 +1,6 @@ #include "graphics/mesh.h" #include "graphics/graphics.h" +#include #include #include @@ -43,7 +44,6 @@ Mesh* lovrMeshCreate(size_t count, MeshFormat* format, MeshDrawMode drawMode, Me Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy); if (!mesh) return NULL; - vec_init(&mesh->map); vec_init(&mesh->format); if (format) { @@ -79,6 +79,9 @@ Mesh* lovrMeshCreate(size_t count, MeshFormat* format, MeshDrawMode drawMode, Me mesh->vao = 0; mesh->vbo = 0; mesh->ibo = 0; + mesh->indices = NULL; + mesh->indexCount = 0; + mesh->indexSize = count > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t); mesh->isRangeEnabled = 0; mesh->rangeStart = 0; mesh->rangeCount = mesh->count; @@ -102,8 +105,8 @@ void lovrMeshDestroy(const Ref* ref) { glDeleteBuffers(1, &mesh->vbo); glDeleteBuffers(1, &mesh->ibo); glDeleteVertexArrays(1, &mesh->vao); - vec_deinit(&mesh->map); vec_deinit(&mesh->format); + free(mesh->indices); #ifdef EMSCRIPTEN free(mesh->data); #endif @@ -126,9 +129,10 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) { lovrMeshBindAttributes(mesh); size_t start = mesh->rangeStart; size_t count = mesh->rangeCount; - if (mesh->map.length > 0) { - count = mesh->isRangeEnabled ? mesh->rangeCount : mesh->map.length; - glDrawElements(mesh->drawMode, count, GL_UNSIGNED_INT, (GLvoid*) (start * sizeof(unsigned int))); + if (mesh->indexCount > 0) { + count = mesh->isRangeEnabled ? mesh->rangeCount : mesh->indexCount; + GLenum indexType = mesh->indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + glDrawElements(mesh->drawMode, count, indexType, (GLvoid*) (start * mesh->indexSize)); } else { glDrawArrays(mesh->drawMode, start, count); } @@ -159,21 +163,22 @@ int lovrMeshGetVertexSize(Mesh* mesh) { return mesh->stride; } -unsigned int* lovrMeshGetVertexMap(Mesh* mesh, size_t* count) { - *count = mesh->map.length; - return mesh->map.data; +void* lovrMeshGetVertexMap(Mesh* mesh, size_t* count) { + *count = mesh->indexCount; + return mesh->indices; } -void lovrMeshSetVertexMap(Mesh* mesh, unsigned int* map, size_t count) { - if (count == 0 || !map) { - vec_clear(&mesh->map); - } else { - vec_clear(&mesh->map); - vec_pusharr(&mesh->map, map, count); - lovrGraphicsBindVertexArray(mesh->vao); - lovrGraphicsBindIndexBuffer(mesh->ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), mesh->map.data, GL_STATIC_DRAW); +void lovrMeshSetVertexMap(Mesh* mesh, void* data, size_t count) { + if (!data || count == 0) { + mesh->indexCount = 0; + return; } + + mesh->indices = data; + mesh->indexCount = count; + lovrGraphicsBindVertexArray(mesh->vao); + lovrGraphicsBindIndexBuffer(mesh->ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->indexCount * mesh->indexSize, mesh->indices, GL_STATIC_DRAW); } int lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) { @@ -226,7 +231,7 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) { } int lovrMeshSetDrawRange(Mesh* mesh, int start, int count) { - size_t limit = mesh->map.length > 0 ? mesh->map.length : mesh->count; + size_t limit = mesh->indexCount > 0 ? mesh->indexCount : mesh->count; if (start < 0 || count < 0 || (size_t) start + count > limit) { return 1; diff --git a/src/graphics/mesh.h b/src/graphics/mesh.h index 0a6c343d..8e75649b 100644 --- a/src/graphics/mesh.h +++ b/src/graphics/mesh.h @@ -49,7 +49,9 @@ typedef struct { GLuint vao; GLuint vbo; GLuint ibo; - vec_uint_t map; + void* indices; + size_t indexCount; + size_t indexSize; int isRangeEnabled; int rangeStart; int rangeCount; @@ -64,8 +66,8 @@ MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh); int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode); int lovrMeshGetVertexCount(Mesh* mesh); int lovrMeshGetVertexSize(Mesh* mesh); -unsigned int* lovrMeshGetVertexMap(Mesh* mesh, size_t* count); -void lovrMeshSetVertexMap(Mesh* mesh, unsigned int* map, size_t count); +void* lovrMeshGetVertexMap(Mesh* mesh, size_t* count); +void lovrMeshSetVertexMap(Mesh* mesh, void* data, size_t count); int lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name); void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, int enabled); int lovrMeshIsRangeEnabled(Mesh* mesh); diff --git a/src/loaders/model.c b/src/loaders/model.c index c20ed60a..8e789c88 100644 --- a/src/loaders/model.c +++ b/src/loaders/model.c @@ -3,6 +3,7 @@ #include "filesystem/file.h" #include "math/math.h" #include "math/mat4.h" +#include #include #include #include @@ -202,11 +203,12 @@ ModelData* lovrModelDataCreate(Blob* blob) { } // Allocate + int indexSize = modelData->vertexCount > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t); modelData->primitiveCount = scene->mNumMeshes; modelData->primitives = malloc(modelData->primitiveCount * sizeof(ModelPrimitive)); modelData->vertexSize = 3 + (modelData->hasNormals ? 3 : 0) + (modelData->hasUVs ? 2 : 0); modelData->vertices = malloc(modelData->vertexSize * modelData->vertexCount * sizeof(float)); - modelData->indices = malloc(modelData->indexCount * sizeof(uint32_t)); + modelData->indices = malloc(modelData->indexCount * indexSize); // Load int vertex = 0; @@ -224,8 +226,16 @@ ModelData* lovrModelDataCreate(Blob* blob) { modelData->primitives[m].drawCount += assimpFace.mNumIndices; - for (unsigned int i = 0; i < assimpFace.mNumIndices; i++) { - modelData->indices[index++] = (vertex / modelData->vertexSize) + assimpFace.mIndices[i]; + if (indexSize == sizeof(uint16_t)) { + uint16_t* indices = modelData->indices; + for (unsigned int i = 0; i < assimpFace.mNumIndices; i++) { + indices[index++] = (vertex / modelData->vertexSize) + assimpFace.mIndices[i]; + } + } else if (indexSize == sizeof(uint32_t)) { + uint32_t* indices = modelData->indices; + for (unsigned int i = 0; i < assimpFace.mNumIndices; i++) { + indices[index++] = (vertex / modelData->vertexSize) + assimpFace.mIndices[i]; + } } } diff --git a/src/loaders/model.h b/src/loaders/model.h index b0f03567..c69f8b97 100644 --- a/src/loaders/model.h +++ b/src/loaders/model.h @@ -23,7 +23,7 @@ typedef struct { ModelPrimitive* primitives; MaterialData* materials; float* vertices; - uint32_t* indices; + void* indices; int nodeCount; int primitiveCount; int materialCount;