Added camera and model. Made several modifications and fixes throughout the code

dev
Shariq Shah 10 years ago
parent bc46f57091
commit 1b649feadc
  1. 8
      orgfile.org
  2. 98
      src/camera.c
  3. 29
      src/camera.h
  4. 14
      src/components.h
  5. 115
      src/entity.c
  6. 5
      src/entity.h
  7. 2
      src/file_io.c
  8. 45
      src/game.c
  9. 28
      src/geometry.c
  10. 3
      src/geometry.h
  11. 170
      src/input.c
  12. 119
      src/linmath.h
  13. 107
      src/model.c
  14. 20
      src/model.h
  15. 5
      src/renderer.c
  16. 26
      src/shader.c
  17. 19
      src/transform.c
  18. 1
      src/transform.h
  19. 2
      src/window_system.c

@ -34,10 +34,14 @@ while using as few libraries as possible.
- State "DONE" from "TODO" [2015-07-27 Mon 11:54] - State "DONE" from "TODO" [2015-07-27 Mon 11:54]
** DONE Investigate about Exit() and at_exit() functions and whether to use them or not. ** DONE Investigate about Exit() and at_exit() functions and whether to use them or not.
- State "DONE" from "TODO" [2015-08-02 Sun 19:09] - State "DONE" from "TODO" [2015-08-02 Sun 19:09]
** TODO Fix readme markdown
** TODO Framebuffer and resolution independent rendering
** TODO Entity ** TODO Entity
** TODO Positive and negative values for input_maps and returning corresponding values when they are true ** TODO Positive and negative values for input_maps and returning corresponding values when they are true
** TODO Camera ** DONE Camera
** TODO Test render - State "DONE" from "TODO" [2015-08-19 Wed 13:30]
** DONE Test render
- State "DONE" from "TODO" [2015-08-19 Wed 13:30]
** TODO Bounding Boxes ** TODO Bounding Boxes
** TODO Materials ** TODO Materials
** TODO Mesh/Model ** TODO Mesh/Model

@ -0,0 +1,98 @@
#include "camera.h"
#include "entity.h"
#include "transform.h"
#include "array.h"
static struct Camera* camera_list;
static int* empty_indices;
struct Camera* camera_get(int index)
{
struct Camera* camera = NULL;
if(index > -1 && index < array_len(camera_list))
camera = &camera_list[index];
return camera;
}
void camera_init(void)
{
camera_list = array_new(struct Camera);
empty_indices = array_new(int);
}
void camera_remove(int index)
{
if(index > -1 && index < array_len(camera_list))
{
camera_list->node = -1;
array_push(empty_indices, index, int);
}
}
void camera_cleanup(void)
{
array_free(camera_list);
array_free(empty_indices);
}
int camera_create(int node, int width, int height)
{
int index = -1;
struct Camera* new_camera = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
new_camera = &camera_list[index];
array_pop(empty_indices);
}
else
{
new_camera = array_grow(camera_list, struct Camera);
index = array_len(camera_list) - 1;
}
new_camera->node = node;
new_camera->farz = 1000.f;
new_camera->nearz = 0.1f;
new_camera->fov = TO_RADIANS(60.f);
new_camera->aspect_ratio = ((float)width / (float)height) <= 0.f ? (4.f / 3.f) : ((float)width / (float)height);
new_camera->ortho = 0;
camera_update_view(new_camera);
camera_update_proj(new_camera);
return index;
}
void camera_update_view_proj(struct Camera* camera)
{
mat4_mul(camera->view_proj_mat, camera->proj_mat, camera->view_mat);
}
void camera_update_view(struct Camera* camera)
{
struct Entity* entity = entity_get(camera->node);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
vec3 lookat = {0.f}, up = {0.f};
transform_get_lookat(transform, lookat);
transform_get_up(transform, up);
mat4_look_at(camera->view_mat, transform->position, lookat, up);
camera_update_view_proj(camera);
}
void camera_update_proj(struct Camera* camera)
{
if(!camera->ortho)
{
mat4_perspective(camera->proj_mat,
camera->fov,
camera->aspect_ratio,
camera->nearz,
camera->farz);
}
else
{
mat4_ortho(camera->proj_mat, -1, 1, -1, 1, camera->nearz, camera->farz);
}
camera_update_view_proj(camera);
}

@ -0,0 +1,29 @@
#ifndef camera_H
#define camera_H
#include "linmath.h"
struct Camera
{
int node;
mat4 proj_mat;
mat4 view_mat;
mat4 view_proj_mat;
float fov;
float aspect_ratio;
float nearz;
float farz;
int ortho;
};
struct Camera* camera_get(int index);
void camera_init(void);
void camera_cleanup(void);
void camera_remove(int index);
int camera_create(int node, int width, int height);
void camera_update_view_proj(struct Camera* camera);
void camera_update_view(struct Camera* camera);
void camera_update_proj(struct Camera* camera);
#endif

@ -10,4 +10,18 @@ enum Component
MAX_COMPONENTS MAX_COMPONENTS
}; };
inline static const char* comp_to_str(enum Component component)
{
const char* str = 0;
switch(component)
{
case C_TRANSFORM : str = "TRANSFORM"; break;
case C_MODEL : str = "MODEL"; break;
case C_CAMERA : str = "CAMERA"; break;
case C_RIGIDBODY : str = "RIGIDBODY"; break;
case MAX_COMPONENTS : str = "MAX_COMPONENTS"; break;
}
return str;
}
#endif #endif

