From 6546a955384f968bff96c67b73e1579d0fbff9d5 Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Tue, 7 Jan 2020 21:27:58 +1100 Subject: [PATCH] We no longer keep around geometry data after passing it on to opengl as it is not needed anymore resulting in some memory savings --- src/common/version.h | 2 +- src/game/geometry.c | 221 ++++++++++++++++++------------------------- src/game/geometry.h | 11 +-- src/game/renderer.c | 2 +- todo.txt | 3 +- 5 files changed, 100 insertions(+), 139 deletions(-) diff --git a/src/common/version.h b/src/common/version.h index 6b3b2bb..676f945 100755 --- a/src/common/version.h +++ b/src/common/version.h @@ -4,7 +4,7 @@ /* Auto generated version file. DO NOT MODIFY */ #define SYMMETRY_VERSION_MAJOR 0 #define SYMMETRY_VERSION_MINOR 1 -#define SYMMETRY_VERSION_REVISION 303 +#define SYMMETRY_VERSION_REVISION 304 #define SYMMETRY_VERSION_BRANCH "dev" #endif \ No newline at end of file diff --git a/src/game/geometry.c b/src/game/geometry.c index f6b8db1..1b737b8 100755 --- a/src/game/geometry.c +++ b/src/game/geometry.c @@ -17,9 +17,9 @@ GLenum* draw_modes = NULL; static struct Geometry* geometry_list; static int* empty_indices; -static int load_from_file(struct Geometry* geometry, const char* filename); -static void create_vao(struct Geometry* geometry); +static void create_vao(struct Geometry* geometry, vec3* vertices, vec2* uvs, vec3* normals, vec3* vertex_colors, uint* indices); static struct Geometry* generate_new_index(int* out_new_index); +static void geom_bounding_volume_generate(struct Geometry* geometry, vec3* vertices); void geom_init(void) { @@ -49,20 +49,19 @@ int geom_find(const char* filename) return index; } -void geom_bounding_volume_generate(int index) +void geom_bounding_volume_generate(struct Geometry* geometry, vec3* vertices) { - struct Geometry* geometry = &geometry_list[index]; - struct Bounding_Box* box = &geometry->bounding_box; - struct Bounding_Sphere* sphere = &geometry->bounding_sphere; + struct Bounding_Box* box = &geometry->bounding_box; + struct Bounding_Sphere* sphere = &geometry->bounding_sphere; vec3_fill(&box->max, -FLT_MIN, -FLT_MIN, -FLT_MIN); vec3_fill(&box->min, FLT_MAX, FLT_MAX, FLT_MAX); vec3_fill(&sphere->center, 0.f, 0.f, 0.f); sphere->radius = 0.f; - for(int i = 0; i < array_len(geometry->vertices); i++) + for(int i = 0; i < array_len(vertices); i++) { - vec3* vertex = &geometry->vertices[i]; + vec3* vertex = &vertices[i]; if(vertex->x > box->max.x) box->max.x = vertex->x; if(vertex->y > box->max.y) box->max.y = vertex->y; if(vertex->z > box->max.z) box->max.z = vertex->z; @@ -85,13 +84,7 @@ void geom_bounding_volume_generate(int index) } } -void geom_bounding_volume_generate_all(void) -{ - for(int i = 0; i < array_len(geometry_list); i++) - geom_bounding_volume_generate(i); -} - -static struct Geometry* generate_new_index(int* out_new_index) +struct Geometry* generate_new_index(int* out_new_index) { assert(out_new_index); int empty_len = array_len(empty_indices); @@ -122,10 +115,58 @@ int geom_create_from_file(const char* name) new_geo = generate_new_index(&index); assert(new_geo); - if(load_from_file(new_geo, name)) + char* full_path = str_new("models/%s", name); + FILE* file = io_file_open(DIRT_INSTALL, full_path, "rb"); + free(full_path); + if(file) { - create_vao(new_geo); - geom_bounding_volume_generate(index); + const uint32 INDEX_SIZE = sizeof(uint32); + const uint32 VEC3_SIZE = sizeof(vec3); + const uint32 VEC2_SIZE = sizeof(vec2); + uint32 header[4]; + size_t bytes_read = 0; + if((bytes_read = fread(header, INDEX_SIZE, 4, file)) <= 0) + { + log_error("geometry:load_from_file", "Read failed"); + /* TODO: Some error here, find it and fix it */ + array_pop(geometry_list); + index = -1; + } + else + { + uint32 indices_count = header[0]; + uint32 vertices_count = header[1]; + uint32 normals_count = header[2]; + uint32 uvs_count = header[3]; + // Indices + uint* indices = array_new_cap(uint, indices_count); + fread(indices, INDEX_SIZE, indices_count, file); + array_match_len_cap(indices); + // Vertices + vec3* vertices = array_new_cap(vec3, vertices_count); + fread(vertices, VEC3_SIZE, vertices_count, file); + array_match_len_cap(vertices); + // Normals + vec3* normals = array_new_cap(vec3, normals_count); + fread(normals, VEC3_SIZE, normals_count, file); + array_match_len_cap(normals); + // Uvs + vec2* uvs = array_new_cap(vec2, uvs_count); + fread(uvs, VEC2_SIZE, uvs_count, file); + array_match_len_cap(uvs); + + new_geo->filename = str_new(name); + new_geo->draw_indexed = 1; + new_geo->ref_count++; + + create_vao(new_geo, vertices, uvs, normals, NULL, indices); + geom_bounding_volume_generate(new_geo, vertices); + if(vertices) array_free(vertices); + if(indices) array_free(indices); + if(uvs) array_free(uvs); + if(normals) array_free(normals); + } + fclose(file); } else { @@ -151,29 +192,12 @@ int geom_create(const char* name, assert(name && vertices && uvs && normals && indices); int index = -1; /* add new geometry object or overwrite existing one */ - struct Geometry* new_geo = NULL; - new_geo = generate_new_index(&index); - assert(new_geo); - new_geo->filename = str_new(name); - new_geo->vertices = array_new_cap(vec3, array_len(vertices)); - array_copy(vertices, new_geo->vertices); - new_geo->normals = array_new_cap(vec3, array_len(normals)); - array_copy(normals, new_geo->normals); - new_geo->uvs = array_new_cap(vec2, array_len(uvs)); - array_copy(uvs, new_geo->uvs); - new_geo->indices = array_new_cap(uint, array_len(indices)); - array_copy(indices, new_geo->indices); - if(vertex_colors) - { - new_geo->vertex_colors = array_new_cap(vec3, array_len(vertex_colors)); - array_copy(vertex_colors, new_geo->vertex_colors); - } - else - { - new_geo->vertex_colors = array_new(vec3); - } - create_vao(new_geo); - //generateBoundingBox(index); + struct Geometry* new_geometry = NULL; + new_geometry = generate_new_index(&index); + assert(new_geometry); + new_geometry->filename = str_new(name); + create_vao(new_geometry, vertices, uvs, normals, vertex_colors, indices); + geom_bounding_volume_generate(new_geometry, vertices); return index; } @@ -188,18 +212,8 @@ void geom_remove(int index) geometry->ref_count--; if(geometry->ref_count < 0) { - if(geometry->indices) array_free(geometry->indices); - if(geometry->vertices) array_free(geometry->vertices); - if(geometry->uvs) array_free(geometry->uvs); - if(geometry->normals) array_free(geometry->normals); - if(geometry->vertex_colors) array_free(geometry->vertex_colors); - if(geometry->filename) free(geometry->filename); - geometry->indices = NULL; - geometry->vertices = NULL; - geometry->uvs = NULL; - geometry->normals = NULL; - geometry->vertex_colors = NULL; - geometry->filename = NULL; + if(geometry->filename) free(geometry->filename); + geometry->filename = NULL; glDeleteBuffers(1, &geometry->vertex_vbo); glDeleteBuffers(1, &geometry->color_vbo); @@ -231,64 +245,12 @@ void geom_cleanup(void) array_free(draw_modes); } -static int load_from_file(struct Geometry* geometry, const char* filename) -{ - assert(filename); - int success = 1; - char* full_path = str_new("models/%s", filename); - - FILE* file = io_file_open(DIRT_INSTALL, full_path, "rb"); - free(full_path); - if(file) - { - const uint32 INDEX_SIZE = sizeof(uint32); - const uint32 VEC3_SIZE = sizeof(vec3); - const uint32 VEC2_SIZE = sizeof(vec2); - uint32 header[4]; - size_t bytes_read = 0; - if((bytes_read = fread(header, INDEX_SIZE, 4, file)) <= 0) - { - log_error("geometry:load_from_file", "Read failed"); - success = 0; - } - else - { - uint32 indices_count = header[0]; - uint32 vertices_count = header[1]; - uint32 normals_count = header[2]; - uint32 uvs_count = header[3]; - // Indices - geometry->indices = array_new_cap(uint, indices_count); - fread(geometry->indices, INDEX_SIZE, indices_count, file); - array_match_len_cap(geometry->indices); - // Vertices - geometry->vertices = array_new_cap(vec3, vertices_count); - fread(geometry->vertices, VEC3_SIZE, vertices_count, file); - array_match_len_cap(geometry->vertices); - // Normals - geometry->normals = array_new_cap(vec3, normals_count); - fread(geometry->normals, VEC3_SIZE, normals_count, file); - array_match_len_cap(geometry->normals); - // Uvs - geometry->uvs = array_new_cap(vec2, uvs_count); - fread(geometry->uvs, VEC2_SIZE, uvs_count, file); - array_match_len_cap(geometry->uvs); - - geometry->vertex_colors = array_new(vec3); - } - fclose(file); - geometry->filename = str_new(filename); - geometry->draw_indexed = 1; - geometry->ref_count++; - } - else - { - success = 0; - } - return success; -} - -static void create_vao(struct Geometry* geometry) +void create_vao(struct Geometry* geometry, + vec3* vertices, + vec2* uvs, + vec3* normals, + vec3* vertex_colors, + uint* indices) { // TODO: Add support for different model formats and interleaving VBO assert(geometry); @@ -298,59 +260,62 @@ static void create_vao(struct Geometry* geometry) glGenBuffers(1, &geometry->vertex_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_vbo); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, - array_len(geometry->vertices) * sizeof(vec3), - geometry->vertices, + array_len(vertices) * sizeof(vec3), + vertices, GL_STATIC_DRAW)); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + geometry->vertices_len = array_len(vertices); - if(array_len(geometry->normals) > 0) + if(array_len(normals) > 0) { glGenBuffers(1, &geometry->normal_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->normal_vbo); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, - array_len(geometry->normals) * sizeof(vec3), - geometry->normals, + array_len(normals) * sizeof(vec3), + normals, GL_STATIC_DRAW)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, 0); } - if(array_len(geometry->uvs) > 0) + if(array_len(uvs) > 0) { glGenBuffers(1, &geometry->uv_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->uv_vbo); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, - array_len(geometry->uvs) * sizeof(vec2), - geometry->uvs, + array_len(uvs) * sizeof(vec2), + uvs, GL_STATIC_DRAW)); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); } - if(array_len(geometry->vertex_colors) > 0) + if(vertex_colors && array_len(vertex_colors) > 0) { glGenBuffers(1, &geometry->color_vbo); glBindBuffer(GL_ARRAY_BUFFER, geometry->color_vbo); GL_CHECK(glBufferData(GL_ARRAY_BUFFER, - array_len(geometry->vertex_colors) * sizeof(vec3), - geometry->vertex_colors, + array_len(vertex_colors) * sizeof(vec3), + vertex_colors, GL_STATIC_DRAW)); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0); } - if(array_len(geometry->indices) > 0) + if(array_len(indices) > 0) { glGenBuffers(1, &geometry->index_vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_vbo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, - array_len(geometry->indices) * sizeof(GLuint), - geometry->indices, + array_len(indices) * sizeof(GLuint), + indices, GL_STATIC_DRAW); geometry->draw_indexed = 1; + geometry->indices_len = array_len(indices); } glBindVertexArray(0); + } void geom_render(int index, enum Geometry_Draw_Mode draw_mode) @@ -359,9 +324,9 @@ void geom_render(int index, enum Geometry_Draw_Mode draw_mode) struct Geometry* geo = &geometry_list[index]; glBindVertexArray(geo->vao); if(geo->draw_indexed) - glDrawElements(draw_modes[draw_mode], array_len(geo->indices), GL_UNSIGNED_INT, (void*)0); + glDrawElements(draw_modes[draw_mode], geo->indices_len, GL_UNSIGNED_INT, (void*)0); else - glDrawArrays(draw_modes[draw_mode], 0, array_len(geo->vertices)); + glDrawArrays(draw_modes[draw_mode], 0, geo->vertices_len); glBindVertexArray(0); } @@ -386,7 +351,7 @@ int geom_render_in_frustum(int index, if(intersection == IT_INTERSECT || intersection == IT_INSIDE) { geom_render(index, draw_mode); - indices_rendered = array_len(geometry->indices); + indices_rendered = array_len(geometry->indices_len); } } return indices_rendered; diff --git a/src/game/geometry.h b/src/game/geometry.h index b7d3d68..5fabc13 100755 --- a/src/game/geometry.h +++ b/src/game/geometry.h @@ -31,12 +31,9 @@ struct Geometry uint normal_vbo; uint color_vbo; uint index_vbo; + uint vertices_len; + uint indices_len; int ref_count; - vec3* vertices; - vec3* vertex_colors; - vec3* normals; - vec2* uvs; - uint* indices; struct Bounding_Box bounding_box; struct Bounding_Sphere bounding_sphere; }; @@ -47,8 +44,6 @@ int geom_find(const char* filename); void geom_remove(int index); void geom_cleanup(void); void geom_render(int index, enum Geometry_Draw_Mode draw_mode); -void geom_bounding_volume_generate(int index); -void geom_bounding_volume_generate_all(void); struct Geometry* geom_get(int index); int geom_render_in_frustum(int index, vec4* frustum, @@ -59,6 +54,6 @@ int geom_create(const char* name, vec2* uvs, vec3* normals, uint* indices, - vec3* vertex_colors); + vec3* vertex_colors); // Note: caller responsible for freeing up the data passed in #endif diff --git a/src/game/renderer.c b/src/game/renderer.c index ecb3776..88ceb9f 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -189,7 +189,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) int intersection = bv_intersect_frustum_box(&active_camera->frustum, &mesh->base.derived_bounding_box); if(intersection == IT_INSIDE || intersection == IT_INTERSECT) { - renderer->num_indices += array_len(geometry->indices); + renderer->num_indices += geometry->indices_len; renderer->num_rendered++; } else diff --git a/todo.txt b/todo.txt index 57d6486..84212b2 100644 --- a/todo.txt +++ b/todo.txt @@ -394,4 +394,5 @@ Done: * Show version number in editor and console * Save/Load base bounding boxes for entity types other than static mesh * Disabled picking when a tool is active in editor - * Simplified rendering further and removed unnecessary intermediate fbos \ No newline at end of file + * Simplified rendering further and removed unnecessary intermediate fbos + * We no longer keep geoemtry data loaded from files as it is not needed after data is passed on to opengl \ No newline at end of file