From c97dbf5777c955127aacf906cfe8ba5179351173 Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Sat, 5 Sep 2015 23:24:29 +0500 Subject: [PATCH] Started adding heirarchical transformations --- src/camera.c | 10 ++-- src/entity.c | 13 +++++- src/entity.h | 4 +- src/game.c | 117 +++++++++++++++++++++++++++++++---------------- src/linmath.h | 4 +- src/model.c | 2 +- src/scene.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ src/scene.h | 16 +++++++ src/transform.c | 64 +++++++++++++++++++++++--- src/transform.h | 2 + 10 files changed, 294 insertions(+), 57 deletions(-) create mode 100644 src/scene.c create mode 100644 src/scene.h diff --git a/src/camera.c b/src/camera.c index 37c5dd4..bc17e0a 100644 --- a/src/camera.c +++ b/src/camera.c @@ -56,7 +56,8 @@ int camera_create(int node, int width, int height) 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); + float aspect_ratio = (float)width / (float)height; + new_camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; new_camera->ortho = 0; mat4_identity(new_camera->view_mat); mat4_identity(new_camera->proj_mat); @@ -76,10 +77,11 @@ 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); + vec3 lookat = {0.f}, up = {0.f}, position = {0.f}; + transform_get_absolute_lookat(transform, lookat); transform_get_up(transform, up); - mat4_look_at(camera->view_mat, transform->position, lookat, up); + transform_get_absolute_pos(transform, position); + mat4_look_at(camera->view_mat, position, lookat, up); camera_update_view_proj(camera); } diff --git a/src/entity.c b/src/entity.c index d6a754e..ca3d814 100644 --- a/src/entity.c +++ b/src/entity.c @@ -46,6 +46,8 @@ void entity_remove(int index) } } entity->node = -1; + entity->parent = -1; + array_free(entity->children); free(entity->name); free(entity->tag); entity->name = entity->tag = NULL; @@ -76,6 +78,8 @@ 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; + new_entity->parent = -1; + new_entity->children = array_new(int); for(int i = 0; i < MAX_COMPONENTS; i++) new_entity->components[i] = -1; new_entity->components[C_TRANSFORM] = transform_create(new_entity->node); @@ -88,8 +92,8 @@ struct Entity* entity_get(int index) struct Entity* entity = NULL; if(index >= 0 && index < array_len(entity_list)) entity = &entity_list[index]; - else - log_error("entity:get", "Invalid index '%d'", index); + /* else */ + /* log_error("entity:get", "Invalid index '%d'", index); */ return entity; } @@ -224,3 +228,8 @@ void entity_sync_components(struct Entity* entity) camera_update_view(camera); } } + +struct Entity* entity_get_all(void) +{ + return entity_list; +} diff --git a/src/entity.h b/src/entity.h index 42803f8..06b66e2 100644 --- a/src/entity.h +++ b/src/entity.h @@ -2,7 +2,6 @@ #define entity_H #include "components.h" -#include "num_types.h" struct Entity { @@ -10,6 +9,8 @@ struct Entity char* name; char* tag; int components[MAX_COMPONENTS]; + int parent; + int* children; }; void entity_init(void); @@ -18,6 +19,7 @@ void entity_remove(int index); struct Entity* entity_create(const char* name, const char* tag); struct Entity* entity_get(int index); struct Entity* entity_find(const char* name); +struct Entity* entity_get_all(void); 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, ...); diff --git a/src/game.c b/src/game.c index 8ac0b40..f975e30 100644 --- a/src/game.c +++ b/src/game.c @@ -16,14 +16,15 @@ #include "transform.h" #include "camera.h" #include "model.h" +#include "scene.h" void run(void); void update(float dt); void render(void); void debug(float dt); -struct Entity* entity = NULL; -struct Camera* active_camera = NULL; +int player_node = -1; +int player_pitch_node = -1; void game_init(void) { @@ -35,21 +36,26 @@ void game_init(void) shader_init(); transform_init(); camera_init(); - entity_init(); geom_init(); model_init(); + entity_init(); + scene_init(); - int up_keys[2] = {'W', GLFW_KEY_UP}; - int down_keys[2] = {'S', GLFW_KEY_DOWN}; + int forward_keys[2] = {'W', GLFW_KEY_UP}; + int backward_keys[2] = {'S', GLFW_KEY_DOWN}; + int up_keys[2] = {'Q'}; + int down_keys[2] = {'E'}; int left_keys[2] = {'A', GLFW_KEY_LEFT}; int right_keys[2] = {'D', GLFW_KEY_RIGHT}; int turn_right_keys[1] = {'L'}; int turn_left_keys[1] = {'J'}; int turn_up_keys[1] = {'I'}; int turn_down_keys[1] = {'K'}; - input_map_create("Move_Up", up_keys, 2); - input_map_create("Move_Down", down_keys, 2); + input_map_create("Move_Forward", forward_keys, 2); + input_map_create("Move_Backward", backward_keys, 2); + input_map_create("Move_Up", up_keys, 1); + input_map_create("Move_Down", down_keys, 1); input_map_create("Move_Left", left_keys, 2); input_map_create("Move_Right", right_keys, 2); input_map_create("Turn_Right", turn_right_keys, 1); @@ -58,24 +64,27 @@ void game_init(void) input_map_create("Turn_Down", turn_down_keys, 1); 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* player = scene_add_new("player", "None"); + player_node = player->node; vec3 viewer_pos = {0, 0, 10}; - struct Transform* viewer_tran = entity_component_get(entity, C_TRANSFORM); + struct Transform* viewer_tran = entity_component_get(player, C_TRANSFORM); transform_set_position(viewer_tran, viewer_pos); + struct Entity* player_pitch = scene_add_as_child("player_pitch", NULL, player); + player_pitch_node = player_pitch->node; + entity_component_add(player_pitch, C_CAMERA, 800, 600); - struct Entity* new_ent = entity_create("Model_Entity", NULL); + struct Entity* new_ent = scene_add_new("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"); struct Transform* model_tran = entity_component_get(new_ent, C_TRANSFORM); - vec3 axis = {0.f, 1.f, 0.f}; + //vec3 axis = {0.f, 1.f, 0.f}; //transform_rotate(model_tran, axis, (45.f), TS_WORLD); vec3 scale = {1, 1, 5}; transform_scale(model_tran, scale); - struct Entity* suz = entity_create("Suzanne", NULL); + struct Entity* suz = scene_add_as_child("Suzanne", NULL, new_ent); entity_component_add(suz, C_MODEL, "suzanne.pamesh"); struct Transform* s_tran = entity_component_get(suz, C_TRANSFORM); vec3 s_pos = {3, 0, 0}; @@ -91,14 +100,17 @@ void game_init(void) void debug(float dt) { + struct Entity* entity = entity_get(player_node); + struct Entity* entity_pitch = entity_get(player_pitch_node); struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + struct Transform* pitch_transform = entity_component_get(entity_pitch, C_TRANSFORM); float move_speed = 5.f, turn_speed = 50.f; vec3 offset = {0, 0, 0}; float turn_up_down = 0.f; float turn_left_right = 0.f; float max_up_down = 60.f; static float total_up_down_rot = 0.f; - vec3 rot_axis_up_down = {-1, 0, 0}; + vec3 rot_axis_up_down = {1, 0, 0}; vec3 rot_axis_left_right = {0, 1, 0}; /* Look around */ @@ -107,49 +119,73 @@ void debug(float dt) if(input_map_state_get("Turn_Right", GLFW_PRESS)) turn_left_right += turn_speed; if(input_map_state_get("Turn_Left", GLFW_PRESS)) turn_left_right -= turn_speed; - if(turn_up_down != 0.f) + turn_up_down *= dt; + turn_left_right *= dt; + total_up_down_rot += turn_up_down; + if(total_up_down_rot >= max_up_down) { - total_up_down_rot += turn_up_down; - if(total_up_down_rot >= max_up_down) - { - total_up_down_rot = max_up_down; - turn_left_right = 0.f; - } - else if(total_up_down_rot <= -max_up_down) - { - total_up_down_rot = -max_up_down; - turn_left_right = 0.f; - } - - if(turn_up_down != 0.f) - transform_rotate(transform, rot_axis_up_down, turn_up_down * dt, TS_LOCAL); + total_up_down_rot = max_up_down; + turn_up_down = 0.f; } - + else if(total_up_down_rot <= -max_up_down) + { + total_up_down_rot = -max_up_down; + turn_up_down = 0.f; + } + if(turn_left_right != 0.f) - transform_rotate(transform, rot_axis_left_right, turn_left_right * dt, TS_WORLD); + { + transform_rotate(transform, rot_axis_left_right, -turn_left_right, TS_WORLD); + vec3 up = {0.f}; + vec3 forward = {0.f}; + transform_get_up(transform, up); + transform_get_forward(transform, forward); + //log_message("Up : %.3f, %.3f, %.3f", up[0], up[1], up[2]); + log_message("Forward : %.3f, %.3f, %.3f", forward[0], forward[1], forward[2]); + } + if(turn_up_down != 0.f) + { + transform_rotate(pitch_transform, rot_axis_up_down, -turn_up_down, TS_LOCAL); + vec3 up = {0.f}; + vec3 forward = {0.f}; + transform_get_up(transform, up); + transform_get_forward(transform, forward); + //log_message("Up : %.3f, %.3f, %.3f", up[0], up[1], up[2]); + log_message("Forward : %.3f, %.3f, %.3f", forward[0], forward[1], forward[2]); + } /* Movement */ - if(input_map_state_get("Move_Up", GLFW_PRESS)) offset[2] -= move_speed; - if(input_map_state_get("Move_Down", GLFW_PRESS)) offset[2] += move_speed; + if(input_map_state_get("Move_Forward", GLFW_PRESS)) offset[2] -= move_speed; + if(input_map_state_get("Move_Backward", GLFW_PRESS)) offset[2] += move_speed; if(input_map_state_get("Move_Left", GLFW_PRESS)) offset[0] -= move_speed; if(input_map_state_get("Move_Right", GLFW_PRESS)) offset[0] += move_speed; + if(input_map_state_get("Move_Up", GLFW_PRESS)) offset[1] += move_speed; + if(input_map_state_get("Move_Down", GLFW_PRESS)) offset[1] -= move_speed; vec3_scale(offset, offset, dt); - if(offset[0] != 0 || offset[2] != 0) + if(offset[0] != 0 || offset[2] != 0 || offset[1] != 0) { transform_translate(transform, offset, TS_LOCAL); - 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]); */ } if(input_key_state_get(GLFW_KEY_SPACE, GLFW_PRESS)) { - struct Entity* model = entity_get(1); + struct Entity* model = entity_get(3); + struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM); + vec3 x_axis = {1, 0, 0}; + transform_rotate(mod_tran, x_axis, 25.f * dt, TS_WORLD); + } + + if(input_key_state_get(GLFW_KEY_M, GLFW_PRESS)) + { + struct Entity* model = entity_get(3); struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM); vec3 y_axis = {0, 1, 0}; - transform_rotate(mod_tran, y_axis, 25.f * dt, TS_WORLD); + transform_rotate(mod_tran, y_axis, 25.f * dt, TS_LOCAL); } } @@ -185,6 +221,7 @@ void render(void) void game_cleanup(void) { + scene_cleanup(); entity_cleanup(); model_cleanup(); geom_cleanup(); diff --git a/src/linmath.h b/src/linmath.h index b4b7424..bd7a163 100644 --- a/src/linmath.h +++ b/src/linmath.h @@ -396,7 +396,7 @@ static inline void mat4_perspective(mat4 m, float y_fov, float aspect, float n, 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) +static inline void mat4_look_at(mat4 m, vec3 eye, vec3 lookat, vec3 up) { /* Adapted from Android's OpenGL Matrix.java. */ /* See the OpenGL GLUT documentation for gluLookAt for a description */ @@ -405,7 +405,7 @@ static inline void mat4_look_at(mat4 m, vec3 eye, vec3 center, vec3 up) /* 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_sub(f, lookat, eye); vec3_norm(f, f); vec3 s; diff --git a/src/model.c b/src/model.c index ee049df..5bd4411 100644 --- a/src/model.c +++ b/src/model.c @@ -99,7 +99,7 @@ void model_render_all(struct Camera* camera) 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}; + vec4 color = {0.7f, 0.7f, 0.5f, 1}; shader_set_uniform_vec4(model->shader, "color", color); geom_render(model->geometry_index); shader_unbind(); diff --git a/src/scene.c b/src/scene.c new file mode 100644 index 0000000..2abf59e --- /dev/null +++ b/src/scene.c @@ -0,0 +1,119 @@ +#include "scene.h" +#include "array.h" +#include "entity.h" +#include "log.h" +#include "transform.h" + +#include +#include + +static int root_node = -1; + +void scene_init(void) +{ + /* Add root node to scene */ + struct Entity* root = entity_create("ROOT", NULL); + root_node = root->node; +} + +struct Entity* scene_add_new(const char* name, const char* tag) +{ + return scene_add_as_child(name, tag, scene_get_root()); +} + +struct Entity* scene_add_as_child(const char* name, const char* tag, struct Entity* parent) +{ + assert(parent); + struct Entity* new_entity = NULL; + new_entity = entity_create(name, tag); + new_entity->parent = parent->node; + array_push(parent->children, new_entity->node, int); + struct Transform* new_ent_tran = entity_component_get(new_entity, C_TRANSFORM); + transform_update_transmat(new_ent_tran); + return new_entity; +} + +void scene_remove(struct Entity* entity) +{ + assert(entity); + for(int i = 0; i < array_len(entity->children); i++) + { + struct Entity* child = entity_get(entity->children[i]); + scene_remove(child); + } + entity_remove(entity->node); +} + +void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) +{ + assert(entity && new_parent); + struct Entity* curr_parent = entity_get(entity->parent); + if(curr_parent) + { + /* find the index that the entity is at in the cuurent parent's + children array and remove it from there. Then set the new_parent + as the entity's parent */ + int index = -1; + for(int i = 0; i < array_len(curr_parent->children); i++) + { + if(curr_parent->children[i] == entity->node) + { + index = i; + break; + } + } + + if(index > -1) + { + array_remove_at(curr_parent->children, index); + entity->parent = new_parent->node; + array_push(new_parent, entity->node, int); + struct Transform* entity_tran = entity_component_get(entity, C_TRANSFORM); + transform_update_transmat(entity_tran); + } + else + { + log_error("scene:reset_parent", "Entity %s not found in it's parent '%s''s children array"); + } + } + else + { + log_error("scene:reset_parent", "Cannot change parent of ROOT entity"); + } +} + +void scene_cleanup(void) +{ + struct Entity* entity_list = entity_get_all(); + for(int i = 0; i < array_len(entity_list); i++) + { + if(entity_list[i].node != -1) + entity_remove(i); + } +} + +struct Entity* scene_find(const char* name) +{ + return entity_find(name); +} + +struct Entity* scene_get_root(void) +{ + return entity_get(root_node); +} + +struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name) +{ + assert(parent); + struct Entity* child = NULL; + for(int i = 0; i < array_len(parent->children); i++) + { + struct Entity* curr_child = entity_get(parent->children[i]); + if(strcmp(curr_child->name, name) == 0) + { + child = curr_child; + break; + } + } + return child; +} diff --git a/src/scene.h b/src/scene.h new file mode 100644 index 0000000..3ea5bf0 --- /dev/null +++ b/src/scene.h @@ -0,0 +1,16 @@ +#ifndef scene_H +#define scene_H + +struct Entity; + +void scene_init(void); +void scene_remove(struct Entity* entity); +void scene_reset_parent(struct Entity* entity, struct Entity* new_parent); +void scene_cleanup(void); +struct Entity* scene_add_new(const char* name, const char* tag); /* Add as child of Root */ +struct Entity* scene_add_as_child(const char* name, const char* tag, struct Entity* parent); +struct Entity* scene_find(const char* name); +struct Entity* scene_get_root(void); +struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); + +#endif diff --git a/src/transform.c b/src/transform.c index 4f8afa5..e6f9a1e 100644 --- a/src/transform.c +++ b/src/transform.c @@ -59,13 +59,24 @@ void transform_rotate(struct Transform* transform, { mat4 new_rot; mat4_identity(new_rot); - mat4_rotate(new_rot, new_rot, axis[0], axis[1], axis[2], TO_RADIANS(angle)); + //mat4_rotate(new_rot, new_rot, axis[0], axis[1], axis[2], TO_RADIANS(angle)); + + if(axis[0] == 1) + mat4_rotate_X(new_rot, new_rot, TO_RADIANS(angle)); + if(axis[1] == 1) + mat4_rotate_Y(new_rot, new_rot, TO_RADIANS(angle)); + if(axis[2] == 1) + mat4_rotate_Z(new_rot, new_rot, TO_RADIANS(angle)); + //mat4_orthonormalize(new_rot, new_rot); + //mat4_orthonormalize(new_rot, temp); if(space == TS_LOCAL) mat4_mul(transform->rotation, transform->rotation, new_rot); else if(space == TS_WORLD) mat4_mul(transform->rotation, new_rot, transform->rotation); + //mat4_orthonormalize(transform->rotation, transform->rotation); transform_update_transmat(transform); } + void transform_scale(struct Transform* transform, vec3 scale) { transform->scale[0] = scale[0]; @@ -77,7 +88,7 @@ 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; - mat4_mul_vec3(res, transform->rotation, res); + mat4_mul_vec3(res, transform->trans_mat, res); } void transform_get_lookat(struct Transform* transform, vec3 res) @@ -86,6 +97,14 @@ void transform_get_lookat(struct Transform* transform, vec3 res) vec3_add(res, transform->position, res); } +void transform_get_absolute_lookat(struct Transform* transform, vec3 res) +{ + vec3 abs_position = {0.f}; + transform_get_absolute_pos(transform, abs_position); + transform_get_forward(transform, res); + vec3_add(res, abs_position, res); +} + void transform_get_up(struct Transform* transform, vec3 res) { res[0] = 0; res[1] = 1; res[2] = 0; @@ -101,18 +120,37 @@ void transform_get_right(struct Transform* transform, vec3 res) void transform_update_transmat(struct Transform* transform) { - static mat4 scale, tran; + static mat4 scale, translation; mat4_identity(scale); - mat4_identity(tran); + mat4_identity(translation); mat4_identity(transform->trans_mat); mat4_scale_aniso(scale, scale, transform->scale[0], transform->scale[1], transform->scale[2]); - mat4_translate(tran, transform->position[0], transform->position[1], transform->position[2]); - - mat4_mul(transform->trans_mat, transform->trans_mat, tran); + mat4_translate(translation, transform->position[0], transform->position[1], transform->position[2]); + + mat4_mul(transform->trans_mat, transform->trans_mat, translation); mat4_mul(transform->trans_mat, transform->trans_mat, transform->rotation); mat4_mul(transform->trans_mat, transform->trans_mat, scale); struct Entity* entity = entity_get(transform->node); + struct Entity* parent = entity_get(entity->parent); + if(parent) + { + struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); + mat4_mul(transform->trans_mat, transform->trans_mat, parent_tran->trans_mat); + //mat4_mul(transform->trans_mat, parent_tran->trans_mat, transform->trans_mat); + } + + /* Update all children */ + if(array_len(entity->children) > 0) + { + for(int i = 0; i < array_len(entity->children); i++) + { + struct Entity* child = entity_get(entity->children[i]); + struct Transform* child_tran = entity_component_get(child, C_TRANSFORM); + transform_update_transmat(child_tran); + } + } + entity_sync_components(entity); } @@ -135,3 +173,15 @@ void transform_set_position(struct Transform* transform, vec3 new_position) transform->position[i] = new_position[i]; transform_update_transmat(transform); } + +void transform_get_absolute_pos(struct Transform* transform, vec3 res) +{ + struct Entity* entity = entity_get(transform->node); + struct Entity* parent = entity_get(entity->parent); + if(parent) + { + struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); + transform_get_absolute_pos(parent_tran, res); + } + vec3_add(res, res, transform->position); +} diff --git a/src/transform.h b/src/transform.h index 8af6794..558cbbd 100644 --- a/src/transform.h +++ b/src/transform.h @@ -31,5 +31,7 @@ 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); +void transform_get_absolute_pos(struct Transform* transform, vec3 res); +void transform_get_absolute_lookat(struct Transform* transform, vec3 res); #endif