@ -3,15 +3,17 @@
#include "log.h" #include "log.h"
#include "string_utils.h" #include "string_utils.h"
#include "transform.h" #include "transform.h"
#include "camera.h"
#include "model.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdarg.h>
static struct Entity* entity_list; static struct Entity* entity_list;
static int* empty_indices; static int* empty_indices;
void entity_init(void) void entity_init(void)
{ {
entity_list = array_new(struct Entity); entity_list = array_new(struct Entity);
@ -33,21 +35,16 @@ void entity_remove(int index)
for(int i = 0; i < MAX_COMPONENTS; i++) for(int i = 0; i < MAX_COMPONENTS; i++)
{ {
switch((enum Component)i) if(i == C_TRANSFORM)
{ {
case C_TRANSFORM: transform_remove(entity->components[i]); break; transform_remove(entity->components[i]);
case C_MODEL:
break;
case C_RIGIDBODY:
break;
case C_CAMERA:
break;
default:
/* Only called for MAX_COMPONENTS, do nothing */
break;
}
entity->components[i] = -1; entity->components[i] = -1;
} }
else
{
entity_component_remove(entity, i);
}
}
entity->node = -1; entity->node = -1;
free(entity->name); free(entity->name);
free(entity->tag); free(entity->tag);
@ -79,6 +76,8 @@ struct Entity* entity_create(const char* name, const char* tag)
new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME"); new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME");
new_entity->tag = tag ? str_new(tag) : str_new("DEFAULT_TAG"); new_entity->tag = tag ? str_new(tag) : str_new("DEFAULT_TAG");
new_entity->node = index; new_entity->node = index;
for(int i = 0; i < MAX_COMPONENTS; i++)
new_entity->components[i] = -1;
new_entity->components[C_TRANSFORM] = transform_create(new_entity->node); new_entity->components[C_TRANSFORM] = transform_create(new_entity->node);
return new_entity; return new_entity;
@ -111,67 +110,117 @@ struct Entity* entity_find(const char* name)
} }
return entity; return entity;
} }
int entity_component_remove(struct Entity* entity, enum Component component) int entity_component_remove(struct Entity* entity, enum Component component)
{ {
int success = 1; int success = 1;
assert(entity); assert(entity);
int comp_index = entity->components[component];
switch(component) switch(component)
{ {
case C_TRANSFORM: case C_TRANSFORM: log_error("entity:remove_component", "Cannot remove TRANSFORM"); break;
log_error("entity:remove", "Cannot remove Tranform component"); case C_MODEL: if(comp_index != -1) model_remove(comp_index); break;
success = 0; case C_CAMERA: if(comp_index != -1) camera_remove(comp_index); break;
break;
case C_MODEL:
break;
case C_RIGIDBODY: case C_RIGIDBODY:
break; break;
case C_CAMERA:
break;
default: default:
log_error("entity:component_remove", "Invalid component type"); /* Only called for MAX_COMPONENTS, do nothing */
break; break;
} }
entity->components[component] = -1;
if(success) entity->components[component] = -1; if(success) entity->components[component] = -1;
return success; return success;
} }
void* entity_component_get(struct Entity* entity, enum Component component) void* entity_component_get(struct Entity* entity, enum Component component)
{ {
void* comp_obj = NULL; void* comp_obj = NULL;
assert(entity); assert(entity);
int comp_index = entity->components[component];
if(comp_index != -1)
{
switch(component) switch(component)
{ {
case C_TRANSFORM: comp_obj = transform_get(entity->components[C_TRANSFORM]); break; case C_TRANSFORM: comp_obj = transform_get(comp_index); break;
case C_MODEL: case C_MODEL: comp_obj = model_get(comp_index); break;
break; case C_CAMERA: comp_obj = camera_get(comp_index); break;
case C_RIGIDBODY: case C_RIGIDBODY:
break; break;
case C_CAMERA: default: log_error("entity:component_get", "Invalid component type"); break;
break; }
default: }
log_error("entity:component_get", "Invalid component type"); else
break; {
log_error("entity:component_get", "Entity '%s' does not have component %s",
entity->name,
comp_to_str(component));
} }
return comp_obj; return comp_obj;
} }
void* entity_component_add(struct Entity* entity, enum Component component) void* entity_component_add(struct Entity* entity, enum Component component, ...)
{ {
void* new_comp = NULL; void* new_comp = NULL;
assert(entity); assert(entity);
va_list args;
va_start(args, component);
int new_comp_index = -1;
switch(component) switch(component)
{ {
case C_TRANSFORM: case C_TRANSFORM:
log_error("entity:add_component", "Entity already has Transform component"); log_error("entity:add_component", "Entity already has Transform component");
case C_MODEL: case C_MODEL:
break; {
case C_RIGIDBODY: const char* filename = va_arg(args, const char*);
new_comp_index = model_create(entity->node, filename);
new_comp = model_get(new_comp_index);
}
break; break;
case C_CAMERA: case C_CAMERA:
{
int width = va_arg(args, int);
int height = va_arg(args, int);
new_comp_index = camera_create(entity->node, width, height);
new_comp = camera_get(new_comp_index);
}
break;
case C_RIGIDBODY:
break; break;
default: default:
log_error("entity:component_add", "Invalid component type"); log_error("entity:component_add", "Invalid component type");
break; break;
} }
if(new_comp_index == -1)
{
log_error("entity:component_add", "%s component not added to %s",
comp_to_str(component),
entity->name);
}
else
{
entity->components[component] = new_comp_index;
log_message("%s component added to %s", comp_to_str(component), entity->name);
}
va_end(args);
return new_comp; return new_comp;
} }
int entity_has_component(struct Entity* entity, enum Component component)
{
int has_comp = 0;
if(entity->components[component] != -1)
has_comp = 1;
return has_comp;
}
void entity_sync_components(struct Entity* entity)
{
if(entity_has_component(entity, C_CAMERA))
{
struct Camera* camera = entity_component_get(entity, C_CAMERA);
camera_update_view(camera);
}
}

@ -20,7 +20,8 @@ struct Entity* entity_get(int index);
struct Entity* entity_find(const char* name); struct Entity* entity_find(const char* name);
int entity_component_remove(struct Entity* entity, enum Component component); int entity_component_remove(struct Entity* entity, enum Component component);
void* entity_component_get(struct Entity* entity, enum Component component); void* entity_component_get(struct Entity* entity, enum Component component);
void* entity_component_add(struct Entity* entity, enum Component component); void* entity_component_add(struct Entity* entity, enum Component component, ...);
int entity_has_component(struct Entity* entity, enum Component component);
void entity_sync_components(struct Entity* entity);
#endif #endif

@ -70,6 +70,6 @@ FILE* io_file_open(const char* path, const char* mode)
char* relative_path = str_new(base_assets_path); char* relative_path = str_new(base_assets_path);
relative_path = str_concat(relative_path, path); relative_path = str_concat(relative_path, path);
FILE* file = fopen(relative_path, mode); FILE* file = fopen(relative_path, mode);
if(!file) log_error("io:file", "Fialed to open file '%s'", relative_path); if(!file) log_error("io:file", "Failed to open file '%s'", relative_path);
return file; return file;
} }

@ -15,6 +15,7 @@
#include "array.h" #include "array.h"
#include "transform.h" #include "transform.h"
#include "camera.h" #include "camera.h"
#include "model.h"
void run(void); void run(void);
void update(float dt); void update(float dt);
@ -22,6 +23,7 @@ void render(void);
void debug(float dt); void debug(float dt);
struct Entity* entity = NULL; struct Entity* entity = NULL;
struct Camera* active_camera = NULL;
void game_init(void) void game_init(void)
{ {
@ -35,19 +37,26 @@ void game_init(void)
camera_init(); camera_init();
entity_init(); entity_init();
geom_init(); geom_init();
model_init();
int keys[2] = {'W', GLFW_KEY_UP}; int up_keys[2] = {'W', GLFW_KEY_UP};
int keys2[2] = {'S', GLFW_KEY_DOWN}; int down_keys[2] = {'S', GLFW_KEY_DOWN};
int keys3[1] = {'J'}; int left_keys[2] = {'A', GLFW_KEY_LEFT};
int keys4[1] = {'K'}; int right_keys[2] = {'D', GLFW_KEY_RIGHT};
input_map_create("MoveUp", keys, 2); input_map_create("Move_Up", up_keys, 2);
input_map_create("MoveDown", keys2, 2); input_map_create("Move_Down", down_keys, 2);
input_map_create("Test", keys3, 1); input_map_create("Move_Left", left_keys, 2);
input_map_create("Test2", keys4, 1); input_map_create("Move_Right", right_keys, 2);
int shader = shader_create("phong.vert", "phong.frag"); int shader = shader_create("unshaded.vert", "unshaded.frag");
entity = entity_create("Test", "None"); entity = entity_create("Test", "None");
active_camera = entity_component_add(entity, C_CAMERA, 800, 600);
struct Entity* new_ent = entity_create("Model_Entity", NULL);
struct Transform* tran = entity_component_get(new_ent, C_TRANSFORM);
vec3 position = {0, 0, -5};
transform_translate(tran, position, TS_WORLD);
struct Model* model = entity_component_add(new_ent, C_MODEL, "default.pamesh");
run(); run();
} }
@ -55,10 +64,22 @@ void game_init(void)
void debug(float dt) void debug(float dt)
{ {
struct Transform* transform = entity_component_get(entity, C_TRANSFORM); struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
vec3 offset = {0, 5, 0}; float speed = 5.f;
vec3 offset = {0, 0, 0};
if(input_map_state_get("Move_Up", GLFW_PRESS)) offset[2] -= speed;
if(input_map_state_get("Move_Down", GLFW_PRESS)) offset[2] += speed;
if(input_map_state_get("Move_Left", GLFW_PRESS)) offset[0] -= speed;
if(input_map_state_get("Move_Right", GLFW_PRESS)) offset[0] += speed;
vec3_scale(offset, offset, dt); vec3_scale(offset, offset, dt);
if(offset[0] != 0 || offset[2] != 0)
{
transform_translate(transform, offset, TS_WORLD); transform_translate(transform, offset, TS_WORLD);
log_message("Position : %.3f, %.3f, %.3f", transform->position[0], transform->position[1], transform->position[2]); log_message("Position : %.3f, %.3f, %.3f",
transform->position[0],
transform->position[1],
transform->position[2]);
}
} }
void run(void) void run(void)
@ -83,7 +104,6 @@ void update(float dt)
if(input_key_state_get(GLFW_KEY_ESCAPE, GLFW_PRESS)) if(input_key_state_get(GLFW_KEY_ESCAPE, GLFW_PRESS))
window_set_should_close(1); window_set_should_close(1);
if(input_map_state_get("MoveUp", GLFW_PRESS))
debug(dt); debug(dt);
} }
@ -95,6 +115,7 @@ void render(void)
void game_cleanup(void) void game_cleanup(void)
{ {
entity_cleanup(); entity_cleanup();
model_cleanup();
geom_cleanup(); geom_cleanup();
transform_cleanup(); transform_cleanup();
camera_cleanup(); camera_cleanup();

@ -25,7 +25,7 @@ struct Geometry
uint normal_vbo; uint normal_vbo;
uint color_vbo; uint color_vbo;
uint index_vbo; uint index_vbo;
uint ref_count; int ref_count;
vec3* vertices; vec3* vertices;
vec3* vertex_colors; vec3* vertex_colors;
vec3* normals; vec3* normals;
@ -73,7 +73,6 @@ int geom_create(const char* name)
{ {
/* add new geometry object or overwrite existing one */ /* add new geometry object or overwrite existing one */
struct Geometry* new_geo = NULL; struct Geometry* new_geo = NULL;
int index = -1;
int empty_len = array_len(empty_indices); int empty_len = array_len(empty_indices);
if(empty_len > 0) if(empty_len > 0)
{ {
@ -112,6 +111,11 @@ void geom_remove(int index)
if(index >= 0 && index < array_len(geometry_list)) if(index >= 0 && index < array_len(geometry_list))
{ {
struct Geometry* geometry = &geometry_list[index]; struct Geometry* geometry = &geometry_list[index];
if(geometry->ref_count >= 0)
{
geometry->ref_count--;
if(geometry->ref_count < 0)
{
array_free(geometry->indices); array_free(geometry->indices);
array_free(geometry->vertices); array_free(geometry->vertices);
array_free(geometry->uvs); array_free(geometry->uvs);
@ -120,6 +124,8 @@ void geom_remove(int index)
free(geometry->filename); free(geometry->filename);
array_push(empty_indices, index, int); array_push(empty_indices, index, int);
} }
}
}
} }
void geom_cleanup(void) void geom_cleanup(void)
@ -161,15 +167,21 @@ int load_from_file(struct Geometry* geometry, const char* filename)
// Indices // Indices
geometry->indices = array_new_cap(uint, indices_count); geometry->indices = array_new_cap(uint, indices_count);
fread(geometry->indices, INDEX_SIZE, indices_count, file); fread(geometry->indices, INDEX_SIZE, indices_count, file);
array_match_len_cap(geometry->indices);
// Vertices // Vertices
geometry->vertices = array_new_cap(vec3, vertices_count); geometry->vertices = array_new_cap(vec3, vertices_count);
fread(geometry->vertices, VEC3_SIZE, vertices_count, file); fread(geometry->vertices, VEC3_SIZE, vertices_count, file);
array_match_len_cap(geometry->vertices);
// Normals // Normals
geometry->normals = array_new_cap(vec3, normals_count); geometry->normals = array_new_cap(vec3, normals_count);
fread(geometry->normals, VEC3_SIZE, normals_count, file); fread(geometry->normals, VEC3_SIZE, normals_count, file);
array_match_len_cap(geometry->normals);
// Uvs // Uvs
geometry->uvs = array_new_cap(vec2, uvs_count); geometry->uvs = array_new_cap(vec2, uvs_count);
fread(geometry->uvs, VEC2_SIZE, uvs_count, file); fread(geometry->uvs, VEC2_SIZE, uvs_count, file);
array_match_len_cap(geometry->uvs);
geometry->vertex_colors = array_new(vec3);
} }
fclose(file); fclose(file);
geometry->filename = str_new(filename); geometry->filename = str_new(filename);
@ -251,3 +263,15 @@ void create_vao(struct Geometry* geometry)
} }
glBindVertexArray(0); glBindVertexArray(0);
} }
void geom_render(int index)
{
struct Geometry* geo = &geometry_list[index];
glBindVertexArray(geo->vao);
if(geo->draw_indexed)
glDrawElements(GL_TRIANGLES, array_len(geo->indices), GL_UNSIGNED_INT, (void*)0);
else
glDrawArrays(GL_TRIANGLES, 0, array_len(geo->vertices));
glBindVertexArray(0);
}

@ -2,9 +2,10 @@
#define geometry_H #define geometry_H
void geom_init(void); void geom_init(void);
int geom_ceate(const char* name); int geom_create(const char* name);
int geom_find(const char* filename); int geom_find(const char* filename);
void geom_remove(int index); void geom_remove(int index);
void geom_cleanup(void); void geom_cleanup(void);
void geom_render(int index);
#endif #endif

