From 1b649feadc1b567956335fc009ada90f00b1832c Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Wed, 19 Aug 2015 13:33:23 +0500 Subject: [PATCH] Added camera and model. Made several modifications and fixes throughout the code --- orgfile.org | 8 +- src/camera.c | 98 +++++++++++++++++++++++ src/camera.h | 29 +++++++ src/components.h | 14 ++++ src/entity.c | 127 ++++++++++++++++++++--------- src/entity.h | 5 +- src/file_io.c | 2 +- src/game.c | 49 ++++++++---- src/geometry.c | 42 +++++++--- src/geometry.h | 3 +- src/input.c | 174 ++++++++++++++++++++++++++++++++++++++-- src/linmath.h | 191 +++++++++++++++++++++++++------------------- src/model.c | 107 +++++++++++++++++++++++++ src/model.h | 20 +++++ src/renderer.c | 5 ++ src/shader.c | 26 +++--- src/transform.c | 19 ++++- src/transform.h | 1 + src/window_system.c | 2 +- 19 files changed, 748 insertions(+), 174 deletions(-) create mode 100644 src/camera.c create mode 100644 src/camera.h create mode 100644 src/model.c create mode 100644 src/model.h diff --git a/orgfile.org b/orgfile.org index be0aa7b..b4bbf0e 100644 --- a/orgfile.org +++ b/orgfile.org @@ -34,10 +34,14 @@ while using as few libraries as possible. - 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. - State "DONE" from "TODO" [2015-08-02 Sun 19:09] +** TODO Fix readme markdown +** TODO Framebuffer and resolution independent rendering ** TODO Entity ** TODO Positive and negative values for input_maps and returning corresponding values when they are true -** TODO Camera -** TODO Test render +** DONE Camera +- 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 Materials ** TODO Mesh/Model diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..fdaf370 --- /dev/null +++ b/src/camera.c @@ -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); +} diff --git a/src/camera.h b/src/camera.h new file mode 100644 index 0000000..72d56a5 --- /dev/null +++ b/src/camera.h @@ -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 diff --git a/src/components.h b/src/components.h index 1a94366..2c3d4b0 100644 --- a/src/components.h +++ b/src/components.h @@ -10,4 +10,18 @@ enum Component 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 diff --git a/src/entity.c b/src/entity.c index 78cabaa..d6a754e 100644 --- a/src/entity.c +++ b/src/entity.c @@ -3,15 +3,17 @@ #include "log.h" #include "string_utils.h" #include "transform.h" +#include "camera.h" +#include "model.h" #include #include #include +#include static struct Entity* entity_list; static int* empty_indices; - void entity_init(void) { entity_list = array_new(struct Entity); @@ -33,20 +35,15 @@ void entity_remove(int index) 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; - case C_MODEL: - break; - case C_RIGIDBODY: - break; - case C_CAMERA: - break; - default: - /* Only called for MAX_COMPONENTS, do nothing */ - break; + transform_remove(entity->components[i]); + entity->components[i] = -1; + } + else + { + entity_component_remove(entity, i); } - entity->components[i] = -1; } entity->node = -1; free(entity->name); @@ -79,8 +76,10 @@ struct Entity* entity_create(const char* name, const char* tag) new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME"); new_entity->tag = tag ? str_new(tag) : str_new("DEFAULT_TAG"); 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); - + return new_entity; } @@ -111,67 +110,117 @@ struct Entity* entity_find(const char* name) } return entity; } + int entity_component_remove(struct Entity* entity, enum Component component) { int success = 1; assert(entity); - switch(component) + int comp_index = entity->components[component]; + switch(component) { - case C_TRANSFORM: - log_error("entity:remove", "Cannot remove Tranform component"); - success = 0; - break; - case C_MODEL: - break; + case C_TRANSFORM: log_error("entity:remove_component", "Cannot remove TRANSFORM"); break; + case C_MODEL: if(comp_index != -1) model_remove(comp_index); break; + case C_CAMERA: if(comp_index != -1) camera_remove(comp_index); break; case C_RIGIDBODY: break; - case C_CAMERA: - break; default: - log_error("entity:component_remove", "Invalid component type"); + /* Only called for MAX_COMPONENTS, do nothing */ break; } + entity->components[component] = -1; if(success) entity->components[component] = -1; return success; } + void* entity_component_get(struct Entity* entity, enum Component component) { void* comp_obj = NULL; assert(entity); - switch(component) + int comp_index = entity->components[component]; + if(comp_index != -1) { - case C_TRANSFORM: comp_obj = transform_get(entity->components[C_TRANSFORM]); break; - case C_MODEL: - break; - case C_RIGIDBODY: - break; - case C_CAMERA: - break; - default: - log_error("entity:component_get", "Invalid component type"); - break; + switch(component) + { + case C_TRANSFORM: comp_obj = transform_get(comp_index); break; + case C_MODEL: comp_obj = model_get(comp_index); break; + case C_CAMERA: comp_obj = camera_get(comp_index); break; + case C_RIGIDBODY: + break; + default: log_error("entity:component_get", "Invalid component type"); break; + } + } + else + { + log_error("entity:component_get", "Entity '%s' does not have component %s", + entity->name, + comp_to_str(component)); } 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; assert(entity); + va_list args; + va_start(args, component); + int new_comp_index = -1; switch(component) { case C_TRANSFORM: log_error("entity:add_component", "Entity already has Transform component"); case C_MODEL: - break; - case C_RIGIDBODY: - break; + { + const char* filename = va_arg(args, const char*); + new_comp_index = model_create(entity->node, filename); + new_comp = model_get(new_comp_index); + } + break; 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; default: log_error("entity:component_add", "Invalid component type"); 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; } + +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); + } +} diff --git a/src/entity.h b/src/entity.h index 6c21889..42803f8 100644 --- a/src/entity.h +++ b/src/entity.h @@ -20,7 +20,8 @@ struct Entity* entity_get(int index); struct Entity* entity_find(const char* name); int entity_component_remove(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 diff --git a/src/file_io.c b/src/file_io.c index c81784b..f0b0673 100644 --- a/src/file_io.c +++ b/src/file_io.c @@ -70,6 +70,6 @@ FILE* io_file_open(const char* path, const char* mode) char* relative_path = str_new(base_assets_path); relative_path = str_concat(relative_path, path); 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; } diff --git a/src/game.c b/src/game.c index 02d2e5a..e407015 100644 --- a/src/game.c +++ b/src/game.c @@ -15,6 +15,7 @@ #include "array.h" #include "transform.h" #include "camera.h" +#include "model.h" void run(void); void update(float dt); @@ -22,6 +23,7 @@ void render(void); void debug(float dt); struct Entity* entity = NULL; +struct Camera* active_camera = NULL; void game_init(void) { @@ -35,19 +37,26 @@ void game_init(void) camera_init(); entity_init(); geom_init(); + model_init(); - int keys[2] = {'W', GLFW_KEY_UP}; - int keys2[2] = {'S', GLFW_KEY_DOWN}; - int keys3[1] = {'J'}; - int keys4[1] = {'K'}; - input_map_create("MoveUp", keys, 2); - input_map_create("MoveDown", keys2, 2); - input_map_create("Test", keys3, 1); - input_map_create("Test2", keys4, 1); + int up_keys[2] = {'W', GLFW_KEY_UP}; + int down_keys[2] = {'S', GLFW_KEY_DOWN}; + int left_keys[2] = {'A', GLFW_KEY_LEFT}; + int right_keys[2] = {'D', GLFW_KEY_RIGHT}; + input_map_create("Move_Up", up_keys, 2); + input_map_create("Move_Down", down_keys, 2); + input_map_create("Move_Left", left_keys, 2); + 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"); + 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(); } @@ -55,10 +64,22 @@ void game_init(void) void debug(float dt) { 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); - transform_translate(transform, offset, TS_WORLD); - log_message("Position : %.3f, %.3f, %.3f", transform->position[0], transform->position[1], transform->position[2]); + if(offset[0] != 0 || offset[2] != 0) + { + transform_translate(transform, offset, TS_WORLD); + log_message("Position : %.3f, %.3f, %.3f", + transform->position[0], + transform->position[1], + transform->position[2]); + } } void run(void) @@ -83,8 +104,7 @@ void update(float dt) if(input_key_state_get(GLFW_KEY_ESCAPE, GLFW_PRESS)) window_set_should_close(1); - if(input_map_state_get("MoveUp", GLFW_PRESS)) - debug(dt); + debug(dt); } void render(void) @@ -95,6 +115,7 @@ void render(void) void game_cleanup(void) { entity_cleanup(); + model_cleanup(); geom_cleanup(); transform_cleanup(); camera_cleanup(); diff --git a/src/geometry.c b/src/geometry.c index a4858ff..c88f17c 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -25,7 +25,7 @@ struct Geometry uint normal_vbo; uint color_vbo; uint index_vbo; - uint ref_count; + int ref_count; vec3* vertices; vec3* vertex_colors; vec3* normals; @@ -73,7 +73,6 @@ int geom_create(const char* name) { /* add new geometry object or overwrite existing one */ struct Geometry* new_geo = NULL; - int index = -1; int empty_len = array_len(empty_indices); if(empty_len > 0) { @@ -112,13 +111,20 @@ void geom_remove(int index) if(index >= 0 && index < array_len(geometry_list)) { struct Geometry* geometry = &geometry_list[index]; - array_free(geometry->indices); - array_free(geometry->vertices); - array_free(geometry->uvs); - array_free(geometry->normals); - array_free(geometry->vertex_colors); - free(geometry->filename); - array_push(empty_indices, index, int); + if(geometry->ref_count >= 0) + { + geometry->ref_count--; + if(geometry->ref_count < 0) + { + array_free(geometry->indices); + array_free(geometry->vertices); + array_free(geometry->uvs); + array_free(geometry->normals); + array_free(geometry->vertex_colors); + free(geometry->filename); + array_push(empty_indices, index, int); + } + } } } @@ -161,15 +167,21 @@ int load_from_file(struct Geometry* geometry, const char* filename) // Indices geometry->indices = array_new_cap(uint, indices_count); fread(geometry->indices, INDEX_SIZE, indices_count, file); + array_match_len_cap(geometry->indices); // Vertices geometry->vertices = array_new_cap(vec3, vertices_count); fread(geometry->vertices, VEC3_SIZE, vertices_count, file); + array_match_len_cap(geometry->vertices); // Normals geometry->normals = array_new_cap(vec3, normals_count); fread(geometry->normals, VEC3_SIZE, normals_count, file); + array_match_len_cap(geometry->normals); // Uvs geometry->uvs = array_new_cap(vec2, uvs_count); fread(geometry->uvs, VEC2_SIZE, uvs_count, file); + array_match_len_cap(geometry->uvs); + + geometry->vertex_colors = array_new(vec3); } fclose(file); geometry->filename = str_new(filename); @@ -251,3 +263,15 @@ void create_vao(struct Geometry* geometry) } 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); + +} diff --git a/src/geometry.h b/src/geometry.h index 53275ed..4256c1b 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -2,9 +2,10 @@ #define geometry_H void geom_init(void); -int geom_ceate(const char* name); +int geom_create(const char* name); int geom_find(const char* filename); void geom_remove(int index); void geom_cleanup(void); +void geom_render(int index); #endif diff --git a/src/input.c b/src/input.c index 337cef4..905d6f0 100644 --- a/src/input.c +++ b/src/input.c @@ -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_cursor_move(GLFWwindow* window, double xpos, double ypos); static int map_find(const char* name); +static const char* get_key_name(int key); static struct Input_Map* input_map_list; @@ -30,7 +31,8 @@ void input_init(GLFWwindow* window) glfwSetMouseButtonCallback(window, input_on_mousebutton); glfwSetKeyCallback(window, input_on_key); glfwSetCursorPosCallback(window, input_on_cursor_move); - + //glfwSetInputMode(window, GLFW_STICKY_KEYS, 1); + 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]; for(int j = 0; j < array_len(map->keys); j++) { - if(map->keys[i] == key) + if(map->keys[j] == key) { map->state = action; break; @@ -103,21 +105,52 @@ int input_map_state_get(const char* map_name, int state) break; } } - return state == current_state ? 1 : 0; + + 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; + } } int input_key_state_get(int key, int state_type) { GLFWwindow* window = window_get_active(); 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) { GLFWwindow* window = window_get_active(); 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) @@ -206,3 +239,134 @@ static int map_find(const char* name) } 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"; + } +} diff --git a/src/linmath.h b/src/linmath.h index 66ee5ae..c7ba05d 100644 --- a/src/linmath.h +++ b/src/linmath.h @@ -1,10 +1,13 @@ -#ifndef linmath_H -#define linmath_H +#ifndef LINMATH_H +#define LINMATH_H /* Credit : https://github.com/datenwolf/linmath.h */ #include +#define M_PI 3.14159265358979323846 +#define TO_RADIANS(degrees) ((degrees * M_PI) / 180.0) + #define LINMATH_H_DEFINE_VEC(n) \ typedef float vec##n[n]; \ static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \ @@ -56,7 +59,7 @@ static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b) static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n) { - float p = 2.f*vec3_mul_inner(v, n); + float p = 2.f*vec3_mul_inner(v, n); int i; for(i=0;i<3;++i) r[i] = v[i] - p*n[i]; @@ -72,14 +75,13 @@ static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b) static inline void vec4_reflect(vec4 r, vec4 v, vec4 n) { - float p = 2.f*vec4_mul_inner(v, n); + float p = 2.f*vec4_mul_inner(v, n); int i; for(i=0;i<4;++i) r[i] = v[i] - p*n[i]; } typedef vec4 mat4[4]; - static inline void mat4_identity(mat4 M) { int i, j; @@ -87,7 +89,6 @@ static inline void mat4_identity(mat4 M) for(j=0; j<4; ++j) M[i][j] = i==j ? 1.f : 0.f; } - static inline void mat4_dup(mat4 M, mat4 N) { int i, j; @@ -95,21 +96,18 @@ static inline void mat4_dup(mat4 M, mat4 N) for(j=0; j<4; ++j) M[i][j] = N[i][j]; } - static inline void mat4_row(vec4 r, mat4 M, int i) { int k; for(k=0; k<4; ++k) r[k] = M[k][i]; } - static inline void mat4_col(vec4 r, mat4 M, int i) { int k; for(k=0; k<4; ++k) r[k] = M[i][k]; } - static inline void mat4_transpose(mat4 M, mat4 N) { int i, j; @@ -117,28 +115,24 @@ static inline void mat4_transpose(mat4 M, mat4 N) for(i=0; i<4; ++i) M[i][j] = N[j][i]; } - static inline void mat4_add(mat4 M, mat4 a, mat4 b) { int i; for(i=0; i<4; ++i) vec4_add(M[i], a[i], b[i]); } - static inline void mat4_sub(mat4 M, mat4 a, mat4 b) { int i; for(i=0; i<4; ++i) vec4_sub(M[i], a[i], b[i]); } - static inline void mat4_scale(mat4 M, mat4 a, float k) { int i; for(i=0; i<4; ++i) vec4_scale(M[i], a[i], k); } - static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z) { int i; @@ -149,19 +143,17 @@ static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z) M[3][i] = a[3][i]; } } - static inline void mat4_mul(mat4 M, mat4 a, mat4 b) { mat4 temp; int k, r, c; for(c=0; c<4; ++c) for(r=0; r<4; ++r) { - temp[c][r] = 0.f; - for(k=0; k<4; ++k) - temp[c][r] += a[k][r] * b[c][k]; - } + temp[c][r] = 0.f; + for(k=0; k<4; ++k) + temp[c][r] += a[k][r] * b[c][k]; + } mat4_dup(M, temp); } - static inline void mat4_mul_vec4(vec4 r, mat4 M, vec4 v) { 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]; } } - static inline void mat4_translate(mat4 T, float x, float y, float z) { 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][2] = z; } - static inline void mat4_translate_in_place(mat4 M, float x, float y, float z) { vec4 t = {x, y, z, 0}; @@ -190,82 +180,82 @@ static inline void mat4_translate_in_place(mat4 M, float x, float y, float z) M[3][i] += vec4_mul_inner(r, t); } } - static inline void mat4_from_vec3_mul_outer(mat4 M, vec3 a, vec3 b) { int i, 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) { float s = sinf(angle); float c = cosf(angle); vec3 u = {x, y, z}; + if(vec3_len(u) > 1e-4) { vec3_norm(u, u); mat4 T; mat4_from_vec3_mul_outer(T, u, u); + mat4 S = { - { 0, u[2], -u[1], 0}, - {-u[2], 0, u[0], 0}, - { u[1], -u[0], 0, 0}, - { 0, 0, 0, 0} + { 0, u[2], -u[1], 0}, + {-u[2], 0, u[0], 0}, + { u[1], -u[0], 0, 0}, + { 0, 0, 0, 0} }; mat4_scale(S, S, s); + mat4 C; mat4_identity(C); mat4_sub(C, C, T); + mat4_scale(C, C, c); + mat4_add(T, T, C); mat4_add(T, T, S); - T[3][3] = 1.; + + T[3][3] = 1.; mat4_mul(R, M, T); } else { mat4_dup(R, M); } } - static inline void mat4_rotate_X(mat4 Q, mat4 M, float angle) { float s = sinf(angle); float c = cosf(angle); mat4 R = { {1.f, 0.f, 0.f, 0.f}, - {0.f, c, s, 0.f}, - {0.f, -s, c, 0.f}, + {0.f, c, s, 0.f}, + {0.f, -s, c, 0.f}, {0.f, 0.f, 0.f, 1.f} }; mat4_mul(Q, M, R); } - static inline void mat4_rotate_Y(mat4 Q, mat4 M, float angle) { float s = sinf(angle); float c = cosf(angle); mat4 R = { - { c, 0.f, s, 0.f}, + { c, 0.f, s, 0.f}, { 0.f, 1.f, 0.f, 0.f}, - { -s, 0.f, c, 0.f}, + { -s, 0.f, c, 0.f}, { 0.f, 0.f, 0.f, 1.f} }; mat4_mul(Q, M, R); } - static inline void mat4_rotate_Z(mat4 Q, mat4 M, float angle) { float s = sinf(angle); float c = cosf(angle); mat4 R = { - { c, s, 0.f, 0.f}, - { -s, c, 0.f, 0.f}, + { c, s, 0.f, 0.f}, + { -s, c, 0.f, 0.f}, { 0.f, 0.f, 1.f, 0.f}, { 0.f, 0.f, 0.f, 1.f} }; mat4_mul(Q, M, R); } - static inline void mat4_invert(mat4 T, mat4 M) { 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[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]; + 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[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[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]; -/* 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] ); + 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][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[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][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[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][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[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][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; } - static inline void mat4_orthonormalize(mat4 R, mat4 M) { mat4_dup(R, M); float s = 1.; vec3 h; + vec3_norm(R[2], R[2]); + s = vec3_mul_inner(R[1], R[2]); vec3_scale(h, R[2], s); vec3_sub(R[1], R[1], h); vec3_norm(R[2], R[2]); + s = vec3_mul_inner(R[1], R[2]); vec3_scale(h, R[2], s); vec3_sub(R[1], R[1], h); vec3_norm(R[1], R[1]); + s = vec3_mul_inner(R[0], R[1]); vec3_scale(h, R[1], s); 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][1] = M[0][2] = M[0][3] = 0.f; + M[1][1] = 2.*n/(t-b); M[1][0] = M[1][2] = M[1][3] = 0.f; + M[2][0] = (r+l)/(r-l); M[2][1] = (t+b)/(t-b); M[2][2] = -(f+n)/(f-n); M[2][3] = -1.f; + M[3][2] = -2.f*(f*n)/(f-n); 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) { M[0][0] = 2.f/(r-l); M[0][1] = M[0][2] = M[0][3] = 0.f; + M[1][1] = 2.f/(t-b); M[1][0] = M[1][2] = M[1][3] = 0.f; + M[2][2] = -2.f/(f-n); M[2][0] = M[2][1] = M[2][3] = 0.f; + M[3][0] = -(r+l)/(r-l); M[3][1] = -(t+b)/(t-b); M[3][2] = -(f+n)/(f-n); M[3][3] = 1.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. - * linmath.h uses radians for everything! */ + /* NOTE: Degrees are an unhandy unit to work with. + * linmath.h uses radians for everything! */ float const a = 1.f / tan(y_fov / 2.f); + m[0][0] = a / aspect; m[0][1] = 0.f; m[0][2] = 0.f; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = a; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = -((f + n) / (f - n)); m[2][3] = -1.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = -((2.f * f * n) / (f - n)); m[3][3] = 0.f; } - static inline void mat4_look_at(mat4 m, vec3 eye, vec3 center, vec3 up) { -/* Adapted from Android's OpenGL Matrix.java. */ -/* See the OpenGL GLUT documentation for gluLookAt for a description */ -/* of the algorithm. We implement it in a straightforward way: */ -/* TODO: The negation of of can be spared by swapping the order of - * operands in the following cross products in the right way. */ + /* Adapted from Android's OpenGL Matrix.java. */ + /* See the OpenGL GLUT documentation for gluLookAt for a description */ + /* of the algorithm. We implement it in a straightforward way: */ + + /* TODO: The negation of of can be spared by swapping the order of + * operands in the following cross products in the right way. */ vec3 f; - vec3_sub(f, center, eye); - vec3_norm(f, f); + vec3_sub(f, center, eye); + vec3_norm(f, f); + vec3 s; vec3_mul_cross(s, f, up); vec3_norm(s, s); + vec3 t; vec3_mul_cross(t, s, f); - m[0][0] = s[0]; - m[0][1] = t[0]; + + m[0][0] = s[0]; + m[0][1] = t[0]; m[0][2] = -f[0]; - m[0][3] = 0.f; - m[1][0] = s[1]; - m[1][1] = t[1]; + m[0][3] = 0.f; + + m[1][0] = s[1]; + m[1][1] = t[1]; m[1][2] = -f[1]; - m[1][3] = 0.f; - m[2][0] = s[2]; - m[2][1] = t[2]; + m[1][3] = 0.f; + + m[2][0] = s[2]; + m[2][1] = t[2]; m[2][2] = -f[2]; - m[2][3] = 0.f; - m[3][0] = 0.f; - m[3][1] = 0.f; - m[3][2] = 0.f; - m[3][3] = 1.f; + m[2][3] = 0.f; + + m[3][0] = 0.f; + m[3][1] = 0.f; + m[3][2] = 0.f; + m[3][3] = 1.f; + mat4_translate_in_place(m, -eye[0], -eye[1], -eye[2]); } typedef float quat[4]; - static inline void quat_identity(quat q) { q[0] = q[1] = q[2] = 0.f; q[3] = 1.f; } - static inline void quat_add(quat r, quat a, quat b) { int i; for(i=0; i<4; ++i) r[i] = a[i] + b[i]; } - static inline void quat_sub(quat r, quat a, quat b) { int i; for(i=0; i<4; ++i) r[i] = a[i] - b[i]; } - static inline void quat_mul(quat r, quat p, quat q) { vec3 w; @@ -439,14 +449,12 @@ static inline void quat_mul(quat r, quat p, quat q) vec3_add(r, r, w); r[3] = p[3]*q[3] - vec3_mul_inner(p, q); } - static inline void quat_scale(quat r, quat v, float s) { int i; for(i=0; i<4; ++i) r[i] = v[i] * s; } - static inline float quat_inner_product(quat a, quat b) { float p = 0.f; @@ -455,7 +463,6 @@ static inline float quat_inner_product(quat a, quat b) p += b[i]*a[i]; return p; } - static inline void quat_conj(quat r, quat q) { int i; @@ -463,7 +470,6 @@ static inline void quat_conj(quat r, quat q) r[i] = -q[i]; r[3] = q[3]; } - static inline void quat_rotate(quat r, float angle, vec3 axis) { vec3 v; 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[3] = cosf(angle / 2); } - #define quat_norm vec4_norm - 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); - quat_norm(r, r); - quat_mul(r, v_, r); - quat_mul(r, q, r); -} +/* + * Method by Fabian 'ryg' Giessen (of Farbrausch) +t = 2 * cross(q.xyz, v) +v' = v + q.w * t + cross(q.xyz, t) + */ + 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) { float a = q[3]; @@ -494,39 +508,45 @@ static inline void mat4_from_quat(mat4 M, quat q) float b2 = b*b; float c2 = c*c; float d2 = d*d; + M[0][0] = a2 + b2 - c2 - d2; M[0][1] = 2.f*(b*c + a*d); M[0][2] = 2.f*(b*d - a*c); M[0][3] = 0.f; + M[1][0] = 2*(b*c - a*d); M[1][1] = a2 - b2 + c2 - d2; M[1][2] = 2.f*(c*d + a*b); M[1][3] = 0.f; + M[2][0] = 2.f*(b*d + a*c); M[2][1] = 2.f*(c*d - a*b); M[2][2] = a2 - b2 - c2 + d2; M[2][3] = 0.f; + M[3][0] = M[3][1] = M[3][2] = 0.f; M[3][3] = 1.f; } static inline void mat4o_mul_quat(mat4 R, mat4 M, quat q) { -/* XXX: The way this is written only works for othogonal matrices. */ +/* XXX: The way this is written only works for othogonal matrices. */ /* TODO: Take care of non-orthogonal case. */ quat_mul_vec3(R[0], q, M[0]); quat_mul_vec3(R[1], q, M[1]); quat_mul_vec3(R[2], q, M[2]); + R[3][0] = R[3][1] = R[3][2] = 0.f; R[3][3] = 1.f; } - static inline void quat_from_mat4(quat q, mat4 M) { float r=0.f; int i; + int perm[] = { 0, 1, 2, 0, 1 }; int *p = perm; + for(i = 0; i<3; i++) { float m = M[i][i]; if( m < r ) @@ -534,12 +554,15 @@ static inline void quat_from_mat4(quat q, mat4 M) m = r; p = &perm[i]; } + r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] ); + if(r < 1e-6) { q[0] = 1.f; q[1] = q[2] = q[3] = 0.f; return; } + q[0] = r/2.f; 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); diff --git a/src/model.c b/src/model.c new file mode 100644 index 0000000..ee049df --- /dev/null +++ b/src/model.c @@ -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 + +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(); + } +} diff --git a/src/model.h b/src/model.h new file mode 100644 index 0000000..87f73b8 --- /dev/null +++ b/src/model.h @@ -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 diff --git a/src/renderer.c b/src/renderer.c index 8b696de..e717e86 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -2,6 +2,8 @@ #include "GLFW/glfw3.h" #include "log.h" +#include "camera.h" +#include "model.h" void on_framebuffer_size_change(GLFWwindow* window, int width, int height); @@ -14,6 +16,9 @@ void renderer_init(GLFWwindow* window) void renderer_draw(void) { 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) diff --git a/src/shader.c b/src/shader.c index 7099093..04e4bd0 100644 --- a/src/shader.c +++ b/src/shader.c @@ -235,7 +235,7 @@ void shader_unbind(void) 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); if(handle == -1) @@ -244,44 +244,44 @@ int get_uniform_location(const int shader_index, const char* name) 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) 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) 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) 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) 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) 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) glUniformMatrix4fv(location, 1, GL_FALSE, *value); } diff --git a/src/transform.c b/src/transform.c index 0f8c3de..36ee50b 100644 --- a/src/transform.c +++ b/src/transform.c @@ -1,9 +1,10 @@ #include "transform.h" #include "array.h" +#include "entity.h" #include -struct Transform* transform_list; -int* empty_indices; +static struct Transform* transform_list; +static int* empty_indices; 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) { - 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); } +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) { 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) { 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_from_quat(rot, transform->rotation); 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, rot); 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) diff --git a/src/transform.h b/src/transform.h index 76ea47f..e0d7b4f 100644 --- a/src/transform.h +++ b/src/transform.h @@ -26,6 +26,7 @@ void transform_rotate(struct Transform* transform, enum Transform_Space space); void transform_scale(struct Transform* transform, vec3 scale); 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_right(struct Transform* transform, vec3 res); void transform_update_transmat(struct Transform* transform); diff --git a/src/window_system.c b/src/window_system.c index 0b06fb3..a1076d5 100644 --- a/src/window_system.c +++ b/src/window_system.c @@ -29,7 +29,7 @@ int window_init(const char* title, int width, int height) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 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); if(!active_window) {