aboutsummaryrefslogtreecommitdiff
path: root/07-july/src
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
Initial commit
Diffstat (limited to '07-july/src')
-rw-r--r--07-july/src/camera.c85
-rw-r--r--07-july/src/camera.h32
-rw-r--r--07-july/src/game.h42
-rw-r--r--07-july/src/graphics/shaders.c134
-rw-r--r--07-july/src/graphics/shaders.h46
-rw-r--r--07-july/src/graphics/video.c14
-rw-r--r--07-july/src/graphics/video.h7
-rw-r--r--07-july/src/graphics/window.c44
-rw-r--r--07-july/src/graphics/window.h20
-rw-r--r--07-july/src/gui/gui_renderer.c0
-rw-r--r--07-july/src/gui/gui_renderer.h9
-rw-r--r--07-july/src/gui/widget.c17
-rw-r--r--07-july/src/gui/widget.h13
-rw-r--r--07-july/src/input.c21
-rw-r--r--07-july/src/input.h11
-rw-r--r--07-july/src/light.c1
-rw-r--r--07-july/src/light.h13
-rw-r--r--07-july/src/main.c227
-rw-r--r--07-july/src/math/math_util.c10
-rw-r--r--07-july/src/math/math_util.h9
-rw-r--r--07-july/src/math/matrix4x4.c180
-rw-r--r--07-july/src/math/matrix4x4.h35
-rw-r--r--07-july/src/math/vector2f.c60
-rw-r--r--07-july/src/math/vector2f.h20
-rw-r--r--07-july/src/math/vector3f.c65
-rw-r--r--07-july/src/math/vector3f.h20
-rw-r--r--07-july/src/math/vector4f.c70
-rw-r--r--07-july/src/math/vector4f.h20
-rw-r--r--07-july/src/player.c62
-rw-r--r--07-july/src/player.h17
-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
-rw-r--r--07-july/src/terrain.c163
-rw-r--r--07-july/src/terrain.h27
-rw-r--r--07-july/src/texture.c47
-rw-r--r--07-july/src/texture.h18
-rw-r--r--07-july/src/util/util.c49
-rw-r--r--07-july/src/util/util.h19
-rw-r--r--07-july/src/util/util_time.c52
-rw-r--r--07-july/src/util/util_time.h13
-rw-r--r--07-july/src/vertex.h21
45 files changed, 2191 insertions, 0 deletions
diff --git a/07-july/src/camera.c b/07-july/src/camera.c
new file mode 100644
index 0000000..9afadf2
--- /dev/null
+++ b/07-july/src/camera.c
@@ -0,0 +1,85 @@
+#include "camera.h"
+
+#include "util/util_time.h"
+
+static const float movementSpeed = 40.0f;
+
+void Camera_Init(camera_t* camera)
+{
+ camera->position = vec3_create(5.0f, 15.0f, 0.0f);
+ camera->viewDirection = vec3_create(-1.0f, 0.0f, 0.0f);
+ camera->needsUpdate = true;
+ camera->up = vec3_create(0.0f, 1.0f, 0.0f);
+}
+
+void Camera_Move_Up(camera_t* camera)
+{
+ vec3_t temp = vec3_scalar_mul(&camera->up, movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &temp);
+}
+
+void Camera_Move_Down(camera_t* camera)
+{
+ vec3_t temp = vec3_scalar_mul(&camera->up, -movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &temp);
+}
+
+void Camera_Move_Left(camera_t* camera)
+{
+ vec3_t strafeDirection = vec3_cross_mul(&camera->viewDirection, &camera->up);
+ strafeDirection = vec3_scalar_mul(&strafeDirection, -movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &strafeDirection);
+}
+
+void Camera_Move_Right(camera_t* camera)
+{
+ vec3_t strafeDirection = vec3_cross_mul(&camera->viewDirection, &camera->up);
+ strafeDirection = vec3_scalar_mul(&strafeDirection, movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &strafeDirection);
+}
+
+void Camera_Move_Foward(camera_t* camera)
+{
+ vec3_t temp = vec3_scalar_mul(&camera->viewDirection, movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &temp);
+}
+
+void Camera_Move_Backward(camera_t* camera)
+{
+ vec3_t temp = vec3_scalar_mul(&camera->viewDirection, -movementSpeed * Time_GetFrameTime());
+ camera->position = vec3_add(&camera->position, &temp);
+}
+
+void Camera_MouseUpdate(camera_t* camera, const vec2_t* newMousePosition)
+{
+ vec2_t mouseDelta = vec2_sub(newMousePosition, &camera->mousePosition);
+
+ //El if evita que el mouse se teletrasporte al cambiar de posicion muy rapido
+ if(vec2_length(&mouseDelta) > 50.0f){
+ camera->mousePosition = *newMousePosition;
+ return;
+ }
+
+ vec3_t verticalRotation = vec3_cross_mul(&camera->viewDirection, &camera->up);
+
+ mat4_t temp = mat4_rotate(mouseDelta.x * -0.5f, &camera->up);
+
+ camera->viewDirection = mat4_mul_vec3(&temp, &camera->viewDirection);
+
+ temp = mat4_rotate(mouseDelta.y * -0.5f, &verticalRotation);
+ camera->viewDirection = mat4_mul_vec3(&temp, &camera->viewDirection);
+
+ camera->mousePosition = *newMousePosition;
+
+ camera->needsUpdate = true;
+}
+
+mat4_t Camera_GetModelToViewMatrix(camera_t* camera)
+{
+ if(camera->needsUpdate)
+ {
+ vec3_t temp = vec3_add(&camera->position, &camera->viewDirection);
+ camera->viewMatrix = mat4_lookAt(&camera->position, &temp, &camera->up);
+ }
+ return camera->viewMatrix;
+}
diff --git a/07-july/src/camera.h b/07-july/src/camera.h
new file mode 100644
index 0000000..4254045
--- /dev/null
+++ b/07-july/src/camera.h
@@ -0,0 +1,32 @@
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include "math/matrix4x4.h"
+#include "math/vector3f.h"
+#include "math/vector2f.h"
+#include <stdbool.h>
+
+typedef struct
+{
+ vec3_t position;
+ vec3_t viewDirection;
+ vec3_t up;
+ mat4_t projectionMatrix;
+ mat4_t viewMatrix;
+ vec2_t mousePosition;
+ bool needsUpdate;
+} camera_t;
+
+extern void Camera_Init(camera_t* camera);
+extern void Camera_Move_Up(camera_t* camera);
+extern void Camera_Move_Down(camera_t* camera);
+extern void Camera_Move_Left(camera_t* camera);
+extern void Camera_Move_Right(camera_t* camera);
+extern void Camera_Move_Foward(camera_t* camera);
+extern void Camera_Move_Backward(camera_t* camera);
+extern void Camera_MouseUpdate(camera_t* camera, const vec2_t* newMousePosition);
+
+//Consigue la viewMatrix
+extern mat4_t Camera_GetModelToViewMatrix(camera_t* camera);
+
+#endif // CAMERA_H
diff --git a/07-july/src/game.h b/07-july/src/game.h
new file mode 100644
index 0000000..8ba77ed
--- /dev/null
+++ b/07-july/src/game.h
@@ -0,0 +1,42 @@
+#ifndef GAME_H
+#define GAME_H
+
+#include "camera.h"
+#include "graphics/window.h"
+#include "renderer/entity.h"
+#include "player.h"
+#include "terrain.h"
+#include "texture.h"
+#include "renderer/shape.h"
+#include "graphics/shaders.h"
+
+typedef enum
+{
+ MENU,
+ RUNNING,
+ EXIT
+}GameState_t;
+
+#define NUM_ENTITIES 1
+
+#define WINDOW_WIDTH 1024
+#define WINDOW_HEIGHT 768
+#define WINDOW_ASPECT_RATIO ( (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT )
+
+typedef struct
+{
+ GameState_t gameState;
+ Shader_Layout shaderProgram, terrainProgram;
+
+ entity_t ents[NUM_ENTITIES];
+ shape_t *entsShape;
+ texture_t *entsTexture;
+ terrain_t *terrain;
+
+ player_t player;
+
+ camera_t camera;
+ window_t *window;
+} game_t;
+
+#endif // GAME_H
diff --git a/07-july/src/graphics/shaders.c b/07-july/src/graphics/shaders.c
new file mode 100644
index 0000000..ef4ec0a
--- /dev/null
+++ b/07-july/src/graphics/shaders.c
@@ -0,0 +1,134 @@
+#include "shaders.h"
+#include "../util/util.h"
+
+#include <stdlib.h>
+
+static void CompileShader(const char* source, GLuint shaderID)
+{
+ glShaderSource(shaderID, 1, &source, 0);
+ glCompileShader(shaderID);
+ GLint error;
+ glGetShaderiv(shaderID, GL_COMPILE_STATUS, &error);
+ if(error != GL_TRUE)
+ {
+ GLint logLenth;
+ glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLenth);
+ GLchar buffer[logLenth];
+ glGetShaderInfoLog(shaderID, logLenth, &logLenth, buffer);
+ glDeleteShader(shaderID);
+ Util_FatalError(buffer);
+ }
+}
+
+
+GLuint Shader_CompileShaders(const char* vertexShader, const char* fragmentShader)
+{
+ char* vertexShaderSource = Util_LoadFile(vertexShader);
+ char* fragmentShaderSource = Util_LoadFile(fragmentShader);
+
+ GLuint vs = 0, fs = 0, program;
+ vs = glCreateShader(GL_VERTEX_SHADER);
+ fs = glCreateShader(GL_FRAGMENT_SHADER);
+
+ if(vs == 0 || fs == 0)
+ Util_FatalError("Shaders could not be created\n");
+
+ program = glCreateProgram();
+
+ CompileShader(vertexShaderSource, vs);
+ CompileShader(fragmentShaderSource, fs);
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+
+ glLinkProgram(program);
+
+ GLint error;
+ glGetProgramiv(program, GL_LINK_STATUS, &error);
+
+ if(error != GL_TRUE)
+ {
+ GLint logLength;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+
+ GLchar buffer[logLength];
+ glGetProgramInfoLog(program, logLength, &logLength, buffer);
+
+ glDeleteProgram(program);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ Util_FatalError(buffer);
+ }
+
+ glDetachShader(program, vs);
+ glDetachShader(program, fs);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ free(vertexShaderSource);
+ free(fragmentShaderSource);
+
+ return program;
+}
+
+GLint Shader_GetUniformLocation( GLuint programID, const char* uniformName )
+{
+ GLint u = glGetUniformLocation(programID, uniformName);
+ if(u == GL_INVALID_INDEX)
+ Util_FatalError("Uniform variable could not be found!");
+ else
+ return u;
+
+ return 0;
+}
+
+GLint Shader_GetAttribLocation ( GLuint programID, const char* attributeName )
+{
+ GLint attrLocation = glGetAttribLocation(programID, attributeName);
+ if(attrLocation < 0)
+ Util_FatalError("Attribute could not be found\n");
+ return attrLocation;
+}
+
+void Shader_Destroy(GLuint programID)
+{
+ glUseProgram(0);
+ glDeleteProgram(programID);
+}
+
+void Shader_SetUniformMat4( GLuint programID, const char* name, const float *matrix )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniformMatrix4fv(location, 1, GL_FALSE, matrix);
+}
+
+void Shader_SetUniformFloat( GLuint programID, const char* name, const float val )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniform1f(location, val);
+}
+
+void Shader_SetUniformVec2( GLuint programID, const char* name, const float vec[2] )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniform2fv(location, 1, vec);
+}
+
+void Shader_SetUniformVec3( GLuint programID, const char* name, const float vec[3] )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniform3fv(location, 1, vec);
+}
+
+void Shader_SetUniformVec4( GLuint programID, const char* name, const float vec[4] )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniform4fv(location, 1, vec);
+}
+
+void Shader_SetUniformInt( GLuint programID, const char* name, const int val )
+{
+ GLint location = Shader_GetUniformLocation(programID, name);
+ glUniform1i(location, val);
+}
diff --git a/07-july/src/graphics/shaders.h b/07-july/src/graphics/shaders.h
new file mode 100644
index 0000000..9e0bbab
--- /dev/null
+++ b/07-july/src/graphics/shaders.h
@@ -0,0 +1,46 @@
+#ifndef SHADERS_H
+#define SHADERS_H
+
+#include <GL/glew.h>
+
+#include "../math/matrix4x4.h"
+
+typedef struct
+{
+ GLuint ID;
+
+ GLint position;
+ GLint color;
+ GLint uv;
+ GLint normal;
+
+ GLint totalTransform;
+ GLint modelToWorld;
+ GLint lightPosition;
+ GLint ambientLight;
+ GLint lightColor;
+ GLint lightAttenuation;
+ GLint World_eyePosition;
+ GLint Texture;
+
+ GLint Texture_Background;
+ GLint Texture_R;
+ GLint Texture_G;
+ GLint Texture_B;
+ GLint Texture_BlendMap;
+
+} Shader_Layout;
+
+extern GLuint Shader_CompileShaders(const char* vertexShader, const char* fragmentShader);
+extern GLint Shader_GetUniformLocation( GLuint programID, const char* uniformName );
+extern GLint Shader_GetAttribLocation ( GLuint programID, const char* attributeName );
+extern void Shader_Destroy(GLuint programID);
+
+extern void Shader_SetUniformMat4( GLuint programID, const char* name, const float *matrix );
+extern void Shader_SetUniformFloat( GLuint programID, const char* name, const float val );
+extern void Shader_SetUniformVec2( GLuint programID, const char* name, const float vec[2] );
+extern void Shader_SetUniformVec3( GLuint programID, const char* name, const float vec[3] );
+extern void Shader_SetUniformVec4( GLuint programID, const char* name, const float vec[4] );
+extern void Shader_SetUniformInt( GLuint programID, const char* name, const int val );
+
+#endif // SHADERS_H
diff --git a/07-july/src/graphics/video.c b/07-july/src/graphics/video.c
new file mode 100644
index 0000000..4b9b084
--- /dev/null
+++ b/07-july/src/graphics/video.c
@@ -0,0 +1,14 @@
+#include "video.h"
+
+#include <SDL2/SDL.h>
+#include <GL/glew.h>
+
+void Video_Init()
+{
+
+}
+
+void Video_Shutdown()
+{
+
+}
diff --git a/07-july/src/graphics/video.h b/07-july/src/graphics/video.h
new file mode 100644
index 0000000..db23a45
--- /dev/null
+++ b/07-july/src/graphics/video.h
@@ -0,0 +1,7 @@
+#ifndef VIDEO_H
+#define VIDEO_H
+
+extern void Video_Init(void);
+extern void Video_Shutdown(void);
+
+#endif // VIDEO_H_INCLUDED
diff --git a/07-july/src/graphics/window.c b/07-july/src/graphics/window.c
new file mode 100644
index 0000000..9afb27a
--- /dev/null
+++ b/07-july/src/graphics/window.c
@@ -0,0 +1,44 @@
+#include "window.h"
+#include "../util/util.h"
+#include <stdlib.h>
+
+window_t* Window_Create(const char* title, Uint32 width, Uint32 height)
+{
+ window_t* window = (window_t*) malloc(sizeof(window_t));
+ window->title = title;
+ window->Width = width;
+ window->Height = height;
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ window->window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ width, height, SDL_WINDOW_OPENGL);
+ if(window->window == NULL)
+ Util_FatalError( SDL_GetError() );
+
+ window->context = SDL_GL_CreateContext(window->window);
+
+ if(window->context == NULL)
+ Util_FatalError( SDL_GetError() );
+
+ glViewport(0, 0, width, height);
+ return window;
+}
+
+void Window_Resize(window_t* window, Uint32 width, Uint32 height)
+{
+ window->Width = width;
+ window->Height = height;
+ SDL_SetWindowSize(window->window, width, height);
+ glViewport(0, 0, width, height);
+}
+
+void Window_Update(window_t* window)
+{
+ SDL_GL_SwapWindow(window->window);
+}
+
+void Window_Destroy(window_t* window)
+{
+ SDL_GL_DeleteContext(window->context);
+ SDL_DestroyWindow(window->window);
+ free(window);
+}
diff --git a/07-july/src/graphics/window.h b/07-july/src/graphics/window.h
new file mode 100644
index 0000000..1e71a83
--- /dev/null
+++ b/07-july/src/graphics/window.h
@@ -0,0 +1,20 @@
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <SDL2/SDL.h>
+#include <GL/glew.h>
+
+typedef struct
+{
+ SDL_Window* window;
+ SDL_GLContext context;
+ Uint32 Width, Height;
+ const char* title;
+} window_t;
+
+extern window_t* Window_Create(const char* title, Uint32 width, Uint32 height);
+extern void Window_Resize(window_t* window, Uint32 width, Uint32 height);
+extern void Window_Update(window_t* window);
+extern void Window_Destroy(window_t* window);
+
+#endif // WINDOW_H
diff --git a/07-july/src/gui/gui_renderer.c b/07-july/src/gui/gui_renderer.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/07-july/src/gui/gui_renderer.c
diff --git a/07-july/src/gui/gui_renderer.h b/07-july/src/gui/gui_renderer.h
new file mode 100644
index 0000000..2c1b57f
--- /dev/null
+++ b/07-july/src/gui/gui_renderer.h
@@ -0,0 +1,9 @@
+#ifndef GUI_RENDERER_H
+#define GUI_RENDERER_H
+
+extern void gui_renderer_init();
+extern void gui_renderer_submit(widget *widget);
+extern void gui_renderer_quit();
+
+
+#endif // GUI_RENDERER_H
diff --git a/07-july/src/gui/widget.c b/07-july/src/gui/widget.c
new file mode 100644
index 0000000..9ed00f7
--- /dev/null
+++ b/07-july/src/gui/widget.c
@@ -0,0 +1,17 @@
+#include "widget.h"
+#include <stdlib.h>
+
+widget_t *Widget_CreateImage(texture_t *texture, int x, int y, int w, int h)
+{
+ widget_t *widget = (widget_t *) malloc( sizeof(widget_t) );
+ *widget = (widget_t){ x, y, w, h, 0, texture };
+
+ glGenBuffers(1, &widget->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, widget->vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, NULL, GL_DYNAMIC_DRAW);
+}
+
+void Widget_Destroy(widget_t *widget)
+{
+ free(widget);
+}
diff --git a/07-july/src/gui/widget.h b/07-july/src/gui/widget.h
new file mode 100644
index 0000000..91fc4c4
--- /dev/null
+++ b/07-july/src/gui/widget.h
@@ -0,0 +1,13 @@
+#ifndef WIDGET_H
+#define WIDGET_H
+
+#include "GL/glew.h"
+#include "../texture.h"
+
+typedef struct
+{
+ int x, y, w, h;
+ texture_t *texture;
+} widget_t;
+
+#endif // WIDGET_H
diff --git a/07-july/src/input.c b/07-july/src/input.c
new file mode 100644
index 0000000..8384ceb
--- /dev/null
+++ b/07-july/src/input.c
@@ -0,0 +1,21 @@
+#include "input.h"
+
+static bool key_buffer[MAX_KEY_BUFFER_SIZE] = { false };
+
+void Input_PressKey(unsigned int key)
+{
+ if(key > 256 || key < 0) return;
+ key_buffer[key] = true;
+}
+
+void Input_ReleaseKey(unsigned int key)
+{
+ if(key > 256 || key < 0) return;
+ key_buffer[key] = false;
+}
+
+bool Input_isKeyPressed(unsigned int key)
+{
+ if(key > 256 || key < 0) return false;
+ return key_buffer[key];
+}
diff --git a/07-july/src/input.h b/07-july/src/input.h
new file mode 100644
index 0000000..92876ca
--- /dev/null
+++ b/07-july/src/input.h
@@ -0,0 +1,11 @@
+#ifndef INPUT_H
+#define INPUT_H
+
+#include <stdbool.h>
+#define MAX_KEY_BUFFER_SIZE 256
+
+void Input_PressKey(unsigned int key);
+void Input_ReleaseKey(unsigned int key);
+bool Input_isKeyPressed(unsigned int key);
+
+#endif // INPUT_H
diff --git a/07-july/src/light.c b/07-july/src/light.c
new file mode 100644
index 0000000..decd182
--- /dev/null
+++ b/07-july/src/light.c
@@ -0,0 +1 @@
+#include "light.h"
diff --git a/07-july/src/light.h b/07-july/src/light.h
new file mode 100644
index 0000000..6b6da0a
--- /dev/null
+++ b/07-july/src/light.h
@@ -0,0 +1,13 @@
+#ifndef LIGHT_H
+#define LIGHT_H
+
+#include "vertex.h"
+
+typedef struct
+{
+ vec3_t position;
+ color_t color;
+ vec3_t attenuation;
+} light_t;
+
+#endif // LIGHT_H
diff --git a/07-july/src/main.c b/07-july/src/main.c
new file mode 100644
index 0000000..d119764
--- /dev/null
+++ b/07-july/src/main.c
@@ -0,0 +1,227 @@
+#include "game.h"
+#include "math/vector3f.h"
+#include "math/vector2f.h"
+#include "math/matrix4x4.h"
+#include "input.h"
+#include "util/util.h"
+#include "util/util_time.h"
+#include "light.h"
+#include "renderer/renderer.h"
+
+/*
+ TODO: Shadows
+ Texture Atlases
+
+ improve math package
+ repair gui on renderer.c
+*/
+
+void LoadResources(game_t* game);
+void Draw(game_t* game);
+void ProcessInput(game_t* game);
+void CleanUp(game_t* game);
+
+int main(int args, char* argv[])
+{
+ SDL_Init(SDL_INIT_EVERYTHING);
+
+ game_t game;
+ game.gameState = RUNNING;
+ game.window = Window_Create("Test", WINDOW_WIDTH, WINDOW_HEIGHT);
+
+ if(glewInit() != GLEW_OK)
+ Util_FatalError("Glew could no be started!");
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ SDL_GL_SetSwapInterval(0);
+ //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+
+ game.shaderProgram.ID = Shader_CompileShaders("resources/shaders/shader.vert",
+ "resources/shaders/shader.frag");
+
+ game.terrainProgram.ID = Shader_CompileShaders("resources/shaders/terrainShader.vert",
+ "resources/shaders/terrainShader.frag");
+ glUseProgram(game.shaderProgram.ID);
+
+ Camera_Init(&game.camera);
+
+ LoadResources(&game);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+ Time_Init();
+ Time_SetMaxFramesPerSecond(6000);
+ while(game.gameState != EXIT)
+ {
+ Time_Begin();
+ ProcessInput(&game);
+ Player_Update(&game.player, game.terrain);
+ Draw(&game);
+
+ float FPS = Time_End();
+
+ if( !( Time_GetCountedFrames() % (int)FPS ) ) {
+ fprintf(stderr, "FPS: %.4f\n", FPS);
+ }
+ }
+
+ Window_Destroy(game.window);
+ CleanUp(&game);
+ SDL_Quit();
+ return 0;
+}
+
+void CleanUp(game_t* game)
+{
+ Shape_Free(game->entsShape);
+ Texture_Destroy(game->entsTexture);
+ Terrain_Destroy(game->terrain);
+
+ Shader_Destroy(game->shaderProgram.ID);
+ Shader_Destroy(game->terrainProgram.ID);
+ Render_Quit();
+}
+
+void LoadResources(game_t* game)
+{
+ Render_Init();
+ Uint32 start = SDL_GetTicks();
+
+ game->entsShape = Shape_MakeCube();
+ game->entsTexture = Texture_Create("resources/textures/gato.png");
+
+ Player_Init(&game->player);
+ game->player.entity.texture = game->entsTexture;
+ game->player.entity.shape = game->entsShape;
+
+ {
+ vec3_t position = { 0.0f, 3.0f, 0.0f };
+ float rotation[3] = { 0.0f, 45.0f, 45.0f };
+ game->ents[0].position = position;
+ game->ents[0].rotX = rotation[0];
+ game->ents[0].rotY = rotation[1];
+ game->ents[0].rotZ = rotation[2];
+ game->ents[0].shape = game->entsShape;
+ game->ents[0].texture = game->entsTexture;
+ }
+
+ {
+ vec3_t position = { -400.0f, 0.0f, -400.0f };
+ texture_t *blendmap = Texture_Create("resources/textures/blendmap.png");
+ TerrainTexturePack pack =
+ {
+ {
+ Texture_Create("resources/textures/soil1.png"),
+ Texture_Create("resources/textures/soil2.png"),
+ Texture_Create("resources/textures/soil4.png"),
+ Texture_Create("resources/textures/soil3.png"),
+ }
+ };
+ game->terrain = Terrain_Create(800, 800, "resources/textures/heightmap.png", blendmap, &pack);
+ game->terrain->position = position;
+ }
+
+ /* Shader Layouts */
+
+ game->shaderProgram.Texture = Shader_GetUniformLocation(game->shaderProgram.ID, "Texture");
+ game->shaderProgram.modelToWorld = Shader_GetUniformLocation(game->shaderProgram.ID, "Matrix_modelToWorld");
+ game->shaderProgram.totalTransform = Shader_GetUniformLocation(game->shaderProgram.ID, "Matrix_totalTransform");
+ game->shaderProgram.lightPosition = Shader_GetUniformLocation(game->shaderProgram.ID, "lightPosition");
+ game->shaderProgram.lightColor = Shader_GetUniformLocation(game->shaderProgram.ID, "lightColor");
+ game->shaderProgram.lightAttenuation = Shader_GetUniformLocation(game->shaderProgram.ID, "attenuation");
+
+ game->terrainProgram.modelToWorld = Shader_GetUniformLocation(game->terrainProgram.ID, "Matrix_modelToWorld");
+ game->terrainProgram.totalTransform = Shader_GetUniformLocation(game->terrainProgram.ID, "Matrix_totalTransform");
+ game->terrainProgram.lightPosition = Shader_GetUniformLocation(game->terrainProgram.ID, "lightPosition");
+ game->terrainProgram.lightColor = Shader_GetUniformLocation(game->terrainProgram.ID, "lightColor");
+ game->terrainProgram.lightAttenuation = Shader_GetUniformLocation(game->terrainProgram.ID, "attenuation");
+
+ game->terrainProgram.Texture_Background = Shader_GetUniformLocation(game->terrainProgram.ID, "Texture_Background");
+ game->terrainProgram.Texture_BlendMap = Shader_GetUniformLocation(game->terrainProgram.ID, "Texture_BlendMap");
+ game->terrainProgram.Texture_R = Shader_GetUniformLocation(game->terrainProgram.ID, "Texture_R");
+ game->terrainProgram.Texture_G = Shader_GetUniformLocation(game->terrainProgram.ID, "Texture_G");
+ game->terrainProgram.Texture_B = Shader_GetUniformLocation(game->terrainProgram.ID, "Texture_B");
+
+ fprintf(stderr, "Loading time: %u (ms)\n", SDL_GetTicks() - start);
+}
+
+void Draw(game_t* game)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /*We upload all the light vectors*/
+ static light_t diffuseLight[4] =
+ {
+ { {0.0f, 20.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.01f, 0.002f} },
+ { {10.0f, 20.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.01f, 0.002f} },
+ { {20.0f, 20.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.01f, 0.002f} },
+ { {30.0f, 20.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.01f, 0.002f} },
+ };
+
+ Shader_SetUniformVec3(game->shaderProgram.ID, "World_eyePosition", (float*)&game->camera.position);
+ Render_LoadLights(&game->shaderProgram, diffuseLight, 4);
+
+ mat4_t viewMatrix, projectionMatrix, projectedViewMatrix;
+
+ viewMatrix = Camera_GetModelToViewMatrix(&game->camera);
+ projectionMatrix = mat4_perspective(60.0f, WINDOW_ASPECT_RATIO, 0.1f, 300.0f);
+ projectedViewMatrix = mat4_mul(&projectionMatrix, &viewMatrix);
+
+ Render_DrawEntity(&game->shaderProgram, &projectedViewMatrix, &game->player.entity);
+ Render_DrawEntity(&game->shaderProgram, &projectedViewMatrix, &game->ents[0]);
+
+ glUseProgram(game->terrainProgram.ID);
+
+ Shader_SetUniformVec3(game->terrainProgram.ID, "World_eyePosition", (float*)&game->camera.position);
+ Render_LoadLights(&game->terrainProgram, diffuseLight, 4);
+
+ Render_DrawTerrain(&game->terrainProgram, &projectedViewMatrix, game->terrain);
+
+ glUseProgram(game->shaderProgram.ID);
+
+ Window_Update(game->window);
+}
+
+void ProcessInput(game_t* game)
+{
+ vec2_t mousePosition;
+ SDL_Event e;
+ while(SDL_PollEvent(&e))
+ {
+ switch(e.type)
+ {
+ case SDL_QUIT:
+ game->gameState = EXIT;
+ break;
+
+ case SDL_MOUSEMOTION:
+ mousePosition = vec2_create(e.motion.x, e.motion.y);
+ Camera_MouseUpdate(&game->camera, &mousePosition);
+ break;
+
+ case SDL_KEYDOWN:
+ Input_PressKey(e.key.keysym.scancode);
+ break;
+
+ case SDL_KEYUP:
+ Input_ReleaseKey(e.key.keysym.scancode);
+ break;
+ }
+
+ if(Input_isKeyPressed(SDL_SCANCODE_UP))
+ Camera_Move_Foward(&game->camera);
+
+ if(Input_isKeyPressed(SDL_SCANCODE_DOWN))
+ Camera_Move_Backward(&game->camera);
+
+ if(Input_isKeyPressed(SDL_SCANCODE_LEFT))
+ Camera_Move_Left(&game->camera);
+
+ if(Input_isKeyPressed(SDL_SCANCODE_RIGHT))
+ Camera_Move_Right(&game->camera);
+
+ if(Input_isKeyPressed(SDL_SCANCODE_ESCAPE))
+ game->gameState = EXIT;
+ }
+}
diff --git a/07-july/src/math/math_util.c b/07-july/src/math/math_util.c
new file mode 100644
index 0000000..f58e447
--- /dev/null
+++ b/07-july/src/math/math_util.c
@@ -0,0 +1,10 @@
+#include "math_util.h"
+
+float baryCentric(vec3_t *p1, vec3_t *p2, vec3_t *p3, vec2_t *pos)
+{
+ float det = (p2->z - p3->z) * (p1->x - p3->x) + (p3->x - p2->x) * (p1->z - p3->z);
+ float l1 = ((p2->z - p3->z) * (pos->x - p3->x) + (p3->x - p2->x) * (pos->y - p3->z)) / det;
+ float l2 = ((p3->z - p1->z) * (pos->x - p3->x) + (p1->x - p3->x) * (pos->y - p3->z)) / det;
+ float l3 = 1.0f - l1 - l2;
+ return l1 * p1->y + l2 * p2->y + l3 * p3->y;
+}
diff --git a/07-july/src/math/math_util.h b/07-july/src/math/math_util.h
new file mode 100644
index 0000000..28a5464
--- /dev/null
+++ b/07-july/src/math/math_util.h
@@ -0,0 +1,9 @@
+#ifndef MATH_UTIL_H
+#define MATH_UTIL_H
+
+#include "vector3f.h"
+#include "vector2f.h"
+
+extern float baryCentric(vec3_t *p1, vec3_t *p2, vec3_t *p3, vec2_t *pos);
+
+#endif // MATH_UTIL_H
diff --git a/07-july/src/math/matrix4x4.c b/07-july/src/math/matrix4x4.c
new file mode 100644
index 0000000..c46895a
--- /dev/null
+++ b/07-july/src/math/matrix4x4.c
@@ -0,0 +1,180 @@
+#include "matrix4x4.h"
+#include "../util/util.h"
+#include <SDL2/SDL.h>
+
+void mat4_identity(mat4_t *a)
+{
+ int i;
+ for(i = 0; i < 4*4; i++)
+ {
+ a->data[i] = 0.0f;
+ }
+ a->data[0 + 0 * 4] = 1.0f;
+ a->data[1 + 1 * 4] = 1.0f;
+ a->data[2 + 2 * 4] = 1.0f;
+ a->data[3 + 3 * 4] = 1.0f;
+}
+
+mat4_t mat4_mul(const mat4_t* a, const mat4_t* b)
+{
+ int i, j, k;
+ GLfloat sum = 0.0f;
+ mat4_t c;
+ mat4_identity(&c);
+ for(i = 0; i < 4; i++)
+ for(j = 0; j < 4; j++){
+ for(k = 0; k < 4; k++){
+ sum += a->data[i + k * 4] * b->data[k + j * 4];
+ }
+ c.data[i + j * 4] = sum;
+ sum = 0.0f;
+ }
+
+ return c;
+}
+
+mat4_t mat4_translate(const vec3_t *a)
+{
+ mat4_t b;
+ mat4_identity(&b);
+ b.data[0 + 3 * 4] = a->x;
+ b.data[1 + 3 * 4] = a->y;
+ b.data[2 + 3 * 4] = a->z;
+ return b;
+}
+
+mat4_t mat4_scale(GLfloat x, GLfloat y, GLfloat z)
+{
+ mat4_t b;
+ mat4_identity(&b);
+ b.data[0 + 0 * 4] = x;
+ b.data[1 + 1 * 4] = y;
+ b.data[2 + 2 * 4] = z;
+ return b;
+}
+
+mat4_t mat4_rotate(GLfloat degrees, const vec3_t* a)
+{
+ mat4_t b;
+ mat4_identity(&b);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees)), o = 1-c;
+ b.data[0 + 0 * 4] = a->x * a->x * o + c;
+ b.data[0 + 1 * 4] = a->x * a->y * o - a->z * s;
+ b.data[0 + 2 * 4] = a->x * a->z * o + a->y * s;
+
+ b.data[1 + 0 * 4] = a->x * a->y * o + a->z * s;
+ b.data[1 + 1 * 4] = a->y * a->y * o + c;
+ b.data[1 + 2 * 4] = a->y * a->z * o - a->x * s;
+
+ b.data[2 + 0 * 4] = a->x * a->z * o - a->y * s;
+ b.data[2 + 1 * 4] = a->y * a->z * o + a->x * s;
+ b.data[2 + 2 * 4] = a->z * a->z * o + c;
+ return b;
+}
+
+mat4_t mat4_rotate_x(GLfloat degrees)
+{
+ mat4_t a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[1 + 1 * 4] = c;
+ a.data[2 + 1 * 4] = s;
+ a.data[1 + 2 * 4] = -s;
+ a.data[2 + 2 * 4] = c;
+ return a;
+}
+
+mat4_t mat4_rotate_y(GLfloat degrees)
+{
+ mat4_t a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[0 + 0 * 4] = c;
+ a.data[2 + 0 * 4] = -s;
+ a.data[0 + 2 * 4] = s;
+ a.data[2 + 2 * 4] = c;
+ return a;
+}
+
+mat4_t mat4_rotate_z(GLfloat degrees)
+{
+ mat4_t a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[0 + 0 * 4] = c;
+ a.data[1 + 0 * 4] = s;
+ a.data[0 + 1 * 4] = -s;
+ a.data[1 + 1 * 4] = c;
+ return a;
+}
+
+mat4_t mat4_perspective(GLfloat fov, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ mat4_t a;
+ GLubyte i, j;
+ for(i = 0; i < 4; i++)
+ for(j = 0; j < 4; j++)
+ a.data[i + j * 4] = 0.0f;
+ fov = toRadians(fov); //To radians
+
+ a.data[0 + 0 * 4] = ( (1.0f / SDL_tanf( fov/2.0f )) / aspect);
+ a.data[1 + 1 * 4] = (1.0f / SDL_tanf( fov/2.0f ));
+ a.data[2 + 2 * 4] = -( (zFar + zNear) / (zFar - zNear) );
+ a.data[2 + 3 * 4] = -( ( 2.0f * zFar * zNear) / (zFar - zNear) );
+ a.data[3 + 2 * 4] = -1.0f;
+
+ return a;
+}
+
+mat4_t
+mat4_orthographic(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top)
+{
+ mat4_t a;
+ mat4_identity(&a);
+ a.data[0 + 0 * 4] = 2.0f / (right - left);
+ a.data[1 + 1 * 4] = 2.0f / (top - bottom);
+ a.data[2 + 2 * 4] = -1.0f;
+
+ a.data[0 + 3 * 4] = (left + right) / (left - right);
+ a.data[1 + 3 * 4] = (bottom + top) / (bottom - top);
+
+ return a;
+}
+
+mat4_t mat4_lookAt(vec3_t* eye, vec3_t* center, vec3_t* up)
+{
+ vec3_t temp = vec3_sub(center, eye);
+
+ vec3_t f = vec3_normalize(&temp);
+ vec3_t u = vec3_normalize(up);
+ temp = vec3_cross_mul(&f, &u);
+ vec3_t s = vec3_normalize(&temp);
+ u = vec3_cross_mul(&s, &f);
+
+ mat4_t a;
+ mat4_identity(&a);
+
+ a.data[0 + 0 * 4] = s.x;
+ a.data[0 + 1 * 4] = s.y;
+ a.data[0 + 2 * 4] = s.z;
+ a.data[1 + 0 * 4] = u.x;
+ a.data[1 + 1 * 4] = u.y;
+ a.data[1 + 2 * 4] = u.z;
+ a.data[2 + 0 * 4] =-f.x;
+ a.data[2 + 1 * 4] =-f.y;
+ a.data[2 + 2 * 4] =-f.z;
+ a.data[0 + 3 * 4] =-vec3_dot_mul(&s, eye);
+ a.data[1 + 3 * 4] =-vec3_dot_mul(&u, eye);
+ a.data[2 + 3 * 4] = vec3_dot_mul(&f, eye);
+
+ return a;
+}
+
+vec3_t mat4_mul_vec3(const mat4_t* a, const vec3_t* b)
+{
+ vec3_t c;
+ c.x = a->data[0 + 0 * 4] * b->x + a->data[0 + 1 * 4] * b->y + a->data[0 + 2 * 4] * b->z + a->data[0 + 3 * 4];
+ c.y = a->data[1 + 0 * 4] * b->x + a->data[1 + 1 * 4] * b->y + a->data[1 + 2 * 4] * b->z + a->data[1 + 3 * 4];
+ c.z = a->data[2 + 0 * 4] * b->x + a->data[2 + 1 * 4] * b->y + a->data[2 + 2 * 4] * b->z + a->data[2 + 3 * 4];
+ return c;
+}
diff --git a/07-july/src/math/matrix4x4.h b/07-july/src/math/matrix4x4.h
new file mode 100644
index 0000000..6668fc5
--- /dev/null
+++ b/07-july/src/math/matrix4x4.h
@@ -0,0 +1,35 @@
+#ifndef MATRIX4X4_H
+#define MATRIX4X4_H
+
+#include <GL/glew.h>
+#include "vector3f.h"
+
+/* accesing data: row + column * width */
+typedef struct
+{
+ GLfloat data[16];
+} mat4_t;
+
+extern void mat4_identity(mat4_t* a);
+extern mat4_t mat4_mul(const mat4_t* a, const mat4_t* b);
+
+extern mat4_t mat4_translate(const vec3_t *a);
+extern mat4_t mat4_scale(GLfloat x, GLfloat y, GLfloat z);
+extern mat4_t mat4_rotate_x(GLfloat degrees);
+extern mat4_t mat4_rotate_y(GLfloat degrees);
+extern mat4_t mat4_rotate_z(GLfloat degrees);
+extern mat4_t mat4_rotate(GLfloat degrees, const vec3_t* a);
+
+extern mat4_t
+mat4_perspective(GLfloat fov, GLfloat aspect, GLfloat zNear, GLfloat zFar);
+
+extern mat4_t
+mat4_orthographic(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top);
+
+extern mat4_t
+mat4_lookAt(vec3_t* eye, vec3_t* center, vec3_t* up);
+
+extern vec3_t
+mat4_mul_vec3(const mat4_t* a, const vec3_t* b);
+
+#endif // MATRIX4X4_H
diff --git a/07-july/src/math/vector2f.c b/07-july/src/math/vector2f.c
new file mode 100644
index 0000000..5a3e29d
--- /dev/null
+++ b/07-july/src/math/vector2f.c
@@ -0,0 +1,60 @@
+#include "vector2f.h"
+#include <SDL2/SDL.h>
+
+vec2_t vec2_create(GLfloat x, GLfloat y)
+{
+ vec2_t a = {x, y};
+ return a;
+}
+
+vec2_t vec2_add(const vec2_t* a, const vec2_t* b)
+{
+ vec2_t c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ return c;
+}
+
+vec2_t vec2_sub(const vec2_t* a, const vec2_t* b)
+{
+ vec2_t c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ return c;
+}
+
+vec2_t vec2_scalar_mul(const vec2_t* a, GLfloat scalar)
+{
+ vec2_t c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ return c;
+}
+
+GLfloat vec2_dot_mul(const vec2_t* a, const vec2_t* b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) );
+}
+
+
+vec2_t vec2_cross_mul(const vec2_t* a, const vec2_t* b)
+{
+ vec2_t c;
+ c.x = (a->x * b->y) - (a->y * b->x);
+ c.y = (a->y * b->x) - (a->x * b->y);
+ return c;
+}
+
+GLfloat vec2_length(vec2_t* a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) );
+}
+
+vec2_t vec2_normalize(vec2_t* a)
+{
+ vec2_t b;
+ GLfloat length = vec2_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ return b;
+}
diff --git a/07-july/src/math/vector2f.h b/07-july/src/math/vector2f.h
new file mode 100644
index 0000000..8c20b9a
--- /dev/null
+++ b/07-july/src/math/vector2f.h
@@ -0,0 +1,20 @@
+#ifndef VECTOR2F_H
+#define VECTOR2F_H
+
+#include <GL/glew.h>
+
+typedef struct
+{
+ GLfloat x, y;
+} vec2_t;
+
+extern vec2_t vec2_create(GLfloat x, GLfloat y);
+extern vec2_t vec2_add(const vec2_t* a, const vec2_t* b);
+extern vec2_t vec2_sub(const vec2_t* a, const vec2_t* b);
+extern vec2_t vec2_scalar_mul(const vec2_t* a, GLfloat scalar);
+extern GLfloat vec2_dot_mul(const vec2_t* a, const vec2_t* b);
+extern vec2_t vec2_cross_mul(const vec2_t* a, const vec2_t* b);
+extern GLfloat vec2_length(vec2_t* a);
+extern vec2_t vec2_normalize(vec2_t* a);
+
+#endif // VECTOR2F_H
diff --git a/07-july/src/math/vector3f.c b/07-july/src/math/vector3f.c
new file mode 100644
index 0000000..d68acf6
--- /dev/null
+++ b/07-july/src/math/vector3f.c
@@ -0,0 +1,65 @@
+#include "vector3f.h"
+#include <SDL2/SDL.h>
+
+vec3_t vec3_create(GLfloat x, GLfloat y, GLfloat z)
+{
+ vec3_t a = {x, y, z};
+ return a;
+}
+
+vec3_t vec3_add(const vec3_t* a, const vec3_t* b)
+{
+ vec3_t c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ c.z = a->z + b->z;
+ return c;
+}
+
+vec3_t vec3_sub(const vec3_t* a, const vec3_t* b)
+{
+ vec3_t c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ c.z = a->z - b->z;
+ return c;
+}
+
+vec3_t vec3_scalar_mul(const vec3_t* a, GLfloat scalar)
+{
+ vec3_t c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ c.z = a->z * scalar;
+ return c;
+}
+
+GLfloat vec3_dot_mul(const vec3_t* a, const vec3_t* b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) );
+}
+
+
+vec3_t vec3_cross_mul(const vec3_t* a, const vec3_t* b)
+{
+ vec3_t c;
+ c.x = (a->y * b->z) - (a->z * b->y);
+ c.y = (a->z * b->x) - (a->x * b->z);
+ c.z = (a->x * b->y) - (a->y * b->x);
+ return c;
+}
+
+GLfloat vec3_length(vec3_t* a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f));
+}
+
+vec3_t vec3_normalize(vec3_t* a)
+{
+ vec3_t b;
+ GLfloat length = vec3_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ b.z = a->z / length;
+ return b;
+}
diff --git a/07-july/src/math/vector3f.h b/07-july/src/math/vector3f.h
new file mode 100644
index 0000000..ab255d1
--- /dev/null
+++ b/07-july/src/math/vector3f.h
@@ -0,0 +1,20 @@
+#ifndef VECTOR3F_H
+#define VECTOR3F_H
+
+#include <GL/glew.h>
+
+typedef struct
+{
+ GLfloat x, y, z;
+} vec3_t;
+
+extern vec3_t vec3_create(GLfloat x, GLfloat y, GLfloat z);
+extern vec3_t vec3_add(const vec3_t* a, const vec3_t* b);
+extern vec3_t vec3_sub(const vec3_t* a, const vec3_t* b);
+extern vec3_t vec3_scalar_mul(const vec3_t* a, GLfloat scalar);
+extern GLfloat vec3_dot_mul(const vec3_t* a, const vec3_t* b);
+extern vec3_t vec3_cross_mul(const vec3_t* a, const vec3_t* b);
+extern GLfloat vec3_length(vec3_t* a);
+extern vec3_t vec3_normalize(vec3_t* a);
+
+#endif // VECTOR3F_H
diff --git a/07-july/src/math/vector4f.c b/07-july/src/math/vector4f.c
new file mode 100644
index 0000000..735e679
--- /dev/null
+++ b/07-july/src/math/vector4f.c
@@ -0,0 +1,70 @@
+#include "vector4f.h"
+#include <SDL2/SDL.h>
+
+vec4_t vec4_create(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ vec4_t a = {x, y, z, w};
+ return a;
+}
+
+vec4_t vec4_add(const vec4_t* a, const vec4_t* b)
+{
+ vec4_t c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ c.z = a->z + b->z;
+ c.w = a->w + b->w;
+ return c;
+}
+
+vec4_t vec4_sub(const vec4_t* a, const vec4_t* b)
+{
+ vec4_t c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ c.z = a->z - b->z;
+ c.w = a->w - b->w;
+ return c;
+}
+
+vec4_t vec4_scalar_mul(const vec4_t* a, GLfloat scalar)
+{
+ vec4_t c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ c.z = a->z * scalar;
+ c.w = a->w * scalar;
+ return c;
+}
+
+GLfloat vec4_dot_mul(const vec4_t* a, const vec4_t* b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) + (a->w * b->w) );
+}
+
+
+vec4_t vec4_cross_mul(const vec4_t* a, const vec4_t* b)
+{
+ vec4_t c;
+ c.x = (a->y * b->z) - (a->z * b->y);
+ c.y = (a->z * b->x) - (a->x * b->z);
+ c.z = (a->x * b->y) - (a->y * b->x);
+ c.w = 1.0f;
+ return c;
+}
+
+GLfloat vec4_length(vec4_t* a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f) + SDL_pow(a->w, 2.0f) );
+}
+
+vec4_t vec4_normalize(vec4_t* a)
+{
+ vec4_t b;
+ GLfloat length = vec4_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ b.z = a->z / length;
+ b.w = a->w / length;
+ return b;
+}
diff --git a/07-july/src/math/vector4f.h b/07-july/src/math/vector4f.h
new file mode 100644
index 0000000..4f83695
--- /dev/null
+++ b/07-july/src/math/vector4f.h
@@ -0,0 +1,20 @@
+#ifndef VECTOR4F_H
+#define VECTOR4F_H
+
+#include <GL/glew.h>
+
+typedef struct
+{
+ GLfloat x, y, z, w;
+} vec4_t;
+
+extern vec4_t vec4_create(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern vec4_t vec4_add(const vec4_t* a, const vec4_t* b);
+extern vec4_t vec4_sub(const vec4_t* a, const vec4_t* b);
+extern vec4_t vec4_scalar_mul(const vec4_t* a, GLfloat scalar);
+extern GLfloat vec4_dot_mul(const vec4_t* a, const vec4_t* b);
+extern vec4_t vec4_cross_mul(const vec4_t* a, const vec4_t* b);
+extern GLfloat vec4_length(vec4_t* a);
+extern vec4_t vec4_normalize(vec4_t* a);
+
+#endif // VECTOR4F_H
diff --git a/07-july/src/player.c b/07-july/src/player.c
new file mode 100644
index 0000000..02a417b
--- /dev/null
+++ b/07-july/src/player.c
@@ -0,0 +1,62 @@
+#include "player.h"
+#include "util/util_time.h"
+#include "input.h"
+#include "util/util.h"
+
+#define MAX_MOVEMENT_SPEED 10
+#define MAX_ROTATION_SPEED 100
+#define GRAVITY -15
+#define JUMP_POWER 7
+
+static void jump(player_t* player)
+{
+ player->verticalSpeed = JUMP_POWER;
+}
+
+static void check_input(player_t* player)
+{
+ if(Input_isKeyPressed(SDL_SCANCODE_W)) {
+ player->speed = MAX_MOVEMENT_SPEED;
+ } else if(Input_isKeyPressed(SDL_SCANCODE_S)) {
+ player->speed = -MAX_MOVEMENT_SPEED;
+ } else {
+ player->speed = 0.0f;
+ }
+
+ if(Input_isKeyPressed(SDL_SCANCODE_A)) {
+ player->turnSpeed = MAX_ROTATION_SPEED;
+ } else if(Input_isKeyPressed(SDL_SCANCODE_D)) {
+ player->turnSpeed = -MAX_ROTATION_SPEED;
+ } else {
+ player->turnSpeed = 0.0f;
+ }
+
+ if(Input_isKeyPressed(SDL_SCANCODE_SPACE)) {
+ jump(player);
+ }
+}
+
+void Player_Init(player_t* player)
+{
+ player->entity.position = vec3_create(0.0f, 6.0f, 0.0f);
+ player->entity.rotX = player->entity.rotY = player->entity.rotZ = 0;
+ player->speed = player->turnSpeed = player->verticalSpeed = 0;
+}
+
+void Player_Update(player_t *player, terrain_t *terrain)
+{
+ check_input(player);
+ player->entity.rotY += player->turnSpeed * Time_GetFrameTime();
+ player->entity.position.x += SDL_sinf(toRadians(player->entity.rotY)) * player->speed * Time_GetFrameTime();
+ player->entity.position.z += SDL_cosf(toRadians(player->entity.rotY)) * player->speed * Time_GetFrameTime();
+
+ player->verticalSpeed += GRAVITY * Time_GetFrameTime();
+
+ player->entity.position.y += player->verticalSpeed * Time_GetFrameTime();
+
+ GLfloat terrainHeight = Terrain_GetHeightOfTerrain(terrain, player->entity.position.x, player->entity.position.z);
+ if(player->entity.position.y - 1.0f < terrainHeight) {
+ player->entity.position.y = terrainHeight + 1.0f;
+ player->verticalSpeed = 0.0f;
+ }
+}
diff --git a/07-july/src/player.h b/07-july/src/player.h
new file mode 100644
index 0000000..654dc17
--- /dev/null
+++ b/07-july/src/player.h
@@ -0,0 +1,17 @@
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include "renderer/entity.h"
+#include "math/vector3f.h"
+#include "terrain.h"
+
+typedef struct
+{
+ entity_t entity;
+ float speed, turnSpeed, verticalSpeed;
+} player_t;
+
+extern void Player_Init(player_t* player);
+extern void Player_Update(player_t* player, terrain_t *terrain);
+
+#endif // PLAYER_H
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
diff --git a/07-july/src/terrain.c b/07-july/src/terrain.c
new file mode 100644
index 0000000..3bc66d2
--- /dev/null
+++ b/07-july/src/terrain.c
@@ -0,0 +1,163 @@
+#include "terrain.h"
+#include "math/math_util.h"
+#include "math/vector3f.h"
+#include "util/util.h"
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_image.h>
+#include <math.h>
+
+#define PLANE_SIZE 128
+#define PLANE_MAX_HEIGHT 10
+
+#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a)
+
+static float GetHeight(int x, int y, SDL_Surface* surface)
+{
+ if(x < 0 || x >= surface->w || y < 0 || y >= surface->h)
+ return 0.0f;
+
+ Uint32 pixel = ( (Uint32*)surface->pixels )[y * surface->w + x];
+ Uint8 r, g, b;
+ SDL_GetRGB(pixel, surface->format, &r, &g, &b);
+
+ float height = (float)r / 255.0f;
+
+ return height * 40.0f;
+}
+
+static vec3_t GenerateNomal(int x, int y, SDL_Surface* surface)
+{
+ float hLeft = GetHeight(x-1, y, surface);
+ float hRight = GetHeight(x+1, y, surface);
+ float hUp = GetHeight(x, y+1, surface);
+ float hDown = GetHeight(x, y-1, surface);
+
+ vec3_t normal = { hLeft - hRight, 2.0f, hDown - hUp};
+ return vec3_normalize(&normal);
+}
+
+GLfloat Terrain_GetHeightOfTerrain(terrain_t* terrain, GLfloat x, GLfloat z)
+{
+ GLfloat terrainX = x - terrain->position.x;
+ GLfloat terrainZ = z - terrain->position.z;
+
+ GLfloat gridSquareSize = (float)terrain->l / ( (float)PLANE_SIZE - 1 );
+
+ GLint gridX = (GLint) floor(terrainX / gridSquareSize);
+ GLint gridZ = (GLint) floor(terrainZ / gridSquareSize);
+
+ if(gridX >= PLANE_SIZE - 1 || gridX < 0 || gridZ >= PLANE_SIZE - 1 || gridZ < 0)
+ {
+ printf("called\n");
+ return 0;
+ }
+
+ GLfloat xCoord = fmod(terrainX, gridSquareSize) / gridSquareSize;
+ GLfloat zCoord = fmod(terrainZ, gridSquareSize) / gridSquareSize;
+ GLfloat answer;
+
+ /* Determine in which triangle of the square are we. "Bary Centric Interpolation"*/
+ if(xCoord <= (1 - zCoord)){
+ /* 0, heights[gridX][gridZ], 0) */
+ vec3_t p1 = { 0, terrain->height[ gridX * PLANE_SIZE + gridZ ], 0 };
+ /* 1, heights[gridX + 1][gridZ], 0) */
+ vec3_t p2 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + gridZ ], 0};
+ /* 0, heights[gridX][gridZ + 1], 1) */
+ vec3_t p3 = { 0, terrain->height[ gridX * PLANE_SIZE + (gridZ + 1) ], 1};
+
+ vec2_t pos = {xCoord, zCoord};
+
+ answer = baryCentric(&p1, &p2, &p3, &pos);
+ } else {
+ /* (1, heights[gridX + 1][gridZ], 0) */
+ vec3_t p1 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + gridZ ], 0 };
+ /* (1, heights[gridX + 1][gridZ + 1], 1) */
+ vec3_t p2 = { 1, terrain->height[ (gridX + 1) * PLANE_SIZE + (gridZ + 1) ], 1};
+ /* (0, heights[gridX][gridZ + 1], 1) */
+ vec3_t p3 = { 0, terrain->height[ gridX * PLANE_SIZE + (gridZ + 1) ], 1};
+ vec2_t pos = {xCoord, zCoord};
+
+ answer = baryCentric(&p1, &p2, &p3, &pos);
+ }
+
+ return answer;
+}
+
+terrain_t *Terrain_Create( int w, int l, const char* heightmap_path, texture_t *blendmap, TerrainTexturePack *textures )
+{
+ terrain_t *terrain = (terrain_t*) malloc( sizeof(terrain_t) );
+ terrain->height = (GLfloat*) malloc( sizeof(GLfloat) * PLANE_SIZE * PLANE_SIZE);
+
+ terrain->blendmap = blendmap;
+ terrain->w = w; terrain->l = l;
+ terrain->textures = *textures;
+
+ SDL_Surface* surface = IMG_Load(heightmap_path);
+ if(surface == NULL)
+ Util_FatalError("Heightmap file could not be loaded\n");
+
+ vertex_t data[PLANE_SIZE * PLANE_SIZE];
+ int x, y;
+ for(x = 0; x < PLANE_SIZE; x++)
+ {
+ for(y = 0; y < PLANE_SIZE; y++)
+ {
+ vertex_t* v = &data[y + x * PLANE_SIZE];
+ v->position = vec3_create( (float)x / (float)PLANE_SIZE, 0.0f, (float)y / (float)PLANE_SIZE);
+ /* Heightmap cordinates */
+ int image_x = v->position.x * surface->w, image_y = v->position.z * surface->h;
+
+ v->texCoord = vec2_create( v->position.x, v->position.z);
+ GLfloat height = GetHeight(image_x, image_y, surface);
+ terrain->height[y + x * PLANE_SIZE] = height;
+ v->position.y = height;
+ v->position.x *= w;
+ v->position.z *= l;
+
+ v->normal = GenerateNomal(image_x, image_y, surface);
+ color_t temp = {+1.0f, +0.0f, +0.0f, +1.0f};
+ v->color = temp;
+ }
+ }
+
+ int runner = 0;
+ GLushort indices[ (PLANE_SIZE-1) * (PLANE_SIZE-1) * 6 ];
+ for(x = 0; x < PLANE_SIZE-1; x++)
+ {
+ for(y = 0; y < PLANE_SIZE-1; y++)
+ {
+ indices[runner++] = PLANE_SIZE * x + y;
+ indices[runner++] = PLANE_SIZE * x + y + 1;
+ indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE;
+
+ indices[runner++] = PLANE_SIZE * x + y + 1;
+ indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE + 1;
+ indices[runner++] = PLANE_SIZE * x + y + PLANE_SIZE;
+ }
+ }
+
+ GLsizeiptr vertexBufferSize = NUM_ARRAY_ELEMENTS(data) * sizeof(vertex_t);
+ GLsizeiptr indexBufferSize = NUM_ARRAY_ELEMENTS(indices) * sizeof(GLushort);
+
+ SDL_FreeSurface(surface);
+
+ terrain->shape = Shape_CreateFromRawData(data, vertexBufferSize, indices, indexBufferSize);
+ return terrain;
+}
+
+void Terrain_Destroy( terrain_t* terrain )
+{
+ if(terrain->height)
+ free(terrain->height);
+
+ Shape_Free(terrain->shape);
+
+ int i;
+ for(i = 0; i < 4; i++)
+ Texture_Destroy(terrain->textures.texture[i]);
+
+ Texture_Destroy(terrain->blendmap);
+ free(terrain);
+}
+
diff --git a/07-july/src/terrain.h b/07-july/src/terrain.h
new file mode 100644
index 0000000..74e9f33
--- /dev/null
+++ b/07-july/src/terrain.h
@@ -0,0 +1,27 @@
+#ifndef TERRAIN_H
+#define TERRAIN_H
+
+#include "renderer/shape.h"
+#include "texture.h"
+
+typedef struct
+{
+ texture_t *texture[4];
+} TerrainTexturePack;
+
+typedef struct
+{
+ shape_t *shape;
+ texture_t *blendmap;
+ TerrainTexturePack textures;
+
+ GLfloat *height;
+ int w, l;
+ vec3_t position;
+} terrain_t;
+
+extern terrain_t *Terrain_Create( int w, int l, const char* heightmap_path, texture_t *blendmap, TerrainTexturePack *textures);
+extern GLfloat Terrain_GetHeightOfTerrain(terrain_t* terrain, GLfloat x, GLfloat z);
+extern void Terrain_Destroy( terrain_t *terrain );
+
+#endif // TERRAIN_H
diff --git a/07-july/src/texture.c b/07-july/src/texture.c
new file mode 100644
index 0000000..26fddde
--- /dev/null
+++ b/07-july/src/texture.c
@@ -0,0 +1,47 @@
+#include "texture.h"
+#include "util/util.h"
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_image.h>
+
+texture_t* Texture_Create( const char* path )
+{
+ texture_t* texture = (texture_t*) malloc( sizeof(texture_t) );
+ SDL_Surface* data = IMG_Load(path);
+ if(data == NULL)
+ Util_FatalError("Texture could not be found!\n");
+
+ glGenTextures(1, &texture->ID);
+ glBindTexture(GL_TEXTURE_2D, texture->ID);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data->w, data->h, GL_FALSE, GL_RGBA, GL_UNSIGNED_BYTE, data->pixels);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+ SDL_FreeSurface(data);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ texture->width = data->w;
+ texture->height = data->h;
+
+ return texture;
+}
+
+void Texture_Bind(texture_t* texture)
+{
+ glBindTexture(GL_TEXTURE_2D, texture->ID);
+}
+
+void Texture_Unbind()
+{
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void Texture_Destroy(texture_t* texture)
+{
+ glDeleteTextures(1, &texture->ID);
+ free(texture);
+}
diff --git a/07-july/src/texture.h b/07-july/src/texture.h
new file mode 100644
index 0000000..98048b5
--- /dev/null
+++ b/07-july/src/texture.h
@@ -0,0 +1,18 @@
+#ifndef TEXTURE_H
+#define TEXTURE_H
+
+#include <GL/glew.h>
+
+typedef struct
+{
+ GLuint ID;
+ GLuint width, height;
+} texture_t;
+
+extern texture_t* Texture_Create( const char* path );
+extern void Texture_Destroy( texture_t* texture );
+
+extern void Texture_Bind(texture_t* texture);
+extern void Texture_Unbind();
+
+#endif // TEXTURE_H
diff --git a/07-july/src/util/util.c b/07-july/src/util/util.c
new file mode 100644
index 0000000..fcdd665
--- /dev/null
+++ b/07-july/src/util/util.c
@@ -0,0 +1,49 @@
+#include "util.h"
+
+#include <SDL2/SDL.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+void Util_FatalError( const char* error )
+{
+ fprintf(stderr, "Fatal Error:\n%s", error);
+ SDL_Quit();
+ exit(1);
+}
+
+char* Util_LoadFile( const char* path )
+{
+ FILE* file = fopen( path, "r" );
+
+ if(file == NULL)
+ {
+ const char* temp = " could not be found\n";
+ size_t length = strlen(temp);
+ length += strlen(path);
+ char buffer[length];
+ strcpy(buffer, path);
+ strcat(buffer, temp);
+ Util_FatalError(buffer);
+ }
+
+ fseek( file, 0, SEEK_END );
+ size_t sizeOfFile = ftell( file );
+ fseek( file, 0, SEEK_SET );
+ char* file_data = (char*) malloc( sizeof(char)*sizeOfFile + 1 );
+ fread( file_data, sizeof(char), sizeOfFile, file );
+ file_data[sizeOfFile] = '\0';
+ fclose(file);
+ return file_data;
+}
+
+float Util_RandomF(float min, float max)
+{
+ return ( min + (float)rand() ) / ( (float)RAND_MAX / (max-min) );
+}
+
+int Util_RandomI(int min, int max)
+{
+ return ( rand()%(max-min) ) + min;
+}
diff --git a/07-july/src/util/util.h b/07-july/src/util/util.h
new file mode 100644
index 0000000..5f82f30
--- /dev/null
+++ b/07-july/src/util/util.h
@@ -0,0 +1,19 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#define toRadians(degrees) (degrees * 3.1415926 / 180.0f)
+#define toDegrees(radians) (radians * 180.0f / 3.1415926)
+
+#ifdef DEBUG
+#include <stdio.h>
+#define myAssert(expr) expr ? 1==1 : fprintf(stderr, "The expresion was not true\n")
+#else
+#define myAssert(expr)
+#endif // DEBUG
+
+extern void Util_FatalError( const char* error );
+extern char* Util_LoadFile( const char* path );
+extern float Util_RandomF(float min, float max);
+extern int Util_RandomI(int min, int max);
+
+#endif // UTIL_H
diff --git a/07-july/src/util/util_time.c b/07-july/src/util/util_time.c
new file mode 100644
index 0000000..b601379
--- /dev/null
+++ b/07-july/src/util/util_time.c
@@ -0,0 +1,52 @@
+#include "util_time.h"
+
+static struct
+{
+ float max_ticks_per_frame; //< cuantos ticks (tiempo demora) un frame
+ Uint32 counted_frames; //< cuantos frames han pasado
+ Uint32 start_ticks; //< ticks al iniciar la iteracion del loop
+ Uint32 beg_ticks; //< ticks desde el inicio del juego
+ Uint32 time_per_frame;
+} TIME = {
+ 1000.0f / 60.0f,
+ 0, 0, 0, 0
+};
+
+void Time_Init()
+{
+ TIME.beg_ticks = SDL_GetTicks();
+}
+
+void Time_Begin()
+{
+ TIME.start_ticks = SDL_GetTicks();
+}
+
+float Time_End()
+{
+ TIME.counted_frames += 1;
+ float FPS = TIME.counted_frames / ( (float)(SDL_GetTicks() - TIME.beg_ticks) / 1000.f );
+
+ float frameTicks = (float)(SDL_GetTicks() - TIME.start_ticks);
+ TIME.time_per_frame = frameTicks;
+ if(frameTicks < TIME.max_ticks_per_frame){
+ SDL_Delay( (Uint32)(TIME.max_ticks_per_frame - frameTicks) );
+ }
+
+ return FPS;
+}
+
+float Time_GetFrameTime()
+{
+ return (float)TIME.time_per_frame / 1000.0f;
+}
+
+void Time_SetMaxFramesPerSecond(Uint32 frames)
+{
+ TIME.max_ticks_per_frame = 1000.0f / (float)frames;
+}
+
+Uint32 Time_GetCountedFrames()
+{
+ return TIME.counted_frames;
+}
diff --git a/07-july/src/util/util_time.h b/07-july/src/util/util_time.h
new file mode 100644
index 0000000..3c3e470
--- /dev/null
+++ b/07-july/src/util/util_time.h
@@ -0,0 +1,13 @@
+#ifndef UTIL_TIME_H
+#define UTIL_TIME_H
+
+#include <SDL2/SDL.h>
+
+extern void Time_Init( void );
+extern void Time_Begin( void );
+extern float Time_End( void );
+extern void Time_SetMaxFramesPerSecond(Uint32 frames);
+extern float Time_GetFrameTime( void );
+extern Uint32 Time_GetCountedFrames( void );
+
+#endif // UTIL_TIME_H
diff --git a/07-july/src/vertex.h b/07-july/src/vertex.h
new file mode 100644
index 0000000..90152c8
--- /dev/null
+++ b/07-july/src/vertex.h
@@ -0,0 +1,21 @@
+#ifndef VERTEX_H
+#define VERTEX_H
+
+#include <GL/glew.h>
+#include "math/vector2f.h"
+#include "math/vector3f.h"
+
+typedef struct
+{
+ GLfloat r, g, b, a;
+} color_t;
+
+typedef struct
+{
+ vec3_t position;
+ color_t color;
+ vec2_t texCoord;
+ vec3_t normal;
+} vertex_t;
+
+#endif // VERTEX_H