From be90d089778b8b32790aeacee0f7b32f7431bf8c Mon Sep 17 00:00:00 2001 From: Warwick Date: Fri, 9 Jan 2026 20:17:25 +0000 Subject: [PATCH] Moved all the mesh stuff to another file (introduced memory leak) --- src/main.c | 100 ++------------------------------------------- src/mesh.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mesh.h | 18 ++++++--- 3 files changed, 132 insertions(+), 103 deletions(-) diff --git a/src/main.c b/src/main.c index 273793b..f5900cb 100644 --- a/src/main.c +++ b/src/main.c @@ -5,9 +5,8 @@ #include "SDL3/SDL_events.h" #include "SDL3/SDL_keycode.h" -#include "SDL3/SDL_surface.h" -#include "SDL3_image/SDL_image.h" #include "camera.h" +#include "mesh.h" #include "shader.h" #include "window.h" @@ -77,87 +76,7 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - // set up vertex data (and buffer(s)) and configure vertex attributes - float vertices[] = { - 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right - 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right - -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left - -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left - }; - unsigned int indices[] = { - 0, 1, 3, // first Triangle - 1, 2, 3 // second Triangle - }; - - GLuint VBO, VAO, EBO; - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - // bind the Vertex Array Object first, then bind and set vertex buffer(s), and - // then configure vertex attributes(s). - glBindVertexArray(VAO); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, - GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), - (void *)(3 * sizeof(float))); - glEnableVertexAttribArray(1); - - // note that this is allowed, the call to glVertexAttribPointer registered VBO - // as the vertex attribute's bound vertex buffer object so afterwards we can - // safely unbind - // glBindBuffer(GL_ARRAY_BUFFER, 0); - - // remember: do NOT unbind the EBO while a VAO is active as the bound element - // buffer object IS stored in the VAO; keep the EBO bound. - // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // You can unbind the VAO afterwards so other VAO calls won't accidentally - // modify this VAO, but this rarely happens. Modifying other VAOs requires a - // call to glBindVertexArray anyways so we generally don't unbind VAOs (nor - // VBOs) when it's not directly necessary. - // glBindVertexArray(0); - - // Texture Load - SDL_Surface *image = IMG_Load("./data/testxure.png"); - if (image == NULL) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load texture"); - return EXIT_FAILURE; - } - SDL_FlipSurface(image, SDL_FLIP_VERTICAL); - - GLuint texture; - glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &texture); - - // Handle different SDL Surface data types - int mode = GL_RGBA; - // if (image->format->BytesPerPixel == 4) { - // mode = GL_RGBA; - // } - - glBindTexture(GL_TEXTURE_2D, texture); - // set the texture wrapping parameters - glTexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - // set texture filtering parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexImage2D(GL_TEXTURE_2D, 0, mode, image->w, image->h, 0, mode, - GL_UNSIGNED_BYTE, image->pixels); - - glGenerateMipmap(GL_TEXTURE_2D); - SDL_DestroySurface(image); + wn_mesh *mesh = wn_mesh_init(global_arena, shader); // Initialise camera Camera camera = Camera_default; @@ -196,24 +115,11 @@ int main(int argc, char *argv[]) { glClearColor(0.1f, 0.3f, 0.4f, 1.f); glClear(GL_COLOR_BUFFER_BIT); - // draw our first triangle - glUseProgram(shader->shaderProgram); - - // seeing as we only have a single VAO there's no need to bind it - // every time, but we'll do so to keep things a bit more organized - glBindVertexArray(VAO); - - // glDrawArrays(GL_TRIANGLES, 0, 6); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - // glBindVertexArray(0); // no need to unbind it every time + wn_mesh_draw(mesh); wn_swapwindow(window); } - glDeleteVertexArrays(1, &VAO); - glDeleteBuffers(1, &VBO); - glDeleteBuffers(1, &EBO); - arena_deinit(global_arena); return EXIT_SUCCESS; } diff --git a/src/mesh.c b/src/mesh.c index e69de29..0008dc6 100644 --- a/src/mesh.c +++ b/src/mesh.c @@ -0,0 +1,117 @@ +#include + +#include "SDL3/SDL_surface.h" +#include "SDL3_image/SDL_image.h" +#include "arena_allocator.h" +#include "mesh.h" + +wn_mesh *wn_mesh_init(Arena *arena, wn_shader *shader) { + // set up vertex data (and buffer(s)) and configure vertex attributes + wn_mesh *mesh = (wn_mesh *)arena_init(arena, sizeof(wn_mesh)); + arena_deinit_task_push(arena, (ArenaDeinitTask){.func_ptr = *wn_mesh_deinit, + .func_param = mesh, + .next = NULL}); + mesh->shader = shader; + float vertices[] = { + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left + -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left + }; + unsigned int indices[] = { + 0, 1, 3, // first Triangle + 1, 2, 3 // second Triangle + }; + + glGenVertexArrays(1, &mesh->VAO); + glGenBuffers(1, &mesh->VBO); + glGenBuffers(1, &mesh->EBO); + // bind the Vertex Array Object first, then bind and set vertex buffer(s), and + // then configure vertex attributes(s). + glBindVertexArray(mesh->VAO); + + glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, + GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), + (void *)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + + // note that this is allowed, the call to glVertexAttribPointer registered VBO + // as the vertex attribute's bound vertex buffer object so afterwards we can + // safely unbind + // glBindBuffer(GL_ARRAY_BUFFER, 0); + + // remember: do NOT unbind the EBO while a VAO is active as the bound element + // buffer object IS stored in the VAO; keep the EBO bound. + // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + // You can unbind the VAO afterwards so other VAO calls won't accidentally + // modify this VAO, but this rarely happens. Modifying other VAOs requires a + // call to glBindVertexArray anyways so we generally don't unbind VAOs (nor + // VBOs) when it's not directly necessary. + // glBindVertexArray(0); + + // Texture Load + SDL_Surface *image = IMG_Load("./data/testxure.png"); + if (image == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load texture"); + return NULL; + } + SDL_FlipSurface(image, SDL_FLIP_VERTICAL); + + GLuint texture; + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &texture); + + // Handle different SDL Surface data types + // int mode = GL_RGB; + // if (image->format->BytesPerPixel == 4) { + int mode = GL_RGBA; + // mode = GL_RGBA; + // } + + glBindTexture(GL_TEXTURE_2D, texture); + // set the texture wrapping parameters + glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, mode, image->w, image->h, 0, mode, + GL_UNSIGNED_BYTE, image->pixels); + + glGenerateMipmap(GL_TEXTURE_2D); + SDL_DestroySurface(image); + + return mesh; +} + +void wn_mesh_draw(wn_mesh *mesh) { + // draw our first triangle + glUseProgram(mesh->shader->shaderProgram); + + // seeing as we only have a single VAO there's no need to bind it + // every time, but we'll do so to keep things a bit more organized + glBindVertexArray(mesh->VAO); + + // glDrawArrays(GL_TRIANGLES, 0, 6); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + // glBindVertexArray(0); // no need to unbind it every time +} + +void wn_mesh_deinit(void *mesh) { + wn_mesh *cast_mesh = (wn_mesh *)mesh; + glDeleteVertexArrays(1, &cast_mesh->VAO); + glDeleteBuffers(1, &cast_mesh->VBO); + glDeleteBuffers(1, &cast_mesh->EBO); +} diff --git a/src/mesh.h b/src/mesh.h index 9247ad8..5f32380 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -1,14 +1,20 @@ #pragma once #include "SDL3/SDL_opengl.h" +#include "arena_allocator.h" #include "shader.h" #include typedef struct { - float *vertex_buffer; - uint vertex_buffer_size; - float *element_buffer; - uint element_buffer_size; wn_shader *shader; - GLuint VBO, VAO, EBO, diffuse_texture; -} Mesh; + GLuint VBO, VAO, EBO; +} wn_mesh; + +// Initialise a model +wn_mesh *wn_mesh_init(Arena* arena, wn_shader *shader); + +// Draw the model with it's linked shader +void wn_mesh_draw(wn_mesh *mesh); + +// Clear up linked buffers +void wn_mesh_deinit(void* mesh);