Implement .obj loader

This commit is contained in:
Marcel Plch 2018-04-23 00:40:31 +02:00
parent 677177cd49
commit d3ff1ed2ad
12 changed files with 1291 additions and 152 deletions

View file

@ -1,7 +1,7 @@
# CMake entry point
cmake_minimum_required (VERSION 3.0)
project(OpenGL_Analog_Clock C)
cmake_policy(SET CMP0072 OLD)
cmake_policy(SET CMP0072 NEW)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
@ -28,13 +28,16 @@ add_definitions(
-D_CRT_SECURE_NO_WARNINGS
)
add_executable(clock
add_executable(
clock
src/main.c
src/clock.c
src/shader.c
src/matrix.c
src/model.c
)
target_link_libraries(clock
target_link_libraries(
clock
${ALL_LIBS}
)

View file

@ -15,8 +15,9 @@
#include <GLFW/glfw3.h>
// Include project headers
#include <shader.h>
#include <model.h>
#include <matrix.h>
#include <shader.h>
// Define macros
#define xfree(p) if (p) free((void *)p)
@ -24,5 +25,7 @@
// Declare functions
int clock_init(GLFWwindow **);
int clock_run(GLFWwindow *);
#endif

View file

@ -1,9 +1,12 @@
#ifndef MATRIX_H
#define MATRIX_H
GLdouble *matrix_new(void);
GLfloat *matrix_new(void);
int matrix_transform(GLdouble *, int,
GLdouble **, int);
GLfloat *matrix_multip(GLfloat *, GLfloat *);
GLfloat *matrix_transform(GLfloat *, int,
GLfloat *);
#endif

12
Include/model.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef MODEL_LOADER_H
#define MODEL_LOADER_H
typedef struct _model {
GLfloat *buffer;
size_t bufsize;
} Model;
Model * model_load(const char *path);
#endif

View file

@ -4,3 +4,4 @@
int LoadShaders(GLuint *, const char *, const char *);
#endif

1009
cube.obj Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,8 @@
#version 330 core
// Ouput data
out vec3 color;
void main()
{
void main() {
color = vec3(1, 0, 0);
// Output color = red
color = vec3(1,0,0);
}
}

View file

@ -1,6 +1,7 @@
#include <clock.h>
int clock_init(GLFWwindow **window) {
int
clock_init(GLFWwindow **window) {
// Initialise GLFW
if(!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
@ -40,3 +41,141 @@ int clock_init(GLFWwindow **window) {
return 0;
}
int
clock_run(GLFWwindow *window) {
GLuint VertexArrayID;
GLuint programID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
if (LoadShaders(&programID,
"../shaders/SimpleVertexShader.vertexshader",
"../shaders/SimpleFragmentShader.fragmentshader")) {
fprintf(stderr, "Could not load shaders.\n");
return -1;
}
static GLfloat g_vertex_buffer_data[] = {
-0.3f, -0.3f, 0.0f, 1.0f,
0.3f, -0.3f, 0.0f, 1.0f,
0.0f, 0.3f, 0.0f, 1.0f
};
Model *model;
model = model_load("../cube.obj");
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, model->bufsize*4*sizeof(GLfloat), model->buffer, GL_STATIC_DRAW);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
GLfloat **matrices = malloc(2 * sizeof(GLfloat *));
GLfloat *temp = matrix_new();
//temp[0] = cos(M_PI*2/60);
//temp[1] = -sin(M_PI*2/60);
//temp[4] = sin(M_PI*2/60);
//temp[5] = cos(M_PI*2/60);
matrices[0] = temp;
temp = matrix_new();
temp[0] = cos(M_PI*2/60/4);
temp[8] = -sin(M_PI*2/60/4);
temp[2] = sin(M_PI*2/60/4);
temp[10] = cos(M_PI*2/60/4);
matrices[1] = temp;
GLfloat *mat = matrix_new();
for (int i = 1; i >= 0; i--) {
temp = matrix_multip(matrices[i], mat);
free(mat);
mat = temp;
}
GLfloat *projection = matrix_new();
GLfloat *buffer;
projection[14] = -1.0f;
buffer = matrix_new();
buffer[0] = (GLfloat)9/16;
temp = matrix_multip(projection, buffer);
free(projection);
projection = buffer;
temp = malloc(model->bufsize * 4 * sizeof(GLfloat));
buffer = malloc(model->bufsize * 4 * sizeof(GLfloat));
memcpy(temp, model->buffer, model->bufsize * 4 * sizeof(GLfloat));
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);
//glfwGetCursorPos(window, &xpos, &ypos);
//g_vertex_buffer_data[0] = (float)xpos / 1280 * 2 - 1 - 0.15;
//g_vertex_buffer_data[1] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[3] = (float)xpos / 1280 * 2 - 1 + 0.15;
//g_vertex_buffer_data[4] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[6] = (float)xpos / 1280 * 2 - 1;
//g_vertex_buffer_data[7] = 2 - (float)ypos / 720 * 2 - 1 + 0.15;
buffer = matrix_transform(temp, model->bufsize, mat);
free(temp);
temp = buffer;
buffer = matrix_transform(buffer, model->bufsize, projection);
memcpy(model->buffer, buffer, model->bufsize * 4 * sizeof(GLfloat));
free(buffer);
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, model->bufsize * 4 * sizeof(GLfloat), model->buffer, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
4, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
NULL // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, model->bufsize); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
// Check if the ESC key was pressed or the window was closed
usleep(1000000/60);
} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Close OpenGL window and terminate GLFW
for (int i = 0; i < 2; i++) {
free(matrices[i]);
}
free(matrices);
glfwTerminate();
return 0;
}

View file

@ -1,106 +1,14 @@
// Include APIs
#include "clock.h"
int main(int argc, char *argv[]) {
int
main(int argc, char *argv[]) {
GLFWwindow *window;
GLuint VertexArrayID;
GLuint programID;
if (clock_init(&window)) {
return -1;
}
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
if (LoadShaders(&programID,
"../shaders/SimpleVertexShader.vertexshader",
"../shaders/SimpleFragmentShader.fragmentshader")) {
fprintf(stderr, "Could not load shaders.\n");
return -1;
}
static GLdouble g_vertex_buffer_data[] = {
-0.3f, -0.3f, 0.3f,
0.3f, -0.3f, -0.3f,
0.0f, 0.3f, -0.0f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
GLdouble **matrices = calloc(1, sizeof(GLdouble *));
GLdouble *rot_mat = matrix_new();
rot_mat[0] = cos(M_PI*2/60);
rot_mat[1] = -sin(M_PI*2/60);
rot_mat[4] = sin(M_PI*2/60);
rot_mat[5] = cos(M_PI*2/60);
*matrices = rot_mat;
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);
//glfwGetCursorPos(window, &xpos, &ypos);
//g_vertex_buffer_data[0] = (float)xpos / 1280 * 2 - 1 - 0.15;
//g_vertex_buffer_data[1] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[3] = (float)xpos / 1280 * 2 - 1 + 0.15;
//g_vertex_buffer_data[4] = 2 - (float)ypos / 720 * 2 - 1 - 0.15;
//g_vertex_buffer_data[6] = (float)xpos / 1280 * 2 - 1;
//g_vertex_buffer_data[7] = 2 - (float)ypos / 720 * 2 - 1 + 0.15;
matrix_transform(g_vertex_buffer_data, 3,
matrices, 1);
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_DOUBLE, // type
GL_FALSE, // normalized?
0, // stride
NULL // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
// Check if the ESC key was pressed or the window was closed
usleep(1000000/60);
} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
return clock_run(window);
}

View file

@ -1,9 +1,23 @@
#include "clock.h"
static GLdouble *
matrix_multip(GLdouble *mat1, GLdouble *mat2) {
GLdouble *result;
GLdouble dot_prod;
GLfloat *
matrix_new() {
GLfloat *mat;
mat = calloc(16, sizeof(GLfloat));
for (int i = 0; i < 4; i++) {
mat[i*4+i] = 1;
}
return mat;
}
GLfloat *
matrix_multip(GLfloat *mat1, GLfloat *mat2) {
GLfloat *result;
GLfloat dot_prod;
result = matrix_new();
@ -17,54 +31,36 @@ matrix_multip(GLdouble *mat1, GLdouble *mat2) {
result[j+i*4] = dot_prod;
}
}
return result;
}
GLdouble *
matrix_new() {
GLdouble *mat;
mat = calloc(16, sizeof(GLdouble));
for (int i = 0; i < 4; i++) {
mat[i*4+i] = 1;
}
GLfloat *
matrix_transform(GLfloat *vects, int vectcount,
GLfloat *mat) {
GLfloat dot_prod;
GLfloat *helper = NULL;
GLfloat *result;
return mat;
}
result = calloc(vectcount*4, sizeof(GLfloat));
int
matrix_transform(GLdouble *vects, int vectcount,
GLdouble **mats, int matcount) {
GLdouble *mat;
GLdouble dot_prod;
GLdouble *helper = NULL;
GLdouble *result;
mat = matrix_new();
result = calloc(vectcount*3, sizeof(GLdouble));
for (int i = matcount-1; i >= 0; i--) {
xfree(helper);
helper = matrix_multip(mats[i], mat);
free(mat);
mat = helper;
}
for (int k = 0; k < vectcount; k++) {
for (int j = 0; j < 3; j++) {
for (int j = 0; j < 4; j++) {
dot_prod = 0;
for (int i = 0; i < 3; i++) {
dot_prod += vects[k*3+i] * mat[i+j*4];
for (int i = 0; i < 4; i++) {
dot_prod += vects[k*4+i] * mat[i+j*4];
}
result[j+k*4] = dot_prod;
}
if (result[k*4+3] != 0.0f) {
GLfloat div = result[k*4+3];
for (int i = 0; i < 4; i++) {
result[k*4+i] /= div;
}
result[j+k*3] = dot_prod;
}
}
memcpy(vects, result, vectcount * 3 * sizeof(GLdouble));
free(result);
return 0;
return result;
}

70
src/model.c Normal file
View file

@ -0,0 +1,70 @@
#include <clock.h>
Model *
model_new(size_t size) {
Model *model = calloc(1, sizeof(Model));
model->buffer = calloc((size ? size : 1) *4 , sizeof(GLfloat));
model->bufsize = size;
}
void
model_free(Model *self) {
free(self->buffer);
free(self);
}
Model *
model_load(const char *path) {
Model *model;
GLfloat *vertices;
int *faces;
size_t vertcount, facecount;
char type, check, *line;
FILE *f;
f = fopen(path, "r");
line = malloc(255);
vertices = malloc(3 * sizeof(GLfloat));
faces = malloc(3 * sizeof(int));
type = 0;
vertcount = 0;
facecount = 0;
do {
check = fscanf(f, "%c", &type);
if (check == EOF) {
break;
}
else if (type == 'v') {
vertices = realloc(vertices, (vertcount+1)*3*sizeof(GLfloat));
check = fscanf(f, "%f %f %f\n", &(vertices[vertcount*3]),
&(vertices[vertcount*3+1]),
&(vertices[vertcount*3+2]));
vertcount++;
}
else if (type == 'f') {
faces = realloc(faces, (facecount+1)*3*sizeof(GLfloat));
check = fscanf(f, "%d %d %d\n", &(faces[facecount*3]),
&(faces[facecount*3+1]),
&(faces[facecount*3+2]));
facecount++;
}
else {
check = fscanf(f, "%*[^\n]\n", NULL);
continue;
}
} while(check != EOF);
model = 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++) {
model->buffer[i*12+j*4+k] = vertices[(faces[i*3+j]-1)*3+k];
}
model->buffer[i*12+j*4+3] = 1;
}
}
return model;
}

View file

@ -116,4 +116,3 @@ end:
return retval;
}