@ -22,6 +22,7 @@ static void input_on_key(GLFWwindow* window, int key, int scancode, int action,
static void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods); static void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods);
static void input_on_cursor_move(GLFWwindow* window, double xpos, double ypos); static void input_on_cursor_move(GLFWwindow* window, double xpos, double ypos);
static int map_find(const char* name); static int map_find(const char* name);
static const char* get_key_name(int key);
static struct Input_Map* input_map_list; static struct Input_Map* input_map_list;
@ -30,6 +31,7 @@ void input_init(GLFWwindow* window)
glfwSetMouseButtonCallback(window, input_on_mousebutton); glfwSetMouseButtonCallback(window, input_on_mousebutton);
glfwSetKeyCallback(window, input_on_key); glfwSetKeyCallback(window, input_on_key);
glfwSetCursorPosCallback(window, input_on_cursor_move); glfwSetCursorPosCallback(window, input_on_cursor_move);
//glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
input_map_list = array_new(struct Input_Map); input_map_list = array_new(struct Input_Map);
} }
@ -63,7 +65,7 @@ static void input_on_key(GLFWwindow* window, int key, int scancode, int action,
struct Input_Map* map = &input_map_list[i]; struct Input_Map* map = &input_map_list[i];
for(int j = 0; j < array_len(map->keys); j++) for(int j = 0; j < array_len(map->keys); j++)
{ {
if(map->keys[i] == key) if(map->keys[j] == key)
{ {
map->state = action; map->state = action;
break; break;
@ -103,21 +105,52 @@ int input_map_state_get(const char* map_name, int state)
break; break;
} }
} }
if(state == GLFW_PRESS)
{
if(current_state == GLFW_PRESS || current_state == GLFW_REPEAT)
return 1;
else
return 0;
}
else
{
return state == current_state ? 1 : 0; return state == current_state ? 1 : 0;
}
} }
int input_key_state_get(int key, int state_type) int input_key_state_get(int key, int state_type)
{ {
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
int current_state = glfwGetKey(window, key); int current_state = glfwGetKey(window, key);
return current_state == state_type ? 1 : 0; if(state_type == GLFW_PRESS)
{
if(current_state == GLFW_PRESS || current_state == GLFW_REPEAT)
return 1;
else
return 0;
}
else
{
return state_type == current_state ? 1 : 0;
}
} }
int input_mousebutton_state_get(int button, int state_type) int input_mousebutton_state_get(int button, int state_type)
{ {
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
int current_state = glfwGetMouseButton(window, button); int current_state = glfwGetMouseButton(window, button);
return current_state == state_type ? 1 : 0; if(state_type == GLFW_PRESS)
{
if(current_state == GLFW_PRESS || current_state == GLFW_REPEAT)
return 1;
else
return 0;
}
else
{
return state_type == current_state ? 1 : 0;
}
} }
void input_map_create(const char* name, int* keys, size_t num_keys) void input_map_create(const char* name, int* keys, size_t num_keys)
@ -206,3 +239,134 @@ static int map_find(const char* name)
} }
return index; return index;
} }
static const char* get_key_name(int key)
{
switch (key)
{
// Printable keys
case GLFW_KEY_A: return "A";
case GLFW_KEY_B: return "B";
case GLFW_KEY_C: return "C";
case GLFW_KEY_D: return "D";
case GLFW_KEY_E: return "E";
case GLFW_KEY_F: return "F";
case GLFW_KEY_G: return "G";
case GLFW_KEY_H: return "H";
case GLFW_KEY_I: return "I";
case GLFW_KEY_J: return "J";
case GLFW_KEY_K: return "K";
case GLFW_KEY_L: return "L";
case GLFW_KEY_M: return "M";
case GLFW_KEY_N: return "N";
case GLFW_KEY_O: return "O";
case GLFW_KEY_P: return "P";
case GLFW_KEY_Q: return "Q";
case GLFW_KEY_R: return "R";
case GLFW_KEY_S: return "S";
case GLFW_KEY_T: return "T";
case GLFW_KEY_U: return "U";
case GLFW_KEY_V: return "V";
case GLFW_KEY_W: return "W";
case GLFW_KEY_X: return "X";
case GLFW_KEY_Y: return "Y";
case GLFW_KEY_Z: return "Z";
case GLFW_KEY_1: return "1";
case GLFW_KEY_2: return "2";
case GLFW_KEY_3: return "3";
case GLFW_KEY_4: return "4";
case GLFW_KEY_5: return "5";
case GLFW_KEY_6: return "6";
case GLFW_KEY_7: return "7";
case GLFW_KEY_8: return "8";
case GLFW_KEY_9: return "9";
case GLFW_KEY_0: return "0";
case GLFW_KEY_SPACE: return "SPACE";
case GLFW_KEY_MINUS: return "MINUS";
case GLFW_KEY_EQUAL: return "EQUAL";
case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET";
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET";
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT";
case GLFW_KEY_COMMA: return "COMMA";
case GLFW_KEY_PERIOD: return "PERIOD";
case GLFW_KEY_SLASH: return "SLASH";
case GLFW_KEY_WORLD_1: return "WORLD 1";
case GLFW_KEY_WORLD_2: return "WORLD 2";
// Function keys
case GLFW_KEY_ESCAPE: return "ESCAPE";
case GLFW_KEY_F1: return "F1";
case GLFW_KEY_F2: return "F2";
case GLFW_KEY_F3: return "F3";
case GLFW_KEY_F4: return "F4";
case GLFW_KEY_F5: return "F5";
case GLFW_KEY_F6: return "F6";
case GLFW_KEY_F7: return "F7";
case GLFW_KEY_F8: return "F8";
case GLFW_KEY_F9: return "F9";
case GLFW_KEY_F10: return "F10";
case GLFW_KEY_F11: return "F11";
case GLFW_KEY_F12: return "F12";
case GLFW_KEY_F13: return "F13";
case GLFW_KEY_F14: return "F14";
case GLFW_KEY_F15: return "F15";
case GLFW_KEY_F16: return "F16";
case GLFW_KEY_F17: return "F17";
case GLFW_KEY_F18: return "F18";
case GLFW_KEY_F19: return "F19";
case GLFW_KEY_F20: return "F20";
case GLFW_KEY_F21: return "F21";
case GLFW_KEY_F22: return "F22";
case GLFW_KEY_F23: return "F23";
case GLFW_KEY_F24: return "F24";
case GLFW_KEY_F25: return "F25";
case GLFW_KEY_UP: return "UP";
case GLFW_KEY_DOWN: return "DOWN";
case GLFW_KEY_LEFT: return "LEFT";
case GLFW_KEY_RIGHT: return "RIGHT";
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
case GLFW_KEY_TAB: return "TAB";
case GLFW_KEY_ENTER: return "ENTER";
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
case GLFW_KEY_INSERT: return "INSERT";
case GLFW_KEY_DELETE: return "DELETE";
case GLFW_KEY_PAGE_UP: return "PAGE UP";
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
case GLFW_KEY_HOME: return "HOME";
case GLFW_KEY_END: return "END";
case GLFW_KEY_KP_0: return "KEYPAD 0";
case GLFW_KEY_KP_1: return "KEYPAD 1";
case GLFW_KEY_KP_2: return "KEYPAD 2";
case GLFW_KEY_KP_3: return "KEYPAD 3";
case GLFW_KEY_KP_4: return "KEYPAD 4";
case GLFW_KEY_KP_5: return "KEYPAD 5";
case GLFW_KEY_KP_6: return "KEYPAD 6";
case GLFW_KEY_KP_7: return "KEYPAD 7";
case GLFW_KEY_KP_8: return "KEYPAD 8";
case GLFW_KEY_KP_9: return "KEYPAD 9";
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTPLY";
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
case GLFW_KEY_PAUSE: return "PAUSE";
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU";
default: return "UNKNOWN";
}
}

@ -1,10 +1,13 @@
#ifndef linmath_H #ifndef LINMATH_H
#define linmath_H #define LINMATH_H
/* Credit : https://github.com/datenwolf/linmath.h */ /* Credit : https://github.com/datenwolf/linmath.h */
#include <math.h> #include <math.h>
#define M_PI 3.14159265358979323846
#define TO_RADIANS(degrees) ((degrees * M_PI) / 180.0)
#define LINMATH_H_DEFINE_VEC(n) \ #define LINMATH_H_DEFINE_VEC(n) \
typedef float vec##n[n]; \ typedef float vec##n[n]; \
static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \ static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
@ -79,7 +82,6 @@ static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
} }
typedef vec4 mat4[4]; typedef vec4 mat4[4];
static inline void mat4_identity(mat4 M) static inline void mat4_identity(mat4 M)
{ {
int i, j; int i, j;
@ -87,7 +89,6 @@ static inline void mat4_identity(mat4 M)
for(j=0; j<4; ++j) for(j=0; j<4; ++j)
M[i][j] = i==j ? 1.f : 0.f; M[i][j] = i==j ? 1.f : 0.f;
} }
static inline void mat4_dup(mat4 M, mat4 N) static inline void mat4_dup(mat4 M, mat4 N)
{ {
int i, j; int i, j;
@ -95,21 +96,18 @@ static inline void mat4_dup(mat4 M, mat4 N)
for(j=0; j<4; ++j) for(j=0; j<4; ++j)
M[i][j] = N[i][j]; M[i][j] = N[i][j];
} }
static inline void mat4_row(vec4 r, mat4 M, int i) static inline void mat4_row(vec4 r, mat4 M, int i)
{ {
int k; int k;
for(k=0; k<4; ++k) for(k=0; k<4; ++k)
r[k] = M[k][i]; r[k] = M[k][i];
} }
static inline void mat4_col(vec4 r, mat4 M, int i) static inline void mat4_col(vec4 r, mat4 M, int i)
{ {
int k; int k;
for(k=0; k<4; ++k) for(k=0; k<4; ++k)
r[k] = M[i][k]; r[k] = M[i][k];
} }
static inline void mat4_transpose(mat4 M, mat4 N) static inline void mat4_transpose(mat4 M, mat4 N)
{ {
int i, j; int i, j;
@ -117,28 +115,24 @@ static inline void mat4_transpose(mat4 M, mat4 N)
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
M[i][j] = N[j][i]; M[i][j] = N[j][i];
} }
static inline void mat4_add(mat4 M, mat4 a, mat4 b) static inline void mat4_add(mat4 M, mat4 a, mat4 b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]); vec4_add(M[i], a[i], b[i]);
} }
static inline void mat4_sub(mat4 M, mat4 a, mat4 b) static inline void mat4_sub(mat4 M, mat4 a, mat4 b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]); vec4_sub(M[i], a[i], b[i]);
} }
static inline void mat4_scale(mat4 M, mat4 a, float k) static inline void mat4_scale(mat4 M, mat4 a, float k)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k); vec4_scale(M[i], a[i], k);
} }
static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z) static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z)
{ {
int i; int i;
@ -149,7 +143,6 @@ static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z)
M[3][i] = a[3][i]; M[3][i] = a[3][i];
} }
} }
static inline void mat4_mul(mat4 M, mat4 a, mat4 b) static inline void mat4_mul(mat4 M, mat4 a, mat4 b)
{ {
mat4 temp; mat4 temp;
@ -161,7 +154,6 @@ static inline void mat4_mul(mat4 M, mat4 a, mat4 b)
} }
mat4_dup(M, temp); mat4_dup(M, temp);
} }
static inline void mat4_mul_vec4(vec4 r, mat4 M, vec4 v) static inline void mat4_mul_vec4(vec4 r, mat4 M, vec4 v)
{ {
int i, j; int i, j;
@ -171,7 +163,6 @@ static inline void mat4_mul_vec4(vec4 r, mat4 M, vec4 v)
r[j] += M[i][j] * v[i]; r[j] += M[i][j] * v[i];
} }
} }
static inline void mat4_translate(mat4 T, float x, float y, float z) static inline void mat4_translate(mat4 T, float x, float y, float z)
{ {
mat4_identity(T); mat4_identity(T);
@ -179,7 +170,6 @@ static inline void mat4_translate(mat4 T, float x, float y, float z)
T[3][1] = y; T[3][1] = y;
T[3][2] = z; T[3][2] = z;
} }
static inline void mat4_translate_in_place(mat4 M, float x, float y, float z) static inline void mat4_translate_in_place(mat4 M, float x, float y, float z)
{ {
vec4 t = {x, y, z, 0}; vec4 t = {x, y, z, 0};
@ -190,23 +180,23 @@ static inline void mat4_translate_in_place(mat4 M, float x, float y, float z)
M[3][i] += vec4_mul_inner(r, t); M[3][i] += vec4_mul_inner(r, t);
} }
} }
static inline void mat4_from_vec3_mul_outer(mat4 M, vec3 a, vec3 b) static inline void mat4_from_vec3_mul_outer(mat4 M, vec3 a, vec3 b)
{ {
int i, j; int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j) for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f; M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
} }
static inline void mat4_rotate(mat4 R, mat4 M, float x, float y, float z, float angle) static inline void mat4_rotate(mat4 R, mat4 M, float x, float y, float z, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
float c = cosf(angle); float c = cosf(angle);
vec3 u = {x, y, z}; vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) { if(vec3_len(u) > 1e-4) {
vec3_norm(u, u); vec3_norm(u, u);
mat4 T; mat4 T;
mat4_from_vec3_mul_outer(T, u, u); mat4_from_vec3_mul_outer(T, u, u);
mat4 S = { mat4 S = {
{ 0, u[2], -u[1], 0}, { 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0}, {-u[2], 0, u[0], 0},
@ -214,19 +204,22 @@ static inline void mat4_rotate(mat4 R, mat4 M, float x, float y, float z, float
{ 0, 0, 0, 0} { 0, 0, 0, 0}
}; };
mat4_scale(S, S, s); mat4_scale(S, S, s);
mat4 C; mat4 C;
mat4_identity(C); mat4_identity(C);
mat4_sub(C, C, T); mat4_sub(C, C, T);
mat4_scale(C, C, c); mat4_scale(C, C, c);
mat4_add(T, T, C); mat4_add(T, T, C);
mat4_add(T, T, S); mat4_add(T, T, S);
T[3][3] = 1.; T[3][3] = 1.;
mat4_mul(R, M, T); mat4_mul(R, M, T);
} else { } else {
mat4_dup(R, M); mat4_dup(R, M);
} }
} }
static inline void mat4_rotate_X(mat4 Q, mat4 M, float angle) static inline void mat4_rotate_X(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
@ -239,7 +232,6 @@ static inline void mat4_rotate_X(mat4 Q, mat4 M, float angle)
}; };
mat4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4_rotate_Y(mat4 Q, mat4 M, float angle) static inline void mat4_rotate_Y(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
@ -252,7 +244,6 @@ static inline void mat4_rotate_Y(mat4 Q, mat4 M, float angle)
}; };
mat4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4_rotate_Z(mat4 Q, mat4 M, float angle) static inline void mat4_rotate_Z(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
@ -265,7 +256,6 @@ static inline void mat4_rotate_Z(mat4 Q, mat4 M, float angle)
}; };
mat4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4_invert(mat4 T, mat4 M) static inline void mat4_invert(mat4 T, mat4 M)
{ {
float s[6]; float s[6];
@ -276,46 +266,55 @@ static inline void mat4_invert(mat4 T, mat4 M)
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2]; s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3]; s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3]; s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1]; c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2]; c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3]; c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2]; c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3]; c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3]; c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
/* Assumes it is invertible */
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] ); float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet; T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet; T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet; T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet; T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet; T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet; T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet; T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet; T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet; T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet; T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet; T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet; T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet; T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet; T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet; T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet; T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
} }
static inline void mat4_orthonormalize(mat4 R, mat4 M) static inline void mat4_orthonormalize(mat4 R, mat4 M)
{ {
mat4_dup(R, M); mat4_dup(R, M);
float s = 1.; float s = 1.;
vec3 h; vec3 h;
vec3_norm(R[2], R[2]); vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]); s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s); vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h); vec3_sub(R[1], R[1], h);
vec3_norm(R[2], R[2]); vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]); s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s); vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h); vec3_sub(R[1], R[1], h);
vec3_norm(R[1], R[1]); vec3_norm(R[1], R[1]);
s = vec3_mul_inner(R[0], R[1]); s = vec3_mul_inner(R[0], R[1]);
vec3_scale(h, R[1], s); vec3_scale(h, R[1], s);
vec3_sub(R[0], R[0], h); vec3_sub(R[0], R[0], h);
@ -326,109 +325,120 @@ static inline void mat4_frustum(mat4 M, float l, float r, float b, float t, floa
{ {
M[0][0] = 2.f*n/(r-l); M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f; M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.*n/(t-b); M[1][1] = 2.*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f; M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][0] = (r+l)/(r-l); M[2][0] = (r+l)/(r-l);
M[2][1] = (t+b)/(t-b); M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n); M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f; M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n); M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f; M[3][0] = M[3][1] = M[3][3] = 0.f;
} }
static inline void mat4_ortho(mat4 M, float l, float r, float b, float t, float n, float f) static inline void mat4_ortho(mat4 M, float l, float r, float b, float t, float n, float f)
{ {
M[0][0] = 2.f/(r-l); M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f; M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f/(t-b); M[1][1] = 2.f/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f; M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][2] = -2.f/(f-n); M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f; M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l); M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b); M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n); M[3][2] = -(f+n)/(f-n);
M[3][3] = 1.f; M[3][3] = 1.f;
} }
static inline void mat4_perspective(mat4 m, float y_fov, float aspect, float n, float f) static inline void mat4_perspective(mat4 m, float y_fov, float aspect, float n, float f)
{ {
/* NOTE: Degrees are an unhandy unit to work with. /* NOTE: Degrees are an unhandy unit to work with.
* linmath.h uses radians for everything! */ * linmath.h uses radians for everything! */
float const a = 1.f / tan(y_fov / 2.f); float const a = 1.f / tan(y_fov / 2.f);
m[0][0] = a / aspect; m[0][0] = a / aspect;
m[0][1] = 0.f; m[0][1] = 0.f;
m[0][2] = 0.f; m[0][2] = 0.f;
m[0][3] = 0.f; m[0][3] = 0.f;
m[1][0] = 0.f; m[1][0] = 0.f;
m[1][1] = a; m[1][1] = a;
m[1][2] = 0.f; m[1][2] = 0.f;
m[1][3] = 0.f; m[1][3] = 0.f;
m[2][0] = 0.f; m[2][0] = 0.f;
m[2][1] = 0.f; m[2][1] = 0.f;
m[2][2] = -((f + n) / (f - n)); m[2][2] = -((f + n) / (f - n));
m[2][3] = -1.f; m[2][3] = -1.f;
m[3][0] = 0.f; m[3][0] = 0.f;
m[3][1] = 0.f; m[3][1] = 0.f;
m[3][2] = -((2.f * f * n) / (f - n)); m[3][2] = -((2.f * f * n) / (f - n));
m[3][3] = 0.f; m[3][3] = 0.f;
} }
static inline void mat4_look_at(mat4 m, vec3 eye, vec3 center, vec3 up) static inline void mat4_look_at(mat4 m, vec3 eye, vec3 center, vec3 up)
{ {
/* Adapted from Android's OpenGL Matrix.java. */ /* Adapted from Android's OpenGL Matrix.java. */
/* See the OpenGL GLUT documentation for gluLookAt for a description */ /* See the OpenGL GLUT documentation for gluLookAt for a description */
/* of the algorithm. We implement it in a straightforward way: */ /* of the algorithm. We implement it in a straightforward way: */
/* TODO: The negation of of can be spared by swapping the order of
/* TODO: The negation of of can be spared by swapping the order of
* operands in the following cross products in the right way. */ * operands in the following cross products in the right way. */
vec3 f; vec3 f;
vec3_sub(f, center, eye); vec3_sub(f, center, eye);
vec3_norm(f, f); vec3_norm(f, f);
vec3 s; vec3 s;
vec3_mul_cross(s, f, up); vec3_mul_cross(s, f, up);
vec3_norm(s, s); vec3_norm(s, s);
vec3 t; vec3 t;
vec3_mul_cross(t, s, f); vec3_mul_cross(t, s, f);
m[0][0] = s[0]; m[0][0] = s[0];
m[0][1] = t[0]; m[0][1] = t[0];
m[0][2] = -f[0]; m[0][2] = -f[0];
m[0][3] = 0.f; m[0][3] = 0.f;
m[1][0] = s[1]; m[1][0] = s[1];
m[1][1] = t[1]; m[1][1] = t[1];
m[1][2] = -f[1]; m[1][2] = -f[1];
m[1][3] = 0.f; m[1][3] = 0.f;
m[2][0] = s[2]; m[2][0] = s[2];
m[2][1] = t[2]; m[2][1] = t[2];
m[2][2] = -f[2]; m[2][2] = -f[2];
m[2][3] = 0.f; m[2][3] = 0.f;
m[3][0] = 0.f; m[3][0] = 0.f;
m[3][1] = 0.f; m[3][1] = 0.f;
m[3][2] = 0.f; m[3][2] = 0.f;
m[3][3] = 1.f; m[3][3] = 1.f;
mat4_translate_in_place(m, -eye[0], -eye[1], -eye[2]); mat4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
} }
typedef float quat[4]; typedef float quat[4];
static inline void quat_identity(quat q) static inline void quat_identity(quat q)
{ {
q[0] = q[1] = q[2] = 0.f; q[0] = q[1] = q[2] = 0.f;
q[3] = 1.f; q[3] = 1.f;
} }
static inline void quat_add(quat r, quat a, quat b) static inline void quat_add(quat r, quat a, quat b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
r[i] = a[i] + b[i]; r[i] = a[i] + b[i];
} }
static inline void quat_sub(quat r, quat a, quat b) static inline void quat_sub(quat r, quat a, quat b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
r[i] = a[i] - b[i]; r[i] = a[i] - b[i];
} }
static inline void quat_mul(quat r, quat p, quat q) static inline void quat_mul(quat r, quat p, quat q)
{ {
vec3 w; vec3 w;
@ -439,14 +449,12 @@ static inline void quat_mul(quat r, quat p, quat q)
vec3_add(r, r, w); vec3_add(r, r, w);
r[3] = p[3]*q[3] - vec3_mul_inner(p, q); r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
} }
static inline void quat_scale(quat r, quat v, float s) static inline void quat_scale(quat r, quat v, float s)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
r[i] = v[i] * s; r[i] = v[i] * s;
} }
static inline float quat_inner_product(quat a, quat b) static inline float quat_inner_product(quat a, quat b)
{ {
float p = 0.f; float p = 0.f;
@ -455,7 +463,6 @@ static inline float quat_inner_product(quat a, quat b)
p += b[i]*a[i]; p += b[i]*a[i];
return p; return p;
} }
static inline void quat_conj(quat r, quat q) static inline void quat_conj(quat r, quat q)
{ {
int i; int i;
@ -463,7 +470,6 @@ static inline void quat_conj(quat r, quat q)
r[i] = -q[i]; r[i] = -q[i];
r[3] = q[3]; r[3] = q[3];
} }
static inline void quat_rotate(quat r, float angle, vec3 axis) { static inline void quat_rotate(quat r, float angle, vec3 axis) {
vec3 v; vec3 v;
vec3_scale(v, axis, sinf(angle / 2)); vec3_scale(v, axis, sinf(angle / 2));
@ -472,18 +478,26 @@ static inline void quat_rotate(quat r, float angle, vec3 axis) {
r[i] = v[i]; r[i] = v[i];
r[3] = cosf(angle / 2); r[3] = cosf(angle / 2);
} }
#define quat_norm vec4_norm #define quat_norm vec4_norm
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v) static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
{ {
quat v_ = {v[0], v[1], v[2], 0.f}; /*
quat_conj(r, q); * Method by Fabian 'ryg' Giessen (of Farbrausch)
quat_norm(r, r); t = 2 * cross(q.xyz, v)
quat_mul(r, v_, r); v' = v + q.w * t + cross(q.xyz, t)
quat_mul(r, q, r); */
} vec3 t = {q[0], q[1], q[2]};
vec3 u = {q[0], q[1], q[2]};
vec3_mul_cross(t, t, v);
vec3_scale(t, t, 2);
vec3_mul_cross(u, u, t);
vec3_scale(t, t, q[3]);
vec3_add(r, v, t);
vec3_add(r, r, u);
}
static inline void mat4_from_quat(mat4 M, quat q) static inline void mat4_from_quat(mat4 M, quat q)
{ {
float a = q[3]; float a = q[3];
@ -494,18 +508,22 @@ static inline void mat4_from_quat(mat4 M, quat q)
float b2 = b*b; float b2 = b*b;
float c2 = c*c; float c2 = c*c;
float d2 = d*d; float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2; M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d); M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c); M[0][2] = 2.f*(b*d - a*c);
M[0][3] = 0.f; M[0][3] = 0.f;
M[1][0] = 2*(b*c - a*d); M[1][0] = 2*(b*c - a*d);
M[1][1] = a2 - b2 + c2 - d2; M[1][1] = a2 - b2 + c2 - d2;
M[1][2] = 2.f*(c*d + a*b); M[1][2] = 2.f*(c*d + a*b);
M[1][3] = 0.f; M[1][3] = 0.f;
M[2][0] = 2.f*(b*d + a*c); M[2][0] = 2.f*(b*d + a*c);
M[2][1] = 2.f*(c*d - a*b); M[2][1] = 2.f*(c*d - a*b);
M[2][2] = a2 - b2 - c2 + d2; M[2][2] = a2 - b2 - c2 + d2;
M[2][3] = 0.f; M[2][3] = 0.f;
M[3][0] = M[3][1] = M[3][2] = 0.f; M[3][0] = M[3][1] = M[3][2] = 0.f;
M[3][3] = 1.f; M[3][3] = 1.f;
} }
@ -517,16 +535,18 @@ static inline void mat4o_mul_quat(mat4 R, mat4 M, quat q)
quat_mul_vec3(R[0], q, M[0]); quat_mul_vec3(R[0], q, M[0]);
quat_mul_vec3(R[1], q, M[1]); quat_mul_vec3(R[1], q, M[1]);
quat_mul_vec3(R[2], q, M[2]); quat_mul_vec3(R[2], q, M[2]);
R[3][0] = R[3][1] = R[3][2] = 0.f; R[3][0] = R[3][1] = R[3][2] = 0.f;
R[3][3] = 1.f; R[3][3] = 1.f;
} }
static inline void quat_from_mat4(quat q, mat4 M) static inline void quat_from_mat4(quat q, mat4 M)
{ {
float r=0.f; float r=0.f;
int i; int i;
int perm[] = { 0, 1, 2, 0, 1 }; int perm[] = { 0, 1, 2, 0, 1 };
int *p = perm; int *p = perm;
for(i = 0; i<3; i++) { for(i = 0; i<3; i++) {
float m = M[i][i]; float m = M[i][i];
if( m < r ) if( m < r )
@ -534,12 +554,15 @@ static inline void quat_from_mat4(quat q, mat4 M)
m = r; m = r;
p = &perm[i]; p = &perm[i];
} }
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] ); r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
if(r < 1e-6) { if(r < 1e-6) {
q[0] = 1.f; q[0] = 1.f;
q[1] = q[2] = q[3] = 0.f; q[1] = q[2] = q[3] = 0.f;
return; return;
} }
q[0] = r/2.f; q[0] = r/2.f;
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r); q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r); q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);

@ -0,0 +1,107 @@
#include "model.h"
#include "array.h"
#include "log.h"
#include "geometry.h"
#include "camera.h"
#include "entity.h"
#include "shader.h"
#include "transform.h"
#include <assert.h>
static struct Model* model_list;
static int* empty_indices;
struct Model* model_get(int index)
{
struct Model* model = NULL;
if(index > -1 && index < array_len(model_list))
model = &model_list[index];
else
log_error("model:get", "Invalid index");
return model;
}
void model_init(void)
{
model_list = array_new(struct Model);
empty_indices = array_new(int);
}
int model_create(int node, const char* geo_name)
{
assert(geo_name);
int geo_index = geom_create(geo_name);
int index = -1;
struct Model* new_model = NULL;
if(geo_index > -1)
{
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_model = &model_list[index];
}
else
{
new_model = array_grow(model_list, struct Model);
index = array_len(model_list) - 1;
}
new_model->node = node;
new_model->geometry_index = geo_index;
new_model->shader = 0; /* Temporary, for test run only till materials are added */
}
else
{
log_error("model:create", "Geometry '%s' not found.", geo_name);
}
return index;
}
void model_remove(int index)
{
if(index > -1 && index < array_len(model_list))
{
struct Model* model = &model_list[index];
model->node = -1;
geom_remove(model->geometry_index);
model->geometry_index = -1;
model->shader = -1;
array_push(empty_indices, index, int);
}
else
{
log_error("model:remove", "Invalid index");
}
}
void model_cleanup(void)
{
for(int i = 0; i < array_len(model_list); i++)
{
if(model_list[i].node != -1)
model_remove(i);
}
array_free(model_list);
array_free(empty_indices);
}
void model_render_all(struct Camera* camera)
{
mat4 mvp;
for(int i = 0; i < array_len(model_list); i++)
{
struct Model* model = &model_list[i];
struct Entity* entity = entity_get(model->node);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
mat4_identity(mvp);
shader_bind(model->shader);
mat4_mul(mvp, camera->view_proj_mat, transform->trans_mat);
shader_set_uniform_mat4(model->shader, "mvp", mvp);
vec4 color = {1, 0, 0, 1};
shader_set_uniform_vec4(model->shader, "color", color);
geom_render(model->geometry_index);
shader_unbind();
}
}

@ -0,0 +1,20 @@
#ifndef model_H
#define model_H
struct Camera;
struct Model
{
int node;
int geometry_index;
int shader; /* Temporary, replace with material */
};
struct Model* model_get(int index);
void model_init(void);
int model_create(int node, const char* geo_name);
void model_remove(int index);
void model_cleanup(void);
void model_render_all(struct Camera* camera);
#endif

@ -2,6 +2,8 @@
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "log.h" #include "log.h"
#include "camera.h"
#include "model.h"
void on_framebuffer_size_change(GLFWwindow* window, int width, int height); void on_framebuffer_size_change(GLFWwindow* window, int width, int height);
@ -14,6 +16,9 @@ void renderer_init(GLFWwindow* window)
void renderer_draw(void) void renderer_draw(void)
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Hard coded version */
struct Camera* camera = camera_get(0);
model_render_all(camera);
} }
void renderer_cleanup(void) void renderer_cleanup(void)

@ -235,7 +235,7 @@ void shader_unbind(void)
glUseProgram(0); glUseProgram(0);
} }
int get_uniform_location(const int shader_index, const char* name) int shader_get_uniform_location(const int shader_index, const char* name)
{ {
GLint handle = glGetUniformLocation(shader_list[shader_index].program, name); GLint handle = glGetUniformLocation(shader_list[shader_index].program, name);
if(handle == -1) if(handle == -1)
@ -244,44 +244,44 @@ int get_uniform_location(const int shader_index, const char* name)
return handle; return handle;
} }
void set_uniform_int(const int shader_index, const char* name, const int value) void shader_set_uniform_int(const int shader_index, const char* name, const int value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniform1i(location, value); glUniform1i(location, value);
} }
void set_uniform_float(const int shader_index, const char* name, const float value) void shader_set_uniform_float(const int shader_index, const char* name, const float value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniform1f(location, value); glUniform1f(location, value);
} }
void set_uniform_vec2(const int shader_index, const char* name, const vec2 value) void shader_set_uniform_vec2(const int shader_index, const char* name, const vec2 value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniform2fv(location, 1, value); glUniform2fv(location, 1, value);
} }
void set_uniform_vec3(const int shader_index, const char* name, const vec3 value) void shader_set_uniform_vec3(const int shader_index, const char* name, const vec3 value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniform3fv(location, 1, value); glUniform3fv(location, 1, value);
} }
void set_uniform_vec4(const int shader_index, const char* name, const vec4 value) void shader_set_uniform_vec4(const int shader_index, const char* name, const vec4 value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniform4fv(location, 1, value); glUniform4fv(location, 1, value);
} }
void setUniformMat4(const int shader_index, const char* name, const mat4 value) void shader_set_uniform_mat4(const int shader_index, const char* name, const mat4 value)
{ {
GLint location = get_uniform_location(shader_index, name); GLint location = shader_get_uniform_location(shader_index, name);
if(location >= 0) if(location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, *value); glUniformMatrix4fv(location, 1, GL_FALSE, *value);
} }

@ -1,9 +1,10 @@
#include "transform.h" #include "transform.h"
#include "array.h" #include "array.h"
#include "entity.h"
#include <assert.h> #include <assert.h>
struct Transform* transform_list; static struct Transform* transform_list;
int* empty_indices; static int* empty_indices;
void transform_init(void) void transform_init(void)
{ {
@ -75,10 +76,16 @@ void transform_scale(struct Transform* transform, vec3 scale)
void transform_get_forward(struct Transform* transform, vec3 res) void transform_get_forward(struct Transform* transform, vec3 res)
{ {
res[0] = 0; res[1] = 0; res[2] = 1; res[0] = 0; res[1] = 0; res[2] = -1;
quat_mul_vec3(res, transform->rotation, res); quat_mul_vec3(res, transform->rotation, res);
} }
void transform_get_lookat(struct Transform* transform, vec3 res)
{
transform_get_forward(transform, res);
vec3_add(res, transform->position, res);
}
void transform_get_up(struct Transform* transform, vec3 res) void transform_get_up(struct Transform* transform, vec3 res)
{ {
res[0] = 0; res[1] = 1; res[2] = 0; res[0] = 0; res[1] = 1; res[2] = 0;
@ -95,12 +102,18 @@ void transform_get_right(struct Transform* transform, vec3 res)
void transform_update_transmat(struct Transform* transform) void transform_update_transmat(struct Transform* transform)
{ {
mat4 scale, rot, tran; mat4 scale, rot, tran;
mat4_identity(scale);
mat4_identity(rot);
mat4_identity(tran);
mat4_identity(transform->trans_mat);
mat4_scale_aniso(scale, scale, transform->scale[0], transform->scale[1], transform->scale[2]); mat4_scale_aniso(scale, scale, transform->scale[0], transform->scale[1], transform->scale[2]);
mat4_from_quat(rot, transform->rotation); mat4_from_quat(rot, transform->rotation);
mat4_translate(tran, transform->position[0], transform->position[1], transform->position[2]); mat4_translate(tran, transform->position[0], transform->position[1], transform->position[2]);
mat4_mul(transform->trans_mat, transform->trans_mat, scale); mat4_mul(transform->trans_mat, transform->trans_mat, scale);
mat4_mul(transform->trans_mat, transform->trans_mat, rot); mat4_mul(transform->trans_mat, transform->trans_mat, rot);
mat4_mul(transform->trans_mat, transform->trans_mat, tran); mat4_mul(transform->trans_mat, transform->trans_mat, tran);
struct Entity* entity = entity_get(transform->node);
entity_sync_components(entity);
} }
struct Transform* transform_get(int index) struct Transform* transform_get(int index)

@ -26,6 +26,7 @@ void transform_rotate(struct Transform* transform,
enum Transform_Space space); enum Transform_Space space);
void transform_scale(struct Transform* transform, vec3 scale); void transform_scale(struct Transform* transform, vec3 scale);
void transform_get_forward(struct Transform* transform, vec3 res); void transform_get_forward(struct Transform* transform, vec3 res);
void transform_get_lookat(struct Transform* transform, vec3 res);
void transform_get_up(struct Transform* transform, vec3 res); void transform_get_up(struct Transform* transform, vec3 res);
void transform_get_right(struct Transform* transform, vec3 res); void transform_get_right(struct Transform* transform, vec3 res);
void transform_update_transmat(struct Transform* transform); void transform_update_transmat(struct Transform* transform);

@ -29,7 +29,7 @@ int window_init(const char* title, int width, int height)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_FOCUSED, GL_TRUE); glfwWindowHint(GLFW_FOCUSED, GL_TRUE);
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
active_window = glfwCreateWindow(width, height, title, NULL, NULL); active_window = glfwCreateWindow(width, height, title, NULL, NULL);
if(!active_window) if(!active_window)
{ {

Loading…
Cancel
Save