aboutsummaryrefslogtreecommitdiff
path: root/07-july/src/renderer
diff options
context:
space:
mode:
authorThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:02:32 +0100
committerThomas Guillermo Albers Raviola <thomas@thomaslabs.org>2026-01-16 23:02:32 +0100
commit6b8af9cf83851c075c6c9514b1deaa931c2b19a4 (patch)
tree428986b49c32e21d3f7a3c2dfa41858ae0153209 /07-july/src/renderer
Initial commit
Diffstat (limited to '07-july/src/renderer')
-rw-r--r--07-july/src/renderer/entity.c18
-rw-r--r--07-july/src/renderer/entity.h20
-rw-r--r--07-july/src/renderer/renderer.c98
-rw-r--r--07-july/src/renderer/renderer.h15
-rw-r--r--07-july/src/renderer/shape.c302
-rw-r--r--07-july/src/renderer/shape.h25
6 files changed, 478 insertions, 0 deletions
diff --git a/07-july/src/renderer/entity.c b/07-july/src/renderer/entity.c
new file mode 100644
index 0000000..b96491d
--- /dev/null
+++ b/07-july/src/renderer/entity.c
@@ -0,0 +1,18 @@
+#include "entity.h"
+
+mat4_t Entity_GetModelTransform(entity_t* entity)
+{
+ mat4_t temp;
+ mat4_t rotation = mat4_rotate_x(entity->rotX);
+ temp = mat4_rotate_y(entity->rotY);
+ rotation = mat4_mul(&rotation, &temp);
+ temp = mat4_rotate_z(entity->rotZ);
+ rotation = mat4_mul(&rotation, &temp);
+
+ temp = mat4_translate(&entity->position);
+
+ mat4_t modelTransform = mat4_mul(&temp, &rotation);
+
+ return modelTransform;
+}
+
diff --git a/07-july/src/renderer/entity.h b/07-july/src/renderer/entity.h
new file mode 100644
index 0000000..8954c7f
--- /dev/null
+++ b/07-july/src/renderer/entity.h
@@ -0,0 +1,20 @@
+#ifndef ENTITY_H
+#define ENTITY_H
+
+#include "../math/vector3f.h"
+#include "../math/matrix4x4.h"
+
+#include "shape.h"
+#include "../texture.h"
+
+typedef struct
+{
+ shape_t *shape;
+ texture_t *texture;
+ vec3_t position;
+ float rotX, rotY, rotZ;
+} entity_t;
+
+extern mat4_t Entity_GetModelTransform(entity_t* entity);
+
+#endif // ENTITY_H
diff --git a/07-july/src/renderer/renderer.c b/07-july/src/renderer/renderer.c
new file mode 100644
index 0000000..5b8638c
--- /dev/null
+++ b/07-july/src/renderer/renderer.c
@@ -0,0 +1,98 @@
+#include "renderer.h"
+#include <string.h>
+
+static const int MAX_LIGHTS = 4;
+
+void Render_Init()
+{
+
+}
+
+void Render_LoadLights(Shader_Layout *layout, light_t *lights, int n)
+{
+ vec3_t light_positions[MAX_LIGHTS];
+ color_t light_colors[MAX_LIGHTS];
+ vec3_t attenuation[MAX_LIGHTS];
+
+ light_t defaultLight = { {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f} };
+
+ int i;
+ for(i = 0; i < MAX_LIGHTS; i++)
+ {
+ if(i < MAX_LIGHTS)
+ {
+ light_positions[i] = lights[i].position;
+ light_colors[i] = lights[i].color;
+ attenuation[i] = lights[i].attenuation;
+ }
+ else
+ {
+ light_positions[i] = defaultLight.position;
+ light_colors[i] = defaultLight.color;
+ attenuation[i] = defaultLight.attenuation;
+ }
+
+ }
+
+ glUniform3fv(layout->lightPosition, MAX_LIGHTS, (float*)light_positions);
+ glUniform4fv(layout->lightColor, MAX_LIGHTS, (float*)light_colors);
+ glUniform3fv(layout->lightAttenuation, MAX_LIGHTS, (float*)attenuation);
+
+}
+
+void Render_DrawEntity(Shader_Layout *layout, mat4_t *projectedViewMatrix, entity_t *entity)
+{
+ glBindVertexArray(entity->shape->vao);
+
+ /*We need the model to world matrix in our shader in order to rotate the normals*/
+ mat4_t modelTransform = Entity_GetModelTransform(entity);
+ glUniformMatrix4fv(layout->modelToWorld, 1, GL_FALSE, modelTransform.data);
+
+ mat4_t totalMatrix = mat4_mul(projectedViewMatrix, &modelTransform);
+ glUniformMatrix4fv(layout->totalTransform, 1, GL_FALSE, totalMatrix.data);
+
+ glActiveTexture(GL_TEXTURE0);
+ glUniform1i(layout->Texture, 0);
+ Texture_Bind(entity->texture);
+
+ glDrawElements(GL_TRIANGLES, entity->shape->num_indices, GL_UNSIGNED_SHORT, NULL);
+ glBindVertexArray(0);
+}
+
+void Render_DrawTerrain(Shader_Layout *layout, mat4_t *projectedViewMatrix, terrain_t *terrain)
+{
+ glBindVertexArray(terrain->shape->vao);
+
+ /* We need the model to world matrix in our shader in order to rotate the normals */
+ mat4_t modelTransform = mat4_translate(&terrain->position);
+ glUniformMatrix4fv(layout->modelToWorld, 1, GL_FALSE, modelTransform.data);
+
+ mat4_t totalMatrix = mat4_mul(projectedViewMatrix, &modelTransform);
+ glUniformMatrix4fv(layout->totalTransform, 1, GL_FALSE, totalMatrix.data);
+
+ glUniform1i(layout->Texture_Background, 0);
+ glUniform1i(layout->Texture_R, 1);
+ glUniform1i(layout->Texture_G, 2);
+ glUniform1i(layout->Texture_B, 3);
+ glUniform1i(layout->Texture_BlendMap, 4);
+
+ glActiveTexture(GL_TEXTURE0);
+ Texture_Bind(terrain->textures.texture[0]);
+ glActiveTexture(GL_TEXTURE1);
+ Texture_Bind(terrain->textures.texture[1]);
+ glActiveTexture(GL_TEXTURE2);
+ Texture_Bind(terrain->textures.texture[2]);
+ glActiveTexture(GL_TEXTURE3);
+ Texture_Bind(terrain->textures.texture[3]);
+ glActiveTexture(GL_TEXTURE4);
+ Texture_Bind(terrain->blendmap);
+
+ glDrawElements(GL_TRIANGLES, terrain->shape->num_indices, GL_UNSIGNED_SHORT, NULL);
+
+ glBindVertexArray(0);
+}
+
+void Render_Quit()
+{
+
+}
diff --git a/07-july/src/renderer/renderer.h b/07-july/src/renderer/renderer.h
new file mode 100644
index 0000000..7d06fdc
--- /dev/null
+++ b/07-july/src/renderer/renderer.h
@@ -0,0 +1,15 @@
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "../graphics/shaders.h"
+#include "entity.h"
+#include "../terrain.h"
+#include "../light.h"
+
+extern void Render_Init();
+extern void Render_LoadLights(Shader_Layout *layout, light_t *lights, int n);
+extern void Render_DrawEntity(Shader_Layout *layout, mat4_t *projectedViewMatrix, entity_t *entity);
+extern void Render_DrawTerrain(Shader_Layout *layout, mat4_t *projectedViewMatrix, terrain_t *terrain);
+extern void Render_Quit();
+
+#endif // RENDERER_H
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);
+ }
+}
diff --git a/07-july/src/renderer/shape.h b/07-july/src/renderer/shape.h
new file mode 100644
index 0000000..b019333
--- /dev/null
+++ b/07-july/src/renderer/shape.h
@@ -0,0 +1,25 @@
+#ifndef SHAPE_H
+#define SHAPE_H
+
+#include "../vertex.h"
+
+typedef struct
+{
+ GLuint num_indices;
+ GLuint vbo, ebo, vao;
+} shape_t;
+
+extern shape_t* Shape_MakeCube();
+extern shape_t* Shape_MakeArrow();
+extern shape_t* Shape_MakeQuad();
+
+extern shape_t* Shape_LoadOBJ(const char* path);
+
+extern shape_t* Shape_CreateFromRawData(vertex_t* vertices, GLsizeiptr vertexBufferSize,
+ GLushort* indices, GLsizeiptr indexBufferSize);
+
+extern void Shape_Free(shape_t* shape);
+
+
+
+#endif // SHAPE_H