Implement model registry

This allows for mass handling of multiple objects
to be rendered.
This commit is contained in:
Marcel Plch 2024-09-29 22:11:45 +02:00
parent 01896962be
commit bd31c409a6
Signed by: dormouse
GPG key ID: 2CA77596BC4BDFFE
4 changed files with 165 additions and 92 deletions

View file

@ -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

183
src/cx.c
View file

@ -1,6 +1,77 @@
#include <cx.h>
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));

View file

@ -13,10 +13,10 @@ main(void) {
Neural_Network *nn;
int retval;
if (cx_glinit(&window)) {
return -1;
}
if (cx_nninit(&nn)) {
return -1;
}

View file

@ -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);
}