From 6b8af9cf83851c075c6c9514b1deaa931c2b19a4 Mon Sep 17 00:00:00 2001 From: Thomas Guillermo Albers Raviola Date: Fri, 16 Jan 2026 23:02:32 +0100 Subject: Initial commit --- 07-july/src/camera.c | 85 +++++++++++ 07-july/src/camera.h | 32 +++++ 07-july/src/game.h | 42 ++++++ 07-july/src/graphics/shaders.c | 134 ++++++++++++++++++ 07-july/src/graphics/shaders.h | 46 ++++++ 07-july/src/graphics/video.c | 14 ++ 07-july/src/graphics/video.h | 7 + 07-july/src/graphics/window.c | 44 ++++++ 07-july/src/graphics/window.h | 20 +++ 07-july/src/gui/gui_renderer.c | 0 07-july/src/gui/gui_renderer.h | 9 ++ 07-july/src/gui/widget.c | 17 +++ 07-july/src/gui/widget.h | 13 ++ 07-july/src/input.c | 21 +++ 07-july/src/input.h | 11 ++ 07-july/src/light.c | 1 + 07-july/src/light.h | 13 ++ 07-july/src/main.c | 227 ++++++++++++++++++++++++++++++ 07-july/src/math/math_util.c | 10 ++ 07-july/src/math/math_util.h | 9 ++ 07-july/src/math/matrix4x4.c | 180 ++++++++++++++++++++++++ 07-july/src/math/matrix4x4.h | 35 +++++ 07-july/src/math/vector2f.c | 60 ++++++++ 07-july/src/math/vector2f.h | 20 +++ 07-july/src/math/vector3f.c | 65 +++++++++ 07-july/src/math/vector3f.h | 20 +++ 07-july/src/math/vector4f.c | 70 ++++++++++ 07-july/src/math/vector4f.h | 20 +++ 07-july/src/player.c | 62 +++++++++ 07-july/src/player.h | 17 +++ 07-july/src/renderer/entity.c | 18 +++ 07-july/src/renderer/entity.h | 20 +++ 07-july/src/renderer/renderer.c | 98 +++++++++++++ 07-july/src/renderer/renderer.h | 15 ++ 07-july/src/renderer/shape.c | 302 ++++++++++++++++++++++++++++++++++++++++ 07-july/src/renderer/shape.h | 25 ++++ 07-july/src/terrain.c | 163 ++++++++++++++++++++++ 07-july/src/terrain.h | 27 ++++ 07-july/src/texture.c | 47 +++++++ 07-july/src/texture.h | 18 +++ 07-july/src/util/util.c | 49 +++++++ 07-july/src/util/util.h | 19 +++ 07-july/src/util/util_time.c | 52 +++++++ 07-july/src/util/util_time.h | 13 ++ 07-july/src/vertex.h | 21 +++ 45 files changed, 2191 insertions(+) create mode 100644 07-july/src/camera.c create mode 100644 07-july/src/camera.h create mode 100644 07-july/src/game.h create mode 100644 07-july/src/graphics/shaders.c create mode 100644 07-july/src/graphics/shaders.h create mode 100644 07-july/src/graphics/video.c create mode 100644 07-july/src/graphics/video.h create mode 100644 07-july/src/graphics/window.c create mode 100644 07-july/src/graphics/window.h create mode 100644 07-july/src/gui/gui_renderer.c create mode 100644 07-july/src/gui/gui_renderer.h create mode 100644 07-july/src/gui/widget.c create mode 100644 07-july/src/gui/widget.h create mode 100644 07-july/src/input.c create mode 100644 07-july/src/input.h create mode 100644 07-july/src/light.c create mode 100644 07-july/src/light.h create mode 100644 07-july/src/main.c create mode 100644 07-july/src/math/math_util.c create mode 100644 07-july/src/math/math_util.h create mode 100644 07-july/src/math/matrix4x4.c create mode 100644 07-july/src/math/matrix4x4.h create mode 100644 07-july/src/math/vector2f.c create mode 100644 07-july/src/math/vector2f.h create mode 100644 07-july/src/math/vector3f.c create mode 100644 07-july/src/math/vector3f.h create mode 100644 07-july/src/math/vector4f.c create mode 100644 07-july/src/math/vector4f.h create mode 100644 07-july/src/player.c create mode 100644 07-july/src/player.h create mode 100644 07-july/src/renderer/entity.c create mode 100644 07-july/src/renderer/entity.h create mode 100644 07-july/src/renderer/renderer.c create mode 100644 07-july/src/renderer/renderer.h create mode 100644 07-july/src/renderer/shape.c create mode 100644 07-july/src/renderer/shape.h create mode 100644 07-july/src/terrain.c create mode 100644 07-july/src/terrain.h create mode 100644 07-july/src/texture.c create mode 100644 07-july/src/texture.h create mode 100644 07-july/src/util/util.c create mode 100644 07-july/src/util/util.h create mode 100644 07-july/src/util/util_time.c create mode 100644 07-july/src/util/util_time.h create mode 100644 07-july/src/vertex.h (limited to '07-july/src') 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 + +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 + +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 + +#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 +#include + +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 + +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 +#include + +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 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 + +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 +#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 + +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 +#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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 +#include +#include +#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 +#include +#include + +#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 +#include + +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 + +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 + +#include +#include +#include + +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 +#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 + +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 +#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 -- cgit v1.2.3