Implement model registry
This allows for mass handling of multiple objects to be rendered.
This commit is contained in:
parent
01896962be
commit
bd31c409a6
4 changed files with 165 additions and 92 deletions
|
@ -1,13 +1,23 @@
|
||||||
#ifndef MODEL_LOADER_H
|
#ifndef MODEL_H
|
||||||
#define MODEL_LOADER_H
|
#define MODEL_H
|
||||||
|
|
||||||
typedef struct _model {
|
typedef struct _model {
|
||||||
GLfloat *object;
|
GLfloat *object;
|
||||||
|
GLfloat **transformations;
|
||||||
|
size_t transformation_count;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
} Model;
|
} Model;
|
||||||
|
|
||||||
|
typedef struct _model_registry {
|
||||||
|
Model **models;
|
||||||
|
size_t model_count;
|
||||||
|
size_t size;
|
||||||
|
} ModelRegistry;
|
||||||
|
|
||||||
Model *model_load(const char *);
|
Model *model_load(const char *);
|
||||||
int model_free(Model *);
|
ModelRegistry* modelRegistry_new(void);
|
||||||
|
int modelRegistry_register(ModelRegistry *, Model *);
|
||||||
|
void modelRegistry_free(ModelRegistry *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
183
src/cx.c
183
src/cx.c
|
@ -1,6 +1,77 @@
|
||||||
#include <cx.h>
|
#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
|
// Initialise GLFW
|
||||||
if(!glfwInit()) {
|
if(!glfwInit()) {
|
||||||
fprintf(stderr, "Failed to initialize GLFW\n");
|
fprintf(stderr, "Failed to initialize GLFW\n");
|
||||||
|
@ -41,25 +112,39 @@ int cx_glinit(GLFWwindow **window) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cx_glrun(GLFWwindow *window) {
|
static int
|
||||||
GLuint VertexArrayID;
|
cx_loadShaders(GLuint *VertexArrayID, GLuint *programID) {
|
||||||
GLuint programID;
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &VertexArrayID);
|
glGenVertexArrays(1, VertexArrayID);
|
||||||
glBindVertexArray(VertexArrayID);
|
glBindVertexArray(*VertexArrayID);
|
||||||
|
|
||||||
// Create and compile our GLSL program from the shaders
|
// Create and compile our GLSL program from the shaders
|
||||||
if (LoadShaders(&programID,
|
if (LoadShaders(programID,
|
||||||
"../shaders/SimpleVertexShader.vertexshader",
|
"../shaders/SimpleVertexShader.vertexshader",
|
||||||
"../shaders/SimpleFragmentShader.fragmentshader")) {
|
"../shaders/SimpleFragmentShader.fragmentshader")) {
|
||||||
fprintf(stderr, "Could not load shaders.\n");
|
fprintf(stderr, "Could not load shaders.\n");
|
||||||
return -1;
|
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
|
// Load model to render from file
|
||||||
Model *model;
|
Model *model;
|
||||||
model = model_load("../3d_assets/cube.obj");
|
model = model_load("../3d_assets/cube.obj");
|
||||||
|
// Establish a model registry
|
||||||
|
ModelRegistry *mr;
|
||||||
|
mr = modelRegistry_new();
|
||||||
|
modelRegistry_register(mr, model);
|
||||||
|
|
||||||
// Allocate the render buffer
|
// Allocate the render buffer
|
||||||
// GL uses this to feed the GPU
|
// GL uses this to feed the GPU
|
||||||
|
@ -69,91 +154,20 @@ int cx_glrun(GLFWwindow *window) {
|
||||||
model->bufsize * 4 * sizeof(GLfloat));
|
model->bufsize * 4 * sizeof(GLfloat));
|
||||||
|
|
||||||
// Bind the render buffer to OpenGL
|
// Bind the render buffer to OpenGL
|
||||||
GLuint vertexbuffer;
|
cx_glbufferBind(model->bufsize*4*sizeof(GLfloat), render_buffer, &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
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remainder from cursor experiments, might be useful later
|
// Remainder from cursor experiments, might be useful later
|
||||||
double xpos, ypos;
|
double xpos, ypos;
|
||||||
glfwGetCursorPos(window, &xpos, &ypos);
|
glfwGetCursorPos(window, &xpos, &ypos);
|
||||||
|
|
||||||
GLfloat *rotation_matrix = matrix_new();
|
|
||||||
GLfloat *translation_matrix = matrix_new();
|
|
||||||
|
|
||||||
|
|
||||||
// Temporary storage of transformation results
|
// Temporary storage of transformation results
|
||||||
GLfloat *temp_buffer[2];
|
|
||||||
|
|
||||||
translation_matrix[3] = 0.5f;
|
|
||||||
|
|
||||||
|
|
||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Clear the screen. It's not mentioned before Tutorial 02,
|
cx_glrender(window, programID, render_buffer, vertexbuffer, mr);
|
||||||
// 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);
|
|
||||||
|
|
||||||
t++;
|
t++;
|
||||||
usleep(1000000/60);
|
usleep(1000000/60);
|
||||||
// Check if the ESC key was pressed or the window was closed
|
// 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
|
// Close OpenGL window and terminate GLFW
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
free(rotation_matrix);
|
modelRegistry_free(mr);
|
||||||
model_free(model);
|
|
||||||
free(render_buffer);
|
free(render_buffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cx_nninit(Neural_Network **nn) {
|
int
|
||||||
|
cx_nninit(Neural_Network **nn) {
|
||||||
// Allocate a Neural Network
|
// Allocate a Neural Network
|
||||||
*nn = neural_new(64, 1);
|
*nn = neural_new(64, 1);
|
||||||
if(!*nn) {
|
if(!*nn) {
|
||||||
|
@ -184,7 +198,8 @@ int cx_nninit(Neural_Network **nn) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cx_nnrun(Neural_Network *nn) {
|
int
|
||||||
|
cx_nnrun(Neural_Network *nn) {
|
||||||
|
|
||||||
// Establish a neural interface.
|
// Establish a neural interface.
|
||||||
float *input_buffer = malloc(64*sizeof(float));
|
float *input_buffer = malloc(64*sizeof(float));
|
||||||
|
|
|
@ -13,10 +13,10 @@ main(void) {
|
||||||
Neural_Network *nn;
|
Neural_Network *nn;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
|
||||||
if (cx_glinit(&window)) {
|
if (cx_glinit(&window)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx_nninit(&nn)) {
|
if (cx_nninit(&nn)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
56
src/model.c
56
src/model.c
|
@ -4,10 +4,18 @@ Model *
|
||||||
model_new(size_t size) {
|
model_new(size_t size) {
|
||||||
Model *self = calloc(1, sizeof(Model));
|
Model *self = calloc(1, sizeof(Model));
|
||||||
self->object = calloc((size ? size : 1) *4 , sizeof(GLfloat));
|
self->object = calloc((size ? size : 1) *4 , sizeof(GLfloat));
|
||||||
|
self->transformations = calloc(8 , sizeof(GLfloat*));
|
||||||
self->bufsize = size;
|
self->bufsize = size;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_free(Model *self) {
|
||||||
|
free(self->object);
|
||||||
|
free(self->transformations);
|
||||||
|
free(self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Model *
|
Model *
|
||||||
model_load(const char *path) {
|
model_load(const char *path) {
|
||||||
|
@ -50,7 +58,7 @@ model_load(const char *path) {
|
||||||
}
|
}
|
||||||
} while(check != EOF);
|
} while(check != EOF);
|
||||||
|
|
||||||
self = model_new(facecount*4);
|
self = model_new(facecount*3);
|
||||||
for (int i = 0; i < facecount; i++) {
|
for (int i = 0; i < facecount; i++) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
for (int k = 0; k < 3; k++) {
|
for (int k = 0; k < 3; k++) {
|
||||||
|
@ -66,10 +74,50 @@ model_load(const char *path) {
|
||||||
return self;
|
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
|
int
|
||||||
model_free(Model *self) {
|
modelRegistry_register(ModelRegistry *self, Model *model) {
|
||||||
free(self->object);
|
if (self->model_count >= self->size) {
|
||||||
free(self);
|
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;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue