diff options
Diffstat (limited to '08-august/src')
44 files changed, 2518 insertions, 0 deletions
diff --git a/08-august/src/camera.c b/08-august/src/camera.c new file mode 100644 index 0000000..545ac85 --- /dev/null +++ b/08-august/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_t){ 4.0f, 40.0f, 4.0f }; + camera->viewDirection = (vec3_t){ -1.0f, -1.0f, 0.0f }; + camera->needsUpdate = true; + camera->up = (vec3_t){ 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/08-august/src/camera.h b/08-august/src/camera.h new file mode 100644 index 0000000..384bee8 --- /dev/null +++ b/08-august/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/08-august/src/game.h b/08-august/src/game.h new file mode 100644 index 0000000..611bd07 --- /dev/null +++ b/08-august/src/game.h @@ -0,0 +1,46 @@ +#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" +#include "renderer/skybox.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, skyboxProgram; + + entity_t ents[NUM_ENTITIES]; + shape_t *entsShape; + GLuint entsTexture; + GLuint normalMap; + GLuint defaultNormalMap; + terrain_t *terrain; + skybox_t sky; + + player_t player; + + camera_t camera; + window_t *window; +} game_t; + +#endif // GAME_H diff --git a/08-august/src/graphics/shaders.c b/08-august/src/graphics/shaders.c new file mode 100644 index 0000000..c0796e1 --- /dev/null +++ b/08-august/src/graphics/shaders.c @@ -0,0 +1,135 @@ +#include "shaders.h" +#include "../util/util.h" + +#include <stdlib.h> +#include <stdbool.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("Some shader failed to compile:\n%s", 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("Shader program failed to link!:\n%s", 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 \"%s\" could not be found!", uniformName); + else + return u; + + return 0; +} + +GLint Shader_GetAttribLocation ( GLuint programID, const char* attributeName ) +{ + GLint attrLocation = glGetAttribLocation(programID, attributeName); + if(attrLocation < 0) + Util_FatalError("Attribute \"%s\" could not be found!\n", attributeName); + 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/08-august/src/graphics/shaders.h b/08-august/src/graphics/shaders.h new file mode 100644 index 0000000..db090fd --- /dev/null +++ b/08-august/src/graphics/shaders.h @@ -0,0 +1,51 @@ +#ifndef SHADERS_H +#define SHADERS_H + +#include <GL/glew.h> + +#include "../math/matrix4x4.h" + +typedef struct +{ + /* Program ID */ + GLuint ID; + + /* Program Attributes */ + GLint position; + GLint color; + GLint uv; + GLint normal; + + /* Program Uniforms */ + GLint totalTransform; + GLint modelToWorld; + GLint lightPosition; + GLint ambientLight; + GLint lightColor; + GLint lightAttenuation; + GLint World_eyePosition; + GLint Texture; + GLint Normal_Map; + + /* Program Multi Purpose Uniforms */ + GLint extra0; + GLint extra1; + GLint extra2; + GLint extra3; + GLint extra4; + GLint extra5; +} 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/08-august/src/graphics/window.c b/08-august/src/graphics/window.c new file mode 100644 index 0000000..1a942ca --- /dev/null +++ b/08-august/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( "The window could not be created:\n%s", SDL_GetError() ); + + window->context = SDL_GL_CreateContext(window->window); + + if(window->context == NULL) + Util_FatalError( "Context could not be created:\n%s", 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/08-august/src/graphics/window.h b/08-august/src/graphics/window.h new file mode 100644 index 0000000..1e71a83 --- /dev/null +++ b/08-august/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/08-august/src/gui/gui_renderer.c b/08-august/src/gui/gui_renderer.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/08-august/src/gui/gui_renderer.c diff --git a/08-august/src/gui/gui_renderer.h b/08-august/src/gui/gui_renderer.h new file mode 100644 index 0000000..2c1b57f --- /dev/null +++ b/08-august/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/08-august/src/gui/widget.c b/08-august/src/gui/widget.c new file mode 100644 index 0000000..9ed00f7 --- /dev/null +++ b/08-august/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/08-august/src/gui/widget.h b/08-august/src/gui/widget.h new file mode 100644 index 0000000..91fc4c4 --- /dev/null +++ b/08-august/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/08-august/src/input.c b/08-august/src/input.c new file mode 100644 index 0000000..8384ceb --- /dev/null +++ b/08-august/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/08-august/src/input.h b/08-august/src/input.h new file mode 100644 index 0000000..92876ca --- /dev/null +++ b/08-august/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/08-august/src/light.c b/08-august/src/light.c new file mode 100644 index 0000000..decd182 --- /dev/null +++ b/08-august/src/light.c @@ -0,0 +1 @@ +#include "light.h" diff --git a/08-august/src/light.h b/08-august/src/light.h new file mode 100644 index 0000000..afc8eda --- /dev/null +++ b/08-august/src/light.h @@ -0,0 +1,13 @@ +#ifndef LIGHT_H +#define LIGHT_H + +#include "vertex.h" + +typedef struct +{ + vec3_t position; + vec4_t color; + vec3_t attenuation; +} light_t; + +#endif // LIGHT_H diff --git a/08-august/src/main.c b/08-august/src/main.c new file mode 100644 index 0000000..41fc253 --- /dev/null +++ b/08-august/src/main.c @@ -0,0 +1,290 @@ +#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" +#include <SDL2/SDL.h> + +/** + TODO: Shadows + Texture Atlases + Memory management + + +improve skybox + | + +->fog + +->day/night + + +mouse picking (is it working perfectly?) + + +add cell shading? + + improve math package + repair gui on renderer.c + improve shape loading (tangent generation) (normal generation) + improve normal mapping +**/ + +void LoadResources(game_t *game); +void Draw(game_t *game); +void ProcessInput(game_t *game); +void CleanUp(game_t *game); + +int main(int argc, char *argv[]) +{ + SDL_Init(SDL_INIT_EVERYTHING); + + game_t game; + game.gameState = RUNNING; + game.window = Window_Create("Test", WINDOW_WIDTH, WINDOW_HEIGHT); + + GLenum err = glewInit(); + if(err != GLEW_OK) { + fputs(glewGetErrorString(err), stderr); + Util_FatalError("Glew could no be started!"); + } + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + SDL_GL_SetSwapInterval(1); + // 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"); + + game.skyboxProgram.ID = Shader_CompileShaders("resources/shaders/skyboxShader.vert", + "resources/shaders/skyboxShader.frag"); + glUseProgram(game.shaderProgram.ID); + + Camera_Init(&game.camera); + game.camera.projectionMatrix = mat4_perspective(60.0f, WINDOW_ASPECT_RATIO, 0.1f, 900.0f); + + LoadResources(&game); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + Time_Init(); + Time_SetMaxFramesPerSecond(60); + 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); + Shape_Free(game->sky.cube); + + Texture_Destroy(game->entsTexture); + Texture_Destroy(game->sky.texture); + + Texture_Destroy(game->normalMap); + Texture_Destroy(game->defaultNormalMap); + + Terrain_Destroy(game->terrain); + + Shader_Destroy(game->shaderProgram.ID); + Shader_Destroy(game->terrainProgram.ID); + Shader_Destroy(game->skyboxProgram.ID); + + Render_Quit(); +} + +void LoadResources(game_t *game) +{ + Render_Init(); + Uint32 start = SDL_GetTicks(); + + game->entsShape = Shape_LoadOBJ("resources/barrel.obj"); + game->entsTexture = Texture_Create2D("resources/textures/barrel.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, 0.0f, 0.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 }; + GLuint blendmap = Texture_Create2D("resources/textures/blendmap.png"); + TerrainTexturePack pack = + { + { + Texture_Create2D("resources/textures/soil1.png"), + Texture_Create2D("resources/textures/soil2.png"), + Texture_Create2D("resources/textures/soil4.png"), + Texture_Create2D("resources/textures/soil3.png"), + } + }; + game->terrain = Terrain_Create(800, 800, "resources/textures/heightmap.png", blendmap, &pack); + game->terrain->position = position; + } + + { + game->sky.rotation = 0.0f; + game->sky.cube = Shape_MakeSkyBox(500.0f); + const char *paths[6] = + { + "resources/textures/right.png", + "resources/textures/left.png", + "resources/textures/top.png", + "resources/textures/bottom.png", + "resources/textures/back.png", + "resources/textures/front.png" + }; + game->sky.texture = Texture_CreateCubeMap(paths); + } + + /* Shader Layouts */ + + Shader_Layout *layout = &game->shaderProgram; + layout->Texture = Shader_GetUniformLocation(layout->ID, "Texture"); + layout->modelToWorld = Shader_GetUniformLocation(layout->ID, "M_model"); + layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); + layout->lightPosition = Shader_GetUniformLocation(layout->ID, "lightPosition"); + layout->lightColor = Shader_GetUniformLocation(layout->ID, "lightColor"); + layout->lightAttenuation = Shader_GetUniformLocation(layout->ID, "attenuation"); + layout->Normal_Map = Shader_GetUniformLocation(layout->ID, "normalMap"); + + layout = &game->terrainProgram; + layout->modelToWorld = Shader_GetUniformLocation(layout->ID, "M_model"); + layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); + layout->lightPosition = Shader_GetUniformLocation(layout->ID, "lightPosition"); + layout->lightColor = Shader_GetUniformLocation(layout->ID, "lightColor"); + layout->lightAttenuation = Shader_GetUniformLocation(layout->ID, "attenuation"); + + layout->extra0 = Shader_GetUniformLocation(layout->ID, "Texture_Background"); + layout->extra1 = Shader_GetUniformLocation(layout->ID, "Texture_R"); + layout->extra2 = Shader_GetUniformLocation(layout->ID, "Texture_G"); + layout->extra3 = Shader_GetUniformLocation(layout->ID, "Texture_B"); + layout->extra4 = Shader_GetUniformLocation(layout->ID, "Texture_BlendMap"); + + layout = &game->skyboxProgram; + layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); + layout->Texture = Shader_GetUniformLocation(layout->ID, "cubeMap"); + + game->normalMap = Texture_Create2D("resources/textures/normal_map.png"); + game->defaultNormalMap = Texture_Create2D("resources/textures/default_normal_map.png"); + + 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 const light_t diffuseLight[1] = + { + /* Sun Light */ + { {5.0f, 40.0f, 2.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f} }, + /* Other lights + { {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, 1); + + glActiveTexture(GL_TEXTURE13); + glBindTexture(GL_TEXTURE_2D, game->normalMap); + + glUniform1i(game->shaderProgram.Normal_Map, 13); + + mat4_t viewMatrix, projectedViewMatrix; + + viewMatrix = Camera_GetModelToViewMatrix(&game->camera); + projectedViewMatrix = mat4_mul(&game->camera.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, 1); + + Render_DrawTerrain(&game->terrainProgram, &projectedViewMatrix, game->terrain); + + glUseProgram(game->skyboxProgram.ID); + Render_DrawSky(&game->skyboxProgram, &viewMatrix, &game->camera.projectionMatrix, &game->sky); + + glUseProgram(game->shaderProgram.ID); + + Window_Update(game->window); +} + +void ProcessInput(game_t *game) +{ + static vec2_t mousePosition; + SDL_Event e; + while(SDL_PollEvent(&e)) + { + switch(e.type) + { + case SDL_QUIT: + game->gameState = EXIT; + break; + + case SDL_MOUSEMOTION: + mousePosition.x = (GLfloat) e.motion.x; + mousePosition.y = (GLfloat) 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/08-august/src/math/math_util.c b/08-august/src/math/math_util.c new file mode 100644 index 0000000..f58e447 --- /dev/null +++ b/08-august/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/08-august/src/math/math_util.h b/08-august/src/math/math_util.h new file mode 100644 index 0000000..28a5464 --- /dev/null +++ b/08-august/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/08-august/src/math/matrix4x4.c b/08-august/src/math/matrix4x4.c new file mode 100644 index 0000000..1888727 --- /dev/null +++ b/08-august/src/math/matrix4x4.c @@ -0,0 +1,325 @@ +#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; +} + +/** TODO: Preprocess these operation (1 + 1 * 4) -> 5 **/ +mat4_t mat4_inverse(const mat4_t *a) +{ + mat4_t inv; + int i; + + /** Remember that inverted matrix is (1/det) * cofactor(transposed) **/ + inv.data[0 + 0 * 4] = (a->data[1 + 1 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 1 * 4] * a->data[3 + 2 * 4] * a->data[1 + 3 * 4] + + a->data[3 + 1 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 1 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[1 + 1 * 4] - + a->data[3 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 1 * 4]); + + inv.data[0 + 1 * 4] = -(a->data[0 + 1 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 1 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 1 * 4] * a->data[0 + 2 * 4] * a->data[2 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 1 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 1 * 4] - + a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[2 + 1 * 4]); + + inv.data[0 + 2 * 4] = (a->data[0 + 1 * 4] * a->data[1 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[1 + 1 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 1 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[3 + 1 * 4] - + a->data[1 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 1 * 4] - + a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 1 * 4]); + + inv.data[0 + 3 * 4] = -(a->data[0 + 1 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] + + a->data[1 + 1 * 4] * a->data[2 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[2 + 1 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 1 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[0 + 1 * 4] - + a->data[2 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 1 * 4]); + + inv.data[1 + 0 * 4] = -(a->data[1 + 0 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 2 * 4] * a->data[1 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[1 + 0 * 4] - + a->data[3 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 0 * 4]); + + inv.data[1 + 1 * 4] = (a->data[0 + 0 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 2 * 4] * a->data[2 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[2 + 0 * 4]); + + inv.data[1 + 2 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 2 * 4] * a->data[3 + 3 * 4] + + a->data[1 + 0 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[3 + 0 * 4] - + a->data[1 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 3 + 4] * a->data[0 + 2 * 4] * a->data[1 + 0 * 4]); + + inv.data[1 + 3 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] + + a->data[1 + 0 * 4] * a->data[2 + 2 * 4] * a->data[0 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 0 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[0 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 0 * 4]); + + inv.data[2 + 0 * 4] = (a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[1 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 3 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 1 * 4] * a->data[1 + 0 * 4] - + a->data[3 + 3 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4]); + + inv.data[2 + 1 * 4] = -(a->data[0 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[2 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 3 * 4] * a->data[0 + 1 * 4] * a->data[2 + 0 * 4]); + + inv.data[2 + 2 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[3 + 3 * 4] + + a->data[1 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 3 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[1 + 3 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 3 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]); + + inv.data[2 + 3 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 3 * 4] + + a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[0 + 3 * 4] + + a->data[2 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 3 * 4] - + a->data[0 + 3 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4] - + a->data[1 + 3 * 4] * a->data[2 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[2 + 3 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]); + + inv.data[3 + 0 * 4] = -(a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 2 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[1 + 2 * 4] + + a->data[3 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 2 * 4] - + a->data[1 + 2 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 2 * 4] * a->data[3 + 1 * 4] * a->data[1 + 0 * 4] - + a->data[3 + 2 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4]); + + inv.data[3 + 1 * 4] = (a->data[0 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 2 * 4] + + a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 2 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[2 + 2 * 4] - + a->data[0 + 2 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[2 + 2 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 2 * 4] * a->data[0 + 1 * 4] * a->data[2 + 0 * 4]); + + inv.data[3 + 2 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[3 + 2 * 4] + + a->data[1 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 2 * 4] + + a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 2 * 4] - + a->data[0 + 2 * 4] * a->data[1 + 1 * 4] * a->data[3 + 0 * 4] - + a->data[1 + 2 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[3 + 2 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]); + + inv.data[3 + 3 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 2 * 4] + + a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[0 + 2 * 4] + + a->data[2 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 2 * 4] - + a->data[0 + 2 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4] - + a->data[1 + 2 * 4] * a->data[2 + 1 * 4] * a->data[0 + 0 * 4] - + a->data[2 + 2 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]); + + /** Remember that our matrix is already transposed and we also got the minors(inside each "inv" entry), + so we just use them. We use a->data[0 + 1 * 4] * inv.data[1 + 0 * 4] becouse inv.data is transposed **/ + float det = a->data[0 + 0 * 4] * inv.data[0 + 0 * 4] + a->data[0 + 1 * 4] * inv.data[1 + 0 * 4] + + a->data[0 + 2 * 4] * inv.data[2 + 0 * 4] + a->data[0 + 3 * 4] * inv.data[3 + 0 * 4]; + + if(det == 0.0f) + return *a; + + det = 1.0f / det; + + for(i = 0; i < 16; i++) + inv.data[i] *= det; + + return inv; +} + +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; +} + +vec4_t mat4_mul_vec4(const mat4_t *a, const vec4_t *b) +{ + vec4_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] * b->w; + 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] * b->w; + 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] * b->w; + c.w = a->data[3 + 0 * 4] * b->x + a->data[3 + 1 * 4] * b->y + a->data[3 + 2 * 4] * b->z + a->data[3 + 3 * 4] * b->w; + return c; +} diff --git a/08-august/src/math/matrix4x4.h b/08-august/src/math/matrix4x4.h new file mode 100644 index 0000000..b7d54aa --- /dev/null +++ b/08-august/src/math/matrix4x4.h @@ -0,0 +1,40 @@ +#ifndef MATRIX4X4_H +#define MATRIX4X4_H + +#include <GL/glew.h> +#include "vector3f.h" +#include "vector4f.h" + +/* accesing data: row + column * width */ +typedef struct +{ + GLfloat data[16]; +} mat4_t; + +extern void mat4_identity(mat4_t *a); +extern mat4_t mat4_inverse(const 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); + +extern vec4_t +mat4_mul_vec4(const mat4_t *a, const vec4_t *b); + +#endif // MATRIX4X4_H diff --git a/08-august/src/math/vector2f.c b/08-august/src/math/vector2f.c new file mode 100644 index 0000000..37ffa9c --- /dev/null +++ b/08-august/src/math/vector2f.c @@ -0,0 +1,54 @@ +#include "vector2f.h" +#include <SDL2/SDL.h> + +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/08-august/src/math/vector2f.h b/08-august/src/math/vector2f.h new file mode 100644 index 0000000..bc1d0bc --- /dev/null +++ b/08-august/src/math/vector2f.h @@ -0,0 +1,19 @@ +#ifndef VECTOR2F_H +#define VECTOR2F_H + +#include <GL/glew.h> + +typedef struct +{ + GLfloat x, y; +} vec2_t; + +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/08-august/src/math/vector3f.c b/08-august/src/math/vector3f.c new file mode 100644 index 0000000..2c2878c --- /dev/null +++ b/08-august/src/math/vector3f.c @@ -0,0 +1,59 @@ +#include "vector3f.h" +#include <SDL2/SDL.h> + +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/08-august/src/math/vector3f.h b/08-august/src/math/vector3f.h new file mode 100644 index 0000000..ab89cb8 --- /dev/null +++ b/08-august/src/math/vector3f.h @@ -0,0 +1,19 @@ +#ifndef VECTOR3F_H +#define VECTOR3F_H + +#include <GL/glew.h> + +typedef struct +{ + GLfloat x, y, z; +} vec3_t; + +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/08-august/src/math/vector4f.c b/08-august/src/math/vector4f.c new file mode 100644 index 0000000..57e4925 --- /dev/null +++ b/08-august/src/math/vector4f.c @@ -0,0 +1,53 @@ +#include "vector4f.h" +#include <SDL2/SDL.h> + +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) ); +} + +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/08-august/src/math/vector4f.h b/08-august/src/math/vector4f.h new file mode 100644 index 0000000..9a2f149 --- /dev/null +++ b/08-august/src/math/vector4f.h @@ -0,0 +1,18 @@ +#ifndef VECTOR4F_H +#define VECTOR4F_H + +#include <GL/glew.h> + +typedef struct +{ + GLfloat x, y, z, w; +} vec4_t; + +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 GLfloat vec4_length(vec4_t *a); +extern vec4_t vec4_normalize(vec4_t *a); + +#endif // VECTOR4F_H diff --git a/08-august/src/player.c b/08-august/src/player.c new file mode 100644 index 0000000..47f285b --- /dev/null +++ b/08-august/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_t){ 0.0f, 35.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/08-august/src/player.h b/08-august/src/player.h new file mode 100644 index 0000000..654dc17 --- /dev/null +++ b/08-august/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/08-august/src/renderer/entity.c b/08-august/src/renderer/entity.c new file mode 100644 index 0000000..b96491d --- /dev/null +++ b/08-august/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/08-august/src/renderer/entity.h b/08-august/src/renderer/entity.h new file mode 100644 index 0000000..ba33004 --- /dev/null +++ b/08-august/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; + GLuint texture; + vec3_t position; + float rotX, rotY, rotZ; +} entity_t; + +extern mat4_t Entity_GetModelTransform(entity_t* entity); + +#endif // ENTITY_H diff --git a/08-august/src/renderer/renderer.c b/08-august/src/renderer/renderer.c new file mode 100644 index 0000000..2ea4426 --- /dev/null +++ b/08-august/src/renderer/renderer.c @@ -0,0 +1,147 @@ +#include "renderer.h" +#include "../util/util_time.h" + +#include <string.h> + +#define MAX_LIGHTS 4 + +void Render_Init() +{ + +} + +void Render_LoadLights(Shader_Layout *layout, const light_t *lights, int n) +{ + vec3_t light_positions[MAX_LIGHTS]; + vec4_t light_colors[MAX_LIGHTS]; + vec3_t attenuation[MAX_LIGHTS]; + + /* Default light in case we are not given enough lights (n < 4) */ + const 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); + glBindTexture(GL_TEXTURE_2D, entity->texture); + + glDrawElements(GL_TRIANGLES, entity->shape->num_indices, GL_UNSIGNED_SHORT, NULL); + glBindVertexArray(0); +} + +/****************************************************************************** +* * +* Function Name: Render_DrawTerrain * +* * +* Specific shader layout * +* -> extra0 Texture_Background * +* -> extra1 Texture_R * +* -> extra2 Texture_G * +* -> extra3 Texture_B * +* -> extra4 Texture_BlendMap * +* * +*******************************************************************************/ + +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); + + /** Set textures for the terrain **/ + + glUniform1i(layout->extra0, 0); + glUniform1i(layout->extra1, 1); + glUniform1i(layout->extra2, 2); + glUniform1i(layout->extra3, 3); + glUniform1i(layout->extra4, 4); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, terrain->textures.texture[0]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, terrain->textures.texture[1]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, terrain->textures.texture[2]); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, terrain->textures.texture[3]); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, terrain->blendmap); + + /************************************************************/ + + glDrawElements(GL_TRIANGLES, terrain->shape->num_indices, GL_UNSIGNED_SHORT, NULL); + + glBindVertexArray(0); +} + +void Render_DrawSky(Shader_Layout *layout, mat4_t *viewMatrix, mat4_t *projectionMatrix, skybox_t *sky) +{ + glBindVertexArray(sky->cube->vao); + + mat4_t myViewMatrix = *viewMatrix; + sky->rotation += SKYBOX_ROTATION_SPEED * Time_GetFrameTime(); + mat4_t rotateMatrix = mat4_rotate_y(sky->rotation); + + /* We don't want to move the skybox around (We want it to stay with the camera in the midle), + just rotate it with the camera so we remove the translations components of the matrix */ + + myViewMatrix.data[0 + 3 * 4] = 0.0f; + myViewMatrix.data[1 + 3 * 4] = 0.0f; + myViewMatrix.data[2 + 3 * 4] = 0.0f; + + myViewMatrix = mat4_mul(&myViewMatrix, &rotateMatrix); + mat4_t totalTransform = mat4_mul(projectionMatrix, &myViewMatrix); + + glUniformMatrix4fv(layout->totalTransform, 1, GL_FALSE, totalTransform.data ); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, sky->texture); + glUniform1i(layout->Texture, 0); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + glBindVertexArray(0); +} + +void Render_Quit() +{ + +} diff --git a/08-august/src/renderer/renderer.h b/08-august/src/renderer/renderer.h new file mode 100644 index 0000000..b6f4f76 --- /dev/null +++ b/08-august/src/renderer/renderer.h @@ -0,0 +1,18 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include "../graphics/shaders.h" +#include "entity.h" +#include "skybox.h" +#include "../terrain.h" +#include "../light.h" + +extern void Render_Init(); +/* Load lights into the shader program */ +extern void Render_LoadLights(Shader_Layout *layout, const 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_DrawSky(Shader_Layout *layout, mat4_t *viewMatrix, mat4_t *projectionMatrix, skybox_t *sky); +extern void Render_Quit(); + +#endif // RENDERER_H diff --git a/08-august/src/renderer/shape.c b/08-august/src/renderer/shape.c new file mode 100644 index 0000000..7f274df --- /dev/null +++ b/08-august/src/renderer/shape.c @@ -0,0 +1,335 @@ +#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 = 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, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, texCoord) ); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, normal) ); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (const void*)offsetof(vertex_t, tangent) ); + + glBindVertexArray(0); + + return shape; +} + +shape_t* Shape_MakeSkyBox(float size) +{ + vec3_t positions[] = + { + {-size, size, -size}, {-size, -size, -size}, {+size, -size, -size}, + {+size, -size, -size}, {+size, +size, -size}, {-size, +size, -size}, + + {-size, -size, +size}, {-size, -size, -size}, {-size, +size, -size}, + {-size, +size, -size}, {-size, +size, +size}, {-size, -size, +size}, + + {+size, -size, -size}, {+size, -size, +size}, {+size, +size, +size}, + {+size, +size, +size}, {+size, +size, -size}, {+size, -size, -size}, + + {-size, -size, +size}, {-size, +size, +size}, {+size, +size, +size}, + {+size, +size, +size}, {+size, -size, +size}, {-size, -size, +size}, + + {-size, +size, -size}, {+size, +size, -size}, {+size, +size, +size}, + {+size, +size, +size}, {-size, +size, +size}, {-size, +size, -size}, + + {-size, -size, -size}, {-size, -size, +size}, {+size, -size, -size}, + {+size, -size, -size}, {-size, -size, +size}, {+size, -size, +size} + }; + + shape_t *shape = malloc( sizeof(shape_t) ); + + shape->num_indices = 0; + + glGenVertexArrays(1, &shape->vao); + glGenBuffers(1, &shape->vbo); + shape->ebo = 0; + + glBindVertexArray(shape->vao); + + glBindBuffer(GL_ARRAY_BUFFER, shape->vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0 ); + + glBindVertexArray(0); + + return shape; +} + +static const int BUFFER_size = 128; + +typedef struct +{ + vertex_t *data; + GLushort *indices; + + vec3_t *positions; + vec2_t *textures; + vec3_t *normals; + vec3_t *tangents; + + unsigned int vertex_count, index_count; + unsigned int index_pointer; + + GLubyte hasTextCoords, hasNormals; +} OBJ_Mesh; + +static vertex_t *search_index(vertex_t *pkey, vertex_t *pelem, unsigned int vertex_count) +{ + int i; + for(i = 0; i < vertex_count; i++) + { + if(pelem[i].position.x == pkey->position.x && + pelem[i].position.y == pkey->position.y && + pelem[i].position.z == pkey->position.z && + pelem[i].texCoord.x == pkey->texCoord.x && + pelem[i].texCoord.y == pkey->texCoord.y && + pelem[i].normal.x == pkey->normal.x && + pelem[i].normal.y == pkey->normal.y && + pelem[i].normal.z == pkey->normal.z) + { + return &pelem[i]; + } + } + return NULL; +} + +static void calculate_tangents(OBJ_Mesh *mesh) +{ + int i; + for(i = 0; i < mesh->index_count; i += 3) + { + int i0 = i; + int i1 = i + 1; + int i2 = i + 2; + + vec3_t *v0 = &mesh->positions[i0]; + vec3_t *v1 = &mesh->positions[i1]; + vec3_t *v2 = &mesh->positions[i2]; + + vec2_t *uv0 = &mesh->textures[i0]; + vec2_t *uv1 = &mesh->textures[i1]; + vec2_t *uv2 = &mesh->textures[i2]; + + vec3_t deltaPos1 = vec3_sub(v1, v0); + vec3_t deltaPos2 = vec3_sub(v2, v0); + + vec2_t deltaUV1 = vec2_sub(uv1, uv0); + vec2_t deltaUV2 = vec2_sub(uv2, uv0); + + GLfloat r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x); + + deltaPos1 = vec3_scalar_mul(&deltaPos1, deltaUV2.y); + deltaPos2 = vec3_scalar_mul(&deltaPos2, deltaUV1.y); + + vec3_t tangent = vec3_sub(&deltaPos1, &deltaPos2); + tangent = vec3_scalar_mul(&tangent, r); + + mesh->tangents[i2] = tangent; + mesh->tangents[i1] = tangent; + mesh->tangents[i0] = tangent; + } + /* + We normalize the tangents at the end of the parse_obj_index loop + for(i = 0; i < mesh.index_count; i++) + { + mesh.tangents[i] = vec3_normalize(&mesh.tangents[i]); + } + */ +} + +static void parse_obj_index(OBJ_Mesh *mesh, vertex_t *current_vertex) +{ + vertex_t *indexOnArray = search_index(current_vertex, mesh->data, mesh->vertex_count); + + /* We check if the vertex was already loaded, so the index points to the created vertex instead of repeating data*/ + if(indexOnArray == NULL) + { + mesh->data = (vertex_t*) realloc( mesh->data, sizeof(vertex_t) * (++mesh->vertex_count) ); + + /* We make the index point to the last vertex added */ + mesh->indices[mesh->index_pointer] = mesh->vertex_count - 1; + + mesh->data[mesh->vertex_count - 1] = *current_vertex; + } + else + { + GLushort index = (GLushort)(indexOnArray - mesh->data); + mesh->data[index].tangent = vec3_add( &mesh->data[index].tangent, + ¤t_vertex->tangent ); + + /* We make the index point to the previus vertex added instead of creating a new one */ + mesh->indices[mesh->index_pointer] = index; + } + + mesh->index_pointer += 1; +} + +shape_t* Shape_LoadOBJ(const char* path) +{ + OBJ_Mesh mesh; + memset( &mesh, 0, sizeof(OBJ_Mesh) ); + + vec3_t *positions = NULL; + vec3_t *normals = NULL; + vec2_t *textures = NULL; + + vertex_t current_vertex; + + unsigned int positions_count = 0, normals_count = 0, textures_count = 0; + + int count = 0, i; + int texture[3], normal[3], verts[3]; + + FILE *file = fopen(path, "r"); + if(file == NULL) + Util_FatalError("%s file could not be loaded!", path); + + 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 + { + positions = (vec3_t*) realloc(positions, sizeof(vec3_t) * (++positions_count) ); + count = sscanf(buffer, "v %f %f %f\n", &positions[positions_count - 1].x, + &positions[positions_count - 1].y, &positions[positions_count - 1].z); + + if(count != 3) + Util_FatalError("Bad vertices data on .obj file"); + } + break; + case 'f': + mesh.index_count += 3; + + mesh.positions = realloc(mesh.positions, mesh.index_count * sizeof(vec3_t) ); + mesh.textures = realloc(mesh.textures, mesh.index_count * sizeof(vec2_t) ); + mesh.normals = realloc(mesh.normals, mesh.index_count * sizeof(vec3_t) ); + + 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"); + + mesh.positions[mesh.index_count - 3] = positions[ verts[0] - 1 ]; + mesh.textures[mesh.index_count - 3] = textures[ texture[0] - 1 ]; + mesh.normals[mesh.index_count - 3] = normals[ normal[0] - 1 ]; + + mesh.positions[mesh.index_count - 2] = positions[ verts[1] - 1 ]; + mesh.textures[mesh.index_count - 2] = textures[ texture[1] - 1 ]; + mesh.normals[mesh.index_count - 2] = normals[ normal[1] - 1 ]; + + mesh.positions[mesh.index_count - 1] = positions[ verts[2] - 1 ]; + mesh.textures[mesh.index_count - 1] = textures[ texture[2] - 1 ]; + mesh.normals[mesh.index_count - 1] = normals[ normal[2] - 1 ]; + + break; + default: + break; + } + } + + mesh.indices = malloc( mesh.index_count * sizeof(GLushort) ); + mesh.tangents = malloc( mesh.index_count * sizeof(vec3_t) ); + calculate_tangents(&mesh); + + for(i = 0; i < mesh.index_count; i++) + { + current_vertex = (vertex_t){.position = mesh.positions[i], .texCoord = mesh.textures[i], + .normal = mesh.normals[i], .tangent = mesh.tangents[i] }; + parse_obj_index(&mesh, ¤t_vertex); + } + + for(i = 0; i < mesh.vertex_count; i++) + { + mesh.data[i].tangent = vec3_normalize(&mesh.data[i].tangent); + } + + free(mesh.positions); + free(mesh.normals); + free(mesh.textures); + free(mesh.tangents); + + free(positions); + free(textures); + free(normals); + + fclose(file); + + GLsizeiptr vertexBuffersize = mesh.vertex_count * sizeof(vertex_t); + GLsizeiptr indexBuffersize = mesh.index_count * sizeof(GLushort); + + shape_t* shape = Shape_CreateFromRawData(mesh.data, vertexBuffersize, mesh.indices, indexBuffersize); + + free(mesh.data); + free(mesh.indices); + + return shape; +} + +void Shape_Free(shape_t* shape) +{ + if(shape) + { + if(shape->vbo) + glDeleteBuffers(1, &shape->vbo); + if(shape->ebo) + glDeleteBuffers(1, &shape->ebo); + if(shape->vao) + glDeleteVertexArrays(1, &shape->vao); + free(shape); + } +} diff --git a/08-august/src/renderer/shape.h b/08-august/src/renderer/shape.h new file mode 100644 index 0000000..8942548 --- /dev/null +++ b/08-august/src/renderer/shape.h @@ -0,0 +1,26 @@ +#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_MakeSkyBox(float size); + +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/08-august/src/renderer/skybox.h b/08-august/src/renderer/skybox.h new file mode 100644 index 0000000..235ee1a --- /dev/null +++ b/08-august/src/renderer/skybox.h @@ -0,0 +1,16 @@ +#ifndef SKYBOX_H +#define SKYBOX_H + +#include <GL/glew.h> +#include "shape.h" + +#define SKYBOX_ROTATION_SPEED 1.0f + +typedef struct +{ + GLuint texture; + shape_t *cube; + GLfloat rotation; +} skybox_t; + +#endif // SKYBOX_H diff --git a/08-august/src/terrain.c b/08-august/src/terrain.c new file mode 100644 index 0000000..c3e972a --- /dev/null +++ b/08-august/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
+
+#include <stdlib.h> + +#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, GLuint 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_t){ (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_t){ 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); + } + } + + 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/08-august/src/terrain.h b/08-august/src/terrain.h new file mode 100644 index 0000000..da9828b --- /dev/null +++ b/08-august/src/terrain.h @@ -0,0 +1,27 @@ +#ifndef TERRAIN_H +#define TERRAIN_H + +#include "renderer/shape.h" +#include "texture.h" + +typedef struct +{ + GLuint texture[4]; +} TerrainTexturePack; + +typedef struct +{ + shape_t *shape; + GLuint 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, GLuint 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/08-august/src/texture.c b/08-august/src/texture.c new file mode 100644 index 0000000..d1b70d9 --- /dev/null +++ b/08-august/src/texture.c @@ -0,0 +1,71 @@ +#include "texture.h" +#include "util/util.h" + +#include <SDL2/SDL.h> +#include <SDL2/SDL_image.h> + +GLuint Texture_Create2D( const char *path ) +{ + GLuint ID; + SDL_Surface *data = IMG_Load(path); + if(data == NULL) + Util_FatalError("Texture %s could not be found!\n", path); + + glGenTextures(1, &ID); + glBindTexture(GL_TEXTURE_2D, ID); + + SDL_LockSurface(data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data->w, data->h, GL_FALSE, GL_RGBA, GL_UNSIGNED_BYTE, data->pixels); + SDL_UnlockSurface(data); + + 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); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.4); + + SDL_FreeSurface(data); + glBindTexture(GL_TEXTURE_2D, 0); + + return ID; +} + +GLuint Texture_CreateCubeMap( const char *paths[6] ) +{ + GLuint ID; + glGenTextures(1, &ID); + glBindTexture(GL_TEXTURE_CUBE_MAP, ID); + + SDL_Surface *data; + + int i; + for(i = 0; i < 6; i++) + { + data = IMG_Load(paths[i]); + + if(data == NULL) + Util_FatalError("Texture %s could not be found!\n", paths[i]); + + SDL_LockSurface(data); + + /* All the textures sides are linearly stored so we just add "i" */ + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, + data->w, data->h, GL_FALSE, GL_RGBA, GL_UNSIGNED_BYTE, data->pixels); + + SDL_UnlockSurface(data); + + SDL_FreeSurface(data); + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + return ID; +} + +void Texture_Destroy(GLuint ID) +{ + glDeleteTextures(1, &ID); +} diff --git a/08-august/src/texture.h b/08-august/src/texture.h new file mode 100644 index 0000000..ea19124 --- /dev/null +++ b/08-august/src/texture.h @@ -0,0 +1,10 @@ +#ifndef TEXTURE_H +#define TEXTURE_H + +#include <GL/glew.h> + +extern GLuint Texture_Create2D( const char *path ); +extern GLuint Texture_CreateCubeMap( const char *paths[6] ); +extern void Texture_Destroy( GLuint ID ); + +#endif // TEXTURE_H diff --git a/08-august/src/util/util.c b/08-august/src/util/util.c new file mode 100644 index 0000000..ad0f1ce --- /dev/null +++ b/08-august/src/util/util.c @@ -0,0 +1,87 @@ +#include "util.h" + +#include <SDL2/SDL.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> + +void Util_FatalError( const char *error, ... ) +{ + fprintf(stderr, "Fatal Error:\n"); + + va_list args; + va_start(args, error); + vfprintf(stderr, error, args); + va_end(args); + + SDL_Quit(); + exit(1); +} + +char *Util_LoadFile( const char *path ) +{ + FILE* file = fopen( path, "r" ); + + if(file == NULL) + { + Util_FatalError("File %s could not be found!\n", path); + } + + 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; +} + +vec3_t +Util_GetMouseRay(int screenWidth, int screenHeigth, mat4_t *viewMatrix, mat4_t *projectionMatrix, + int mouseX, int mouseY) +{ + vec4_t eyeCoords; + vec3_t mouseRay; + /* Normalized device coords NOTE: -y becouse for SDL y = 0 is the top of the screen */ + GLfloat normalX = ( 2.0f * (GLfloat)mouseX ) / (GLfloat) screenWidth - 1.0f; + GLfloat normalY = 1.0f - (2.0f * (GLfloat)mouseY) / (GLfloat) screenHeigth; + + /* clipCoords include 4th component */ + vec4_t clipCoords = { normalX, normalY, -1.0f, 1.0f }; + + /* Remove perpective */ + { + mat4_t invertedProjection = mat4_inverse(projectionMatrix); + eyeCoords = mat4_mul_vec4(&invertedProjection, &clipCoords); + eyeCoords.z = -1.0f; + eyeCoords.w = 0.0f; + } + + /* Remove view matrix*/ + { + mat4_t invertedViewMatrix = mat4_inverse(viewMatrix); + vec4_t temp = mat4_mul_vec4(&invertedViewMatrix, &eyeCoords); + + mouseRay.x = temp.x; + mouseRay.y = temp.y; + mouseRay.z = temp.z; + + mouseRay = vec3_normalize(&mouseRay); + } + + /* Return the ray in world coordinates */ + return mouseRay; +} diff --git a/08-august/src/util/util.h b/08-august/src/util/util.h new file mode 100644 index 0000000..7227547 --- /dev/null +++ b/08-august/src/util/util.h @@ -0,0 +1,25 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "../math/matrix4x4.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); + +extern vec3_t +Util_GetMouseRay(int screenWidth, int screenHeigth, mat4_t *viewMatrix, mat4_t *projectionMatrix, + int mouseX, int mouseY); + +#endif // UTIL_H diff --git a/08-august/src/util/util_time.c b/08-august/src/util/util_time.c new file mode 100644 index 0000000..b601379 --- /dev/null +++ b/08-august/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/08-august/src/util/util_time.h b/08-august/src/util/util_time.h new file mode 100644 index 0000000..3c3e470 --- /dev/null +++ b/08-august/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/08-august/src/vertex.h b/08-august/src/vertex.h new file mode 100644 index 0000000..7ac2ec8 --- /dev/null +++ b/08-august/src/vertex.h @@ -0,0 +1,17 @@ +#ifndef VERTEX_H +#define VERTEX_H + +#include <GL/glew.h> +#include "math/vector2f.h" +#include "math/vector3f.h" +#include "math/vector4f.h" + +typedef struct +{ + vec3_t position; + vec2_t texCoord; + vec3_t normal; + vec3_t tangent; +} vertex_t; + +#endif // VERTEX_H |
