From bd31c409a61a17250fa98aaa228fcc6b108392e1 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Sun, 29 Sep 2024 22:11:45 +0200 Subject: [PATCH] Implement model registry This allows for mass handling of multiple objects to be rendered. --- include/model.h | 16 ++++- src/cx.c | 183 ++++++++++++++++++++++++++---------------------- src/main.c | 2 +- src/model.c | 56 +++++++++++++-- 4 files changed, 165 insertions(+), 92 deletions(-) diff --git a/include/model.h b/include/model.h index ff8145c..5e1a819 100644 --- a/include/model.h +++ b/include/model.h @@ -1,13 +1,23 @@ -#ifndef MODEL_LOADER_H -#define MODEL_LOADER_H +#ifndef MODEL_H +#define MODEL_H typedef struct _model { GLfloat *object; + GLfloat **transformations; + size_t transformation_count; size_t bufsize; } Model; +typedef struct _model_registry { + Model **models; + size_t model_count; + size_t size; +} ModelRegistry; + Model *model_load(const char *); -int model_free(Model *); +ModelRegistry* modelRegistry_new(void); +int modelRegistry_register(ModelRegistry *, Model *); +void modelRegistry_free(ModelRegistry *); #endif diff --git a/src/cx.c b/src/cx.c index 0545e5d..0341b44 100644 --- a/src/cx.c +++ b/src/cx.c @@ -1,6 +1,77 @@ #include -int cx_glinit(GLFWwindow **window) { +static int +cx_glrender(GLFWwindow *window, GLuint programID, GLfloat *render_buffer, + GLuint vertexbuffer, ModelRegistry *mr) { + // Clear the screen. + glClear(GL_COLOR_BUFFER_BIT); + + // Use our shader + glUseProgram(programID); + + GLfloat *rotation_matrix = matrix_new(); + GLfloat *translation_matrix = matrix_new(); + + translation_matrix[3] = 0.5f; + + rotation_matrix[0] = cos(M_PI*2/256); + rotation_matrix[8] = -sin(M_PI*2/256); + rotation_matrix[2] = sin(M_PI*2/256); + rotation_matrix[10] = cos(M_PI*2/256); + + // BANANA, ROH-TAH-TEH + GLfloat *temp_buffer[2]; + temp_buffer[0] = matrix_transform(mr->models[0]->object, mr->models[0]->bufsize, rotation_matrix); + temp_buffer[1] = matrix_transform(temp_buffer[0], mr->models[0]->bufsize, translation_matrix); + + memcpy(render_buffer, temp_buffer[1], + mr->models[0]->bufsize * 4 * sizeof(GLfloat)); + + free(temp_buffer[0]); + free(temp_buffer[1]); + + glBufferData(GL_ARRAY_BUFFER, mr->models[0]->bufsize*4*sizeof(GLfloat), + render_buffer, GL_STATIC_DRAW); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glVertexAttribPointer( + 0, // attribute 0 in the pipeline + 4, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + NULL // array buffer offset + ); + + + // Draw! + glDrawArrays(GL_TRIANGLES, 0, mr->models[0]->bufsize); // 3 indices starting at 0 -> 1 triangle + + glDisableVertexAttribArray(0); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + + temp_buffer[0] = matrix_transform(mr->models[0]->object, mr->models[0]->bufsize, translation_matrix); + free(rotation_matrix); + return 0; +} + +static int +cx_glbufferBind(size_t bufsize, GLfloat *render_buffer, GLuint *vertexbuffer) { + glGenBuffers(1, vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, *vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, bufsize, + render_buffer, GL_STATIC_DRAW); + return 0; + +} + +int +cx_glinit(GLFWwindow **window) { // Initialise GLFW if(!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); @@ -41,25 +112,39 @@ int cx_glinit(GLFWwindow **window) { return 0; } -int cx_glrun(GLFWwindow *window) { - GLuint VertexArrayID; - GLuint programID; +static int +cx_loadShaders(GLuint *VertexArrayID, GLuint *programID) { - glGenVertexArrays(1, &VertexArrayID); - glBindVertexArray(VertexArrayID); + glGenVertexArrays(1, VertexArrayID); + glBindVertexArray(*VertexArrayID); // Create and compile our GLSL program from the shaders - if (LoadShaders(&programID, + if (LoadShaders(programID, "../shaders/SimpleVertexShader.vertexshader", "../shaders/SimpleFragmentShader.fragmentshader")) { fprintf(stderr, "Could not load shaders.\n"); return -1; } + return 0; +} + +int +cx_glrun(GLFWwindow *window) { + GLuint VertexArrayID; + GLuint programID; + GLuint vertexbuffer; + if (cx_loadShaders(&VertexArrayID, &programID)) { + return -1; + } // Load model to render from file Model *model; model = model_load("../3d_assets/cube.obj"); + // Establish a model registry + ModelRegistry *mr; + mr = modelRegistry_new(); + modelRegistry_register(mr, model); // Allocate the render buffer // GL uses this to feed the GPU @@ -69,91 +154,20 @@ int cx_glrun(GLFWwindow *window) { model->bufsize * 4 * sizeof(GLfloat)); // Bind the render buffer to OpenGL - GLuint vertexbuffer; - glGenBuffers(1, &vertexbuffer); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - glBufferData(GL_ARRAY_BUFFER, model->bufsize*4*sizeof(GLfloat), - render_buffer, GL_STATIC_DRAW); - - // 1rst attribute buffer : vertices - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - glVertexAttribPointer( - 0, // attribute 0 in the pipeline - 4, // size - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - NULL // array buffer offset - ); + cx_glbufferBind(model->bufsize*4*sizeof(GLfloat), render_buffer, &vertexbuffer); // Remainder from cursor experiments, might be useful later double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); - GLfloat *rotation_matrix = matrix_new(); - GLfloat *translation_matrix = matrix_new(); - - // Temporary storage of transformation results - GLfloat *temp_buffer[2]; - translation_matrix[3] = 0.5f; int t = 0; do { - // Clear the screen. It's not mentioned before Tutorial 02, - // but it can cause flickering, so it's there nonetheless. - glClear(GL_COLOR_BUFFER_BIT); - - // Use our shader - glUseProgram(programID); - - - rotation_matrix[0] = cos(M_PI*2/256*(t%256)); - rotation_matrix[8] = -sin(M_PI*2/256*(t%256)); - rotation_matrix[2] = sin(M_PI*2/256*(t%256)); - rotation_matrix[10] = cos(M_PI*2/256*(t%256)); - - - // BANANA, ROH-TAH-TEH - temp_buffer[0] = matrix_transform(model->object, model->bufsize, rotation_matrix); - temp_buffer[1] = matrix_transform(temp_buffer[0], model->bufsize, translation_matrix); - - // Guess I'm just projecting. - free(temp_buffer[0]); - - memcpy(render_buffer, temp_buffer[1], model->bufsize * 4 * sizeof(GLfloat)); - free(temp_buffer[1]); - - glBufferData(GL_ARRAY_BUFFER, model->bufsize*4*sizeof(GLfloat), render_buffer, GL_STATIC_DRAW); - - // 1rst attribute buffer : vertices - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - glVertexAttribPointer( - 0, // attribute 0 in the pipeline - 4, // size - GL_FLOAT, // type - GL_FALSE, // normalized? - 0, // stride - NULL // array buffer offset - ); - - - // Draw! - glDrawArrays(GL_TRIANGLES, 0, model->bufsize); // 3 indices starting at 0 -> 1 triangle - - glDisableVertexAttribArray(0); - - // Swap buffers - glfwSwapBuffers(window); - glfwPollEvents(); - - temp_buffer[0] = matrix_transform(model->object, model->bufsize, translation_matrix); - + cx_glrender(window, programID, render_buffer, vertexbuffer, mr); t++; usleep(1000000/60); // Check if the ESC key was pressed or the window was closed @@ -162,15 +176,15 @@ int cx_glrun(GLFWwindow *window) { // Close OpenGL window and terminate GLFW glfwTerminate(); - free(rotation_matrix); - model_free(model); + modelRegistry_free(mr); free(render_buffer); return 0; } -int cx_nninit(Neural_Network **nn) { +int +cx_nninit(Neural_Network **nn) { // Allocate a Neural Network *nn = neural_new(64, 1); if(!*nn) { @@ -184,7 +198,8 @@ int cx_nninit(Neural_Network **nn) { return 0; } -int cx_nnrun(Neural_Network *nn) { +int +cx_nnrun(Neural_Network *nn) { // Establish a neural interface. float *input_buffer = malloc(64*sizeof(float)); diff --git a/src/main.c b/src/main.c index f971510..29f1d7d 100644 --- a/src/main.c +++ b/src/main.c @@ -13,10 +13,10 @@ main(void) { Neural_Network *nn; int retval; - if (cx_glinit(&window)) { return -1; } + if (cx_nninit(&nn)) { return -1; } diff --git a/src/model.c b/src/model.c index 890661d..0d4527f 100644 --- a/src/model.c +++ b/src/model.c @@ -4,10 +4,18 @@ Model * model_new(size_t size) { Model *self = calloc(1, sizeof(Model)); self->object = calloc((size ? size : 1) *4 , sizeof(GLfloat)); + self->transformations = calloc(8 , sizeof(GLfloat*)); self->bufsize = size; return self; } +int +model_free(Model *self) { + free(self->object); + free(self->transformations); + free(self); + return 0; +} Model * model_load(const char *path) { @@ -50,7 +58,7 @@ model_load(const char *path) { } } while(check != EOF); - self = model_new(facecount*4); + self = model_new(facecount*3); for (int i = 0; i < facecount; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { @@ -66,10 +74,50 @@ model_load(const char *path) { return self; } +ModelRegistry * +modelRegistry_new() { + ModelRegistry *mr; + mr = malloc(1 * sizeof(ModelRegistry)); + if (mr == NULL) { + goto err; + } + mr->models = calloc(16, sizeof(Model)); + if (mr->models == NULL) { + goto err; + } + mr->model_count = 0; + mr->size = 16; + return mr; + +err: + if (mr) { + free(mr->models); + } + free(mr); + return NULL; +} + int -model_free(Model *self) { - free(self->object); - free(self); +modelRegistry_register(ModelRegistry *self, Model *model) { + if (self->model_count >= self->size) { + self->size *= 2; + self->models = realloc(self->models, self->size); + if (self->models == NULL) { + modelRegistry_free(self); + return -1; + } + } + self->models[self->model_count] = model; + self->model_count++; return 0; } +void +modelRegistry_free(ModelRegistry *self) { + for (int i = 0; i < self->model_count; i++) { + model_free(self->models[i]); + } + free(self->models); + free(self); +} +