diff options
Diffstat (limited to '07-july/src/renderer/shape.c')
| -rw-r--r-- | 07-july/src/renderer/shape.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/07-july/src/renderer/shape.c b/07-july/src/renderer/shape.c new file mode 100644 index 0000000..d48b847 --- /dev/null +++ b/07-july/src/renderer/shape.c @@ -0,0 +1,302 @@ +#include "shape.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "../util/util.h" + +#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a) + +shape_t* Shape_CreateFromRawData(vertex_t* vertices, GLsizeiptr vertexBufferSize, + GLushort* indices, GLsizeiptr indexBufferSize) +{ + shape_t* shape = (shape_t*) malloc( sizeof(shape_t) ); + + shape->num_indices = ( indexBufferSize / sizeof(GLushort) ); + + glGenVertexArrays(1, &shape->vao); + glGenBuffers(1, &shape->vbo); + glGenBuffers(1, &shape->ebo); + + glBindVertexArray(shape->vao); + + glBindBuffer(GL_ARRAY_BUFFER, shape->vbo); + glBufferData(GL_ARRAY_BUFFER, vertexBufferSize, vertices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shape->ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSize, indices, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glEnableVertexAttribArray(3); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, position) ); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, color) ); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, texCoord) ); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, normal) ); + + glBindVertexArray(0); + + return shape; +} + +shape_t* Shape_MakeCube() +{ + vertex_t data[] = + { + { {-1.0f, +1.0f, +1.0f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.0f, +1.0f, +0.0f} }, + { {+1.0f, +1.0f, +1.0f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 1.0f}, {+0.0f, +1.0f, +0.0f} }, + { {+1.0f, +1.0f, -1.0f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {1.0f, 1.0f}, {+0.0f, +1.0f, +0.0f} }, + { {-1.0f, +1.0f, -1.0f}, {+1.0f, +1.0f, +1.0f, +1.0f}, {1.0f, 0.0f}, {+0.0f, +1.0f, +0.0f} }, + + { {-1.0f, +1.0f, -1.0f}, {+1.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.0f, +0.0f, -1.0f} }, + { {+1.0f, +1.0f, -1.0f}, {+0.0f, +0.5f, +0.2f, +1.0f}, {0.0f, 1.0f}, {+0.0f, +0.0f, -1.0f} }, + { {+1.0f, -1.0f, -1.0f}, {+0.8f, +0.6f, +0.4f, +1.0f}, {1.0f, 1.0f}, {+0.0f, +0.0f, -1.0f} }, + { {-1.0f, -1.0f, -1.0f}, {+0.3f, +1.0f, +0.5f, +1.0f}, {1.0f, 0.0f}, {+0.0f, +0.0f, -1.0f} }, + + { {+1.0f, +1.0f, -1.0f}, {+0.2f, +0.5f, +0.2f, +1.0f}, {0.0f, 0.0f}, {+1.0f, +0.0f, +0.0f} }, + { {+1.0f, +1.0f, +1.0f}, {+0.9f, +0.3f, +0.7f, +1.0f}, {0.0f, 1.0f}, {+1.0f, +0.0f, +0.0f} }, + { {+1.0f, -1.0f, +1.0f}, {+0.3f, +0.7f, +0.5f, +1.0f}, {1.0f, 1.0f}, {+1.0f, +0.0f, +0.0f} }, + { {+1.0f, -1.0f, -1.0f}, {+0.5f, +0.7f, +0.5f, +1.0f}, {1.0f, 0.0f}, {+1.0f, +0.0f, +0.0f} }, + + { {-1.0f, +1.0f, +1.0f}, {+0.7f, +0.8f, +0.2f, +1.0f}, {0.0f, 0.0f}, {-1.0f, +0.0f, +0.0f} }, + { {-1.0f, +1.0f, -1.0f}, {+0.5f, +0.7f, +0.3f, +1.0f}, {0.0f, 1.0f}, {-1.0f, +0.0f, +0.0f} }, + { {-1.0f, -1.0f, -1.0f}, {+0.4f, +0.7f, +0.7f, +1.0f}, {1.0f, 1.0f}, {-1.0f, +0.0f, +0.0f} }, + { {-1.0f, -1.0f, +1.0f}, {+0.2f, +0.5f, +1.0f, +1.0f}, {1.0f, 0.0f}, {-1.0f, +0.0f, +0.0f} }, + + { {+1.0f, +1.0f, +1.0f}, {+0.6f, +1.0f, +0.7f, +1.0f}, {0.0f, 0.0f}, {+0.0f, +0.0f, +1.0f} }, + { {-1.0f, +1.0f, +1.0f}, {+0.6f, +0.4f, +0.8f, +1.0f}, {0.0f, 1.0f}, {+0.0f, +0.0f, +1.0f} }, + { {-1.0f, -1.0f, +1.0f}, {+0.2f, +0.8f, +0.7f, +1.0f}, {1.0f, 1.0f}, {+0.0f, +0.0f, +1.0f} }, + { {+1.0f, -1.0f, +1.0f}, {+0.2f, +0.7f, +1.0f, +1.0f}, {1.0f, 0.0f}, {+0.0f, +0.0f, +1.0f} }, + + { {+1.0f, -1.0f, -1.0f}, {+0.8f, +0.3f, +0.7f, +1.0f}, {0.0f, 0.0f}, {+0.0f, -1.0f, +0.0f} }, + { {-1.0f, -1.0f, -1.0f}, {+0.8f, +0.9f, +0.5f, +1.0f}, {0.0f, 1.0f}, {+0.0f, -1.0f, +0.0f} }, + { {-1.0f, -1.0f, +1.0f}, {+0.5f, +0.8f, +0.5f, +1.0f}, {1.0f, 1.0f}, {+0.0f, -1.0f, +0.0f} }, + { {+1.0f, -1.0f, +1.0f}, {+0.9f, +1.0f, +0.2f, +1.0f}, {1.0f, 0.0f}, {+0.0f, -1.0f, +0.0f} }, + }; + + GLushort indices[] = { + 0, 1, 2, 0, 2, 3, // Top + 4, 5, 6, 4, 6, 7, // Front + 8, 9, 10, 8, 10, 11, // Right + 12, 13, 14, 12, 14, 15, // Left + 16, 17, 18, 16, 18, 19, // Back + 20, 22, 21, 20, 23, 22, // Bottom + }; + + GLsizeiptr vertexBufferSize = NUM_ARRAY_ELEMENTS(data) * sizeof(vertex_t); + GLsizeiptr indexBufferSize = NUM_ARRAY_ELEMENTS(indices) * sizeof(GLushort); + + return Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize); +} + +shape_t* Shape_MakeArrow() +{ + vertex_t data[] = + { + // Top side of arrow head + { {+0.00f, +0.25f, -0.25f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {+0.50f, +0.25f, -0.25f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {+0.00f, +0.25f, -1.00f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {-0.50f, +0.25f, -0.25f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + // Bottom side of arrow head + { {+0.00f, -0.25f, -0.25f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {+0.50f, -0.25f, -0.25f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {+0.00f, -0.25f, -1.00f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {-0.50f, -0.25f, -0.25f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + // Right side of arrow tip + { {+0.50f, +0.25f, -0.25f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {0.83205032f, 0.00f, -0.55470026f} }, + { {+0.00f, +0.25f, -1.00f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {0.83205032f, 0.00f, -0.55470026f} }, + { {+0.00f, -0.25f, -1.00f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {0.83205032f, 0.00f, -0.55470026f} }, + { {+0.50f, -0.25f, -0.25f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {0.83205032f, 0.00f, -0.55470026f} }, + // Left side of arrow tip + { {+0.00f, +0.25f, -1.00f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-0.55708605f, 0.00f, -0.37139067f} }, + { {-0.50f, +0.25f, -0.25f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-0.55708605f, 0.00f, -0.37139067f} }, + { {+0.00f, -0.25f, -1.00f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-0.55708605f, 0.00f, -0.37139067f} }, + { {-0.50f, -0.25f, -0.25f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-0.55708605f, 0.00f, -0.37139067f} }, + // Back side of arrow tip + { {-0.50f, +0.25f, -0.25f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {+0.50f, +0.25f, -0.25f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {-0.50f, -0.25f, -0.25f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {+0.50f, -0.25f, -0.25f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + // Top side of back of arrow + { {+0.25f, +0.25f, -0.25f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {+0.25f, +0.25f, +1.00f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {-0.25f, +0.25f, +1.00f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + { {-0.25f, +0.25f, -0.25f}, {+1.0f, +0.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +1.00f, +0.00f} }, + // Bottom side of back of arrow + { {+0.25f, -0.25f, -0.25f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {+0.25f, -0.25f, +1.00f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {-0.25f, -0.25f, +1.00f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + { {-0.25f, -0.25f, -0.25f}, {+0.0f, +0.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.00f, -1.00f, +0.00f} }, + // Right side of back of arrow + { {+0.25f, +0.25f, -0.25f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+1.00f, +0.00f, +0.00f} }, + { {+0.25f, -0.25f, -0.25f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+1.00f, +0.00f, +0.00f} }, + { {+0.25f, -0.25f, +1.00f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+1.00f, +0.00f, +0.00f} }, + { {+0.25f, +0.25f, +1.00f}, {+0.6f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {+1.00f, +0.00f, +0.00f} }, + // Left side of back of arrow + { {-0.25f, +0.25f, -0.25f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-1.00f, +0.00f, +0.00f} }, + { {-0.25f, -0.25f, -0.25f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-1.00f, +0.00f, +0.00f} }, + { {-0.25f, -0.25f, +1.00f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-1.00f, +0.00f, +0.00f} }, + { {-0.25f, +0.25f, +1.00f}, {+0.0f, +1.0f, +0.0f, +1.0f}, {0.0f, 0.0f}, {-1.00f, +0.00f, +0.00f} }, + // Back side of back of arrow + { {-0.25f, +0.25f, +1.00f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {+0.25f, +0.25f, +1.00f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {-0.25f, -0.25f, +1.00f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + { {+0.25f, -0.25f, +1.00f}, {+0.5f, +0.5f, +0.5f, +1.0f}, {0.0f, 0.0f}, {+0.00f, +0.00f, +1.00f} }, + }; + + GLushort indices[] = { + 0, 1, 2, // Top + 0, 2, 3, + 4, 6, 5, // Bottom + 4, 7, 6, + 8, 10, 9, // Right side of arrow tip + 8, 11, 10, + 12, 15, 13, // Left side of arrow tip + 12, 14, 15, + 16, 19, 17, // Back side of arrow tip + 16, 18, 19, + 20, 22, 21, // Top side of back of arrow + 20, 23, 22, + 24, 25, 26, // Bottom side of back of arrow + 24, 26, 27, + 28, 30, 29, // Right side of back of arrow + 28, 31, 30, + 32, 33, 34, // Left side of back of arrow + 32, 34, 35, + 36, 39, 37, // Back side of back of arrow + 36, 38, 39, + }; + + GLsizeiptr vertexBufferSize = NUM_ARRAY_ELEMENTS(data) * sizeof(vertex_t); + GLsizeiptr indexBufferSize = NUM_ARRAY_ELEMENTS(indices) * sizeof(GLushort); + + return Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize); +} + +shape_t* Shape_MakeQuad() +{ + vertex_t data[] = + { + { {+1.0f, +1.0f, +0.0f}, {+1.0f, +1.0f, +1.0f, +1.0f}, {1.0f, 1.0f}, {+0.0f, +0.0f, +1.0f} }, + { {-1.0f, +1.0f, +0.0f}, {+1.0f, +1.0f, +1.0f, +1.0f}, {0.0f, 1.0f}, {+0.0f, +0.0f, +1.0f} }, + { {+1.0f, -1.0f, +0.0f}, {+1.0f, +1.0f, +1.0f, +1.0f}, {1.0f, 0.0f}, {+0.0f, +0.0f, +1.0f} }, + { {-1.0f, -1.0f, +0.0f}, {+1.0f, +1.0f, +1.0f, +1.0f}, {0.0f, 0.0f}, {+0.0f, +0.0f, +1.0f} }, + }; + + GLushort indices[] = + { + 0, 1, 2, 1, 3, 2 + }; + + GLsizeiptr vertexBufferSize = NUM_ARRAY_ELEMENTS(data) * sizeof(vertex_t); + GLsizeiptr indexBufferSize = NUM_ARRAY_ELEMENTS(indices) * sizeof(GLushort); + + return Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize); +} + +#define BUFFER_SIZE 128 + +shape_t* Shape_LoadOBJ(const char* path) +{ + vec3_t* vertices = NULL; + vec2_t* textures = NULL; + vec3_t* normals = NULL; + + vertex_t* data = NULL; + GLushort* indices = NULL; + + unsigned int vertices_count = 0, textures_count = 0, normals_count = 0, index_pointer = 0, faces_count = 0; + int count = 0; + int texture[3], normal[3], verts[3]; + + FILE* file = fopen(path, "r"); + if(file == NULL) + Util_FatalError(".obj file could not be loaded!"); + + char buffer[BUFFER_SIZE]; + while(!feof(file)) + { + fgets(buffer, BUFFER_SIZE, file); + switch(buffer[0]) + { + case 'v': + if(buffer[1] == 't') { + textures = (vec2_t*) realloc(textures, sizeof(vec2_t) * (++textures_count) ); + count = sscanf(buffer, "vt %f %f\n", &textures[textures_count-1].x, &textures[textures_count-1].y); + if(count != 2) + Util_FatalError("Bad texture coordinates on .obj file"); + } else if(buffer[1] == 'n') { + normals = (vec3_t*) realloc(normals, sizeof(vec3_t) * (++normals_count) ); + count = sscanf(buffer, "vn %f %f %f\n", &normals[normals_count-1].x, + &normals[normals_count-1].y, &normals[normals_count-1].z); + if(count != 3) + Util_FatalError("Bad normals data on .obj file"); + } else { + vertices = (vec3_t*) realloc(vertices, sizeof(vec3_t) * (++vertices_count) ); + count = sscanf(buffer, "v %f %f %f\n", &vertices[vertices_count-1].x, + &vertices[vertices_count-1].y, &vertices[vertices_count-1].z); + if(count != 3) + Util_FatalError("Bad vertices data on .obj file"); + } + break; + case 'f': + data = (vertex_t*) realloc( data, sizeof(vertex_t) * (++faces_count * 3) ); + indices = (GLushort*) realloc( indices, sizeof(GLushort) * (++faces_count * 3) ); + + count = sscanf(buffer, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", + &verts[0], &texture[0], &normal[0], &verts[1], &texture[1], &normal[1], + &verts[2], &texture[2], &normal[2]); + if(count != 9) + Util_FatalError("Bad face data on .obj file"); + + indices[index_pointer] = index_pointer; + data[index_pointer].position = vertices[verts[0]-1]; + data[index_pointer].texCoord = textures[texture[0]-1]; + data[index_pointer++].normal = normals[normal[0]-1]; + + indices[index_pointer] = index_pointer; + data[index_pointer].position = vertices[verts[1]-1]; + data[index_pointer].texCoord = textures[texture[1]-1]; + data[index_pointer++].normal = normals[normal[1]-1]; + + indices[index_pointer] = index_pointer; + data[index_pointer].position = vertices[verts[2]-1]; + data[index_pointer].texCoord = textures[texture[2]-1]; + data[index_pointer++].normal = normals[normal[2]-1]; + + break; + default: + break; + } + } + + free(vertices); + free(normals); + free(textures); + fclose(file); + + /*Remember, each face contains 3 vertex -> (faces_count * 3)*/ + + GLsizeiptr vertexBufferSize = faces_count * sizeof(vertex_t) * 3; + GLsizeiptr indexBufferSize = faces_count * sizeof(GLushort) * 3; + + shape_t* shape = Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize); + + free(data); + free(indices); + + return shape; +} + +void Shape_Free(shape_t* shape) +{ + if(shape) + { + glDeleteBuffers(1, &shape->vbo); + glDeleteBuffers(1, &shape->ebo); + glDeleteVertexArrays(1, &shape->vao); + free(shape); + } +} |
