diff --git a/orgfile.org b/orgfile.org index afcfd47..88a052b 100644 --- a/orgfile.org +++ b/orgfile.org @@ -56,6 +56,50 @@ Sprint: Left Shift *** Level/Scene *** Materials *** Mesh/Geometry +** Notes on entity Systems +- Fat entites with all related properties, i.e. position, mesh etc in them. Easy to serialize, memory friendly, simple to implement + but would require significant changes to the current codebase. e.g. + struct Entity + { + int type; + char* name; + struct Transform {....}; + struct Camera {....}; + + // Separate properties unique to entity types by using unions + struct Renderable + { + struct Model {....}; + union + { + struct Player + { + int score; + int bullets; + }; + + struct Enemy + { + int target; + }; + } + } + }; +- Change component implementation by using anonymous unions to simulate interfaces. e.g + struct Component + { + int type; + union + { + struct Transform {....}; + struct Model {....}; + struct Camera {....}; + } + } +- Use handles for assets +- Use something similar to Variant to use as entity, not sure what or how +- Don't forget to think of the actual use-case and usage when coming up with a solution, don't build castles in the air! + * Things TODO ** DONE Input - State "DONE" from "TODO" [2015-07-02 Thu 01:24] @@ -161,7 +205,11 @@ x Font atlas proper cleanup - Decoupled event handling of gui and input if possible - Custom rendering for gui ** TODO Allow passsing base path as commandline argument? -** TODO Show SDL dialogbox if we cannot launch at all? +** TODO Remove components and switch to "Fat Entities" i.e. one entity struct contains all combinations +** TODO Use variants for material params +** TODO In second refactor pass, use entities everywhere, no need to pass in transform and model separately for example since they're both part of the same entity anyway +** DONE Show SDL dialogbox if we cannot launch at all? +- State "DONE" from "TODO" [2017-05-26 Fri 00:41] ** DONE Writing back to config file - State "DONE" from "TODO" [2017-05-08 Mon 00:57] ** DONE Reading from config file @@ -191,7 +239,8 @@ x Font atlas proper cleanup ** TODO Ray picking ** TODO Remove reduntant "settings" structures and move all configuration stuff to config variables ** TODO Shadow maps -** TODO Log output to file on every run +** DONE Log output to file on every run +- State "DONE" from "TODO" [2017-05-26 Fri 00:41] ** TODO Print processor stats and machine capabilites RAM etc on every run to log. ** TODO Milestone: Pong! - In order to put things into perspective and get a feel for what really needs to be prioritized, a very small but actual game release is necessary. @@ -201,17 +250,19 @@ x Font atlas proper cleanup ? Game .so with init, update and cleanup functions x Configuration files and "cvars" load/reload x Keybindings in config -- Log output on every run. +x Log output on every run. - Implement entity load/save to file ? Prefab load/save to file ** TODO Do input maps really need to be queried by their string names? ** TODO Reloading all the things! (textures/shaders/models/settings/entities etc) ** TODO Separate Debug/Editor camera from the active camera in the scene that can be switched to at any time +** TODO Make logging to file and console toggleable at complie-time or run-time ** DONE Add option to specify where to read/write files from instead of being hard-coded assets dir - State "DONE" from "TODO" [2017-05-24 Wed 17:12] ** TODO Add default keybindings ** TODO Write default config/keybindings etc to file if none are found in preferences dir ** TODO Fix input map bugs +** TODO Flatpak packaging for linux releases ** TODO Use hashmap for debugvar slots in editor ** TODO Use hashmap to store input maps ** DONE Live data views in editor diff --git a/src/bounding_volumes.c b/src/bounding_volumes.c index 0bdff6c..c686fb1 100644 --- a/src/bounding_volumes.c +++ b/src/bounding_volumes.c @@ -1,4 +1,5 @@ #include "bounding_volumes.h" +#include "entity.h" #include "transform.h" #include diff --git a/src/camera.c b/src/camera.c index 1cb27fd..b56637c 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,6 +1,7 @@ #include "camera.h" #include "entity.h" #include "transform.h" +#include "entity.h" #include "array.h" #include "framebuffer.h" #include "texture.h" @@ -15,92 +16,45 @@ #include #include -static struct Camera* camera_list; -static int* empty_indices; -static int primary_camera_index; - static void update_frustum(struct Camera* camera); -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) +void camera_destroy(struct Camera* camera) { - camera_list = array_new(struct Camera); - empty_indices = array_new(int); - primary_camera_index = -1; -} - -void camera_remove(int index) -{ - if(index > -1 && index < array_len(camera_list)) - { - struct Camera* camera = &camera_list[index]; - if(camera->fbo != -1) framebuffer_remove(camera->fbo); - if(camera->render_tex != -1) texture_remove(camera->render_tex); - if(camera->depth_tex != -1) texture_remove(camera->depth_tex); - camera->fbo = camera->render_tex = camera->depth_tex = camera->node = -1; - camera->ortho = camera->resizeable = 0; - camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f; - mat4_identity(&camera->view_mat); - mat4_identity(&camera->proj_mat); - mat4_identity(&camera->view_proj_mat); - for(int i = 0; i < FP_NUM_PLANES; i++) - vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); - vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0); - array_push(empty_indices, index, int); - } -} - -void camera_cleanup(void) -{ - for(int i = 0; i < array_len(camera_list); i++) - if(camera_list[i].node != -1) camera_remove(i); - array_free(camera_list); - array_free(empty_indices); + assert(camera); + if(camera->fbo != -1) framebuffer_remove(camera->fbo); + if(camera->render_tex != -1) texture_remove(camera->render_tex); + if(camera->depth_tex != -1) texture_remove(camera->depth_tex); + camera->fbo = camera->render_tex = camera->depth_tex = -1; + camera->ortho = camera->resizeable = false; + camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f; + mat4_identity(&camera->view_mat); + mat4_identity(&camera->proj_mat); + mat4_identity(&camera->view_proj_mat); + for(int i = 0; i < FP_NUM_PLANES; i++) + vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); + vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0); } -int camera_create(int node, int width, int height) +void camera_create(struct Camera* camera, struct Transform* transform, 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->fbo = -1; - new_camera->render_tex = -1; - new_camera->depth_tex = -1; - new_camera->node = node; - new_camera->farz = 1000.f; - new_camera->nearz = 0.1f; - new_camera->fov = 60.f; - new_camera->ortho = 0; - new_camera->resizeable = 1; + camera->fbo = -1; + camera->render_tex = -1; + camera->depth_tex = -1; + camera->farz = 1000.f; + camera->nearz = 0.1f; + camera->fov = 60.f; + camera->ortho = 0; + camera->resizeable = 1; float aspect_ratio = (float)width / (float)height; - new_camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; - mat4_identity(&new_camera->view_mat); - mat4_identity(&new_camera->proj_mat); - mat4_identity(&new_camera->view_proj_mat); + camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; + mat4_identity(&camera->view_mat); + mat4_identity(&camera->proj_mat); + mat4_identity(&camera->view_proj_mat); for(int i = 0; i < FP_NUM_PLANES; i++) - vec4_fill(&new_camera->frustum[i], 0.f, 0.f, 0.f, 0.f); - camera_update_view(new_camera); - camera_update_proj(new_camera); - vec4_fill(&new_camera->clear_color, 1.f, 1.f, 1.f, 1.f); - return index; + vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); + camera_update_view(camera, transform); + camera_update_proj(camera); + vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f); } void camera_update_view_proj(struct Camera* camera) @@ -110,10 +64,8 @@ void camera_update_view_proj(struct Camera* camera) update_frustum(camera); } -void camera_update_view(struct Camera* camera) +void camera_update_view(struct Camera* camera, struct Transform* transform) { - struct Entity* entity = entity_get(camera->node); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); vec3 lookat = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f}; @@ -157,11 +109,9 @@ void camera_attach_fbo(struct Camera* camera, camera->fbo = framebuffer_create(width, height, has_depth, 0, resizeable); if(camera->fbo > -1) { - char tex_name[128]; if(has_color) { - snprintf(tex_name, 128, "cam_render_tex_%d", camera->node); - camera->render_tex = texture_create(tex_name, + camera->render_tex = texture_create(NULL, TU_DIFFUSE, width, height, GL_RGBA, @@ -175,12 +125,9 @@ void camera_attach_fbo(struct Camera* camera, framebuffer_set_texture(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0); } - memset(tex_name, '\0', 128); - if(has_depth) { - snprintf(tex_name, 128, "cam_depth_tex_%d", camera->node); - camera->depth_tex = texture_create(tex_name, + camera->depth_tex = texture_create(NULL, TU_SHADOWMAP1, width, height, GL_DEPTH_COMPONENT, @@ -202,41 +149,6 @@ void camera_attach_fbo(struct Camera* camera, } } -struct Camera* camera_get_all(void) -{ - return camera_list; -} - -void camera_set_primary_viewer(struct Camera* camera) -{ - assert(camera); - if(camera->node == -1) - { - log_error("camera:set_primary_viewer", "Invalid camera!"); - } - else - { - /* locate the index of this camera */ - for(int i = 0; i < array_len(camera_list); i++) - { - if(camera_list[i].node == camera->node) - { - primary_camera_index = i; - break; - } - - } - } -} - -struct Camera* camera_get_primary(void) -{ - struct Camera* primary_camera = NULL; - if(primary_camera_index != -1) - primary_camera = &camera_list[primary_camera_index]; - return primary_camera; -} - static void update_frustum(struct Camera* camera) { assert(camera); @@ -280,15 +192,15 @@ static void update_frustum(struct Camera* camera) } } -void camera_resize_all(int width, int height) -{ - for(int i = 0; i < array_len(camera_list); i++) - { - struct Camera* camera = &camera_list[i]; - if(!camera->resizeable) continue; - - float aspect = (float)width / (float)height; - camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; - camera_update_proj(camera); - } -} +/* void camera_resize_all(int width, int height) */ +/* { */ +/* for(int i = 0; i < array_len(camera_list); i++) */ +/* { */ +/* struct Camera* camera = &camera_list[i]; */ +/* if(!camera->resizeable) continue; */ + +/* float aspect = (float)width / (float)height; */ +/* camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; */ +/* camera_update_proj(camera); */ +/* } */ +/* } */ diff --git a/src/camera.h b/src/camera.h index 2a584fd..233dbb9 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,36 +1,13 @@ -#ifndef camera_H -#define camera_H +#ifndef CAMERA_H +#define CAMERA_H -#include "linmath.h" +struct Camera; +struct Transform; -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; - int fbo; - int render_tex; - int depth_tex; - vec4 clear_color; - vec4 frustum[6]; - int resizeable; -}; - -struct Camera* camera_get(int index); -struct Camera* camera_get_all(void); -struct Camera* camera_get_primary(void); -void camera_init(void); -void camera_cleanup(void); -void camera_remove(int index); -int camera_create(int node, int width, int height); +void camera_destroy(struct Camera* camera); +void camera_create(struct Camera* camera, struct Transform* transform, int width, int height); void camera_update_view_proj(struct Camera* camera); -void camera_update_view(struct Camera* camera); +void camera_update_view(struct Camera* camera, struct Transform* transform); void camera_update_proj(struct Camera* camera); void camera_attach_fbo(struct Camera* camera, int width, @@ -38,7 +15,6 @@ void camera_attach_fbo(struct Camera* camera, int has_depth, int has_color, int resizeable); -void camera_set_primary_viewer(struct Camera* camera); -void camera_resize_all(int width, int height); +/* void camera_resize_all(int width, int height); */ #endif diff --git a/src/components.h b/src/components.h deleted file mode 100644 index fb55d19..0000000 --- a/src/components.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef components_H -#define components_H - -enum Component -{ - C_TRANSFORM = 0, - C_MODEL, - C_CAMERA, - C_LIGHT, - C_SOUND_SOURCE, - C_RIGIDBODY, - NUM_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_LIGHT: str = "LIGHT"; break; - case C_SOUND_SOURCE: str = "SOUND_SOURCE"; break; - case C_RIGIDBODY: str = "RIGIDBODY"; break; - case NUM_COMPONENTS: str = "NUM_COMPONENTS"; break; - } - return str; -} - -#endif diff --git a/src/entity.c b/src/entity.c index 19379a5..b128a11 100644 --- a/src/entity.c +++ b/src/entity.c @@ -34,32 +34,27 @@ void entity_cleanup(void) void entity_remove(int index) { struct Entity* entity = &entity_list[index]; - if(entity->node == -1) return; - - for(int i = 0; i < NUM_COMPONENTS; i++) - { - if(i == C_TRANSFORM) - { - transform_remove(entity->components[i]); - entity->components[i] = -1; - } - else - { - entity_component_remove(entity, i); - } - } - entity->node = -1; - entity->parent = -1; - entity->is_listener = 0; - array_free(entity->children); - entity->children = NULL; + + transform_destroy(&entity->transform); + switch(entity->type) + { + case ET_CAMERA: camera_destroy(&entity->camera); break; + case ET_LIGHT: light_destroy(&entity->light, entity->id); break; + case ET_SOUND_SOURCE: sound_source_destroy(&entity->sound_source); break; + case ET_STATIC_MESH: model_destroy(&entity->model, entity->id); break; + case ET_ROOT: break; + default: log_error("entity:remove", "Invalid entity type"); break; + }; + entity->id = -1; + entity->is_listener = false; + entity->marked_for_deletion = false; + entity->renderable = false; + entity->name = NULL; free(entity->name); - free(entity->tag); - entity->name = entity->tag = NULL; array_push(empty_indices, index, int); } -struct Entity* entity_create(const char* name, const char* tag) +struct Entity* entity_create(const char* name, const int type, int parent_id) { struct Entity* new_entity = NULL; int index = -1; @@ -73,23 +68,18 @@ struct Entity* entity_create(const char* name, const char* tag) else { new_entity = array_grow(entity_list, struct Entity); - new_entity->name = new_entity->tag = NULL; + new_entity->name = NULL; index = array_len(entity_list) - 1; } if(new_entity->name) free(new_entity->name); - if(new_entity->tag) free(new_entity->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->is_listener = 0; - new_entity->children = array_new(int); - for(int i = 0; i < NUM_COMPONENTS; i++) - new_entity->components[i] = -1; - new_entity->components[C_TRANSFORM] = transform_create(new_entity->node); - + new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME"); + new_entity->id = index; + new_entity->is_listener = false; + new_entity->type = type; + new_entity->marked_for_deletion = false; + new_entity->renderable = false; + transform_create(&new_entity->transform, parent_id); return new_entity; } @@ -119,145 +109,35 @@ struct Entity* entity_find(const char* name) return entity; } -int entity_component_remove(struct Entity* entity, enum Component component) +void entity_post_update(void) { - int success = 1; - assert(entity); - int comp_index = entity->components[component]; - switch(component) - { - 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_LIGHT: if(comp_index != -1) light_remove(comp_index); break; - case C_SOUND_SOURCE: if(comp_index != -1) sound_source_remove(comp_index); break; - case C_RIGIDBODY: - break; - default: - /* Only called for NUM_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); - int comp_index = entity->components[component]; - if(comp_index != -1) + for(int i = 0; i < array_len(entity_list); i++) { - switch(component) + struct Entity* entity = &entity_list[i]; + if(entity->id == -1) continue; + + if(entity->marked_for_deletion) { - 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_LIGHT: comp_obj = light_get(comp_index); break; - case C_SOUND_SOURCE: comp_obj = sound_source_get(comp_index); break; - case C_RIGIDBODY: - break; - default: log_error("entity:component_get", "Invalid component type"); break; + entity_remove(i); + continue; } } - 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, ...) -{ - assert(entity); - void* new_comp = NULL; - 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: - { - const char* filename = va_arg(args, const char*); - const char* material_name = va_arg(args, const char*); - new_comp_index = model_create(entity->node, filename, material_name); - 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_LIGHT: - { - int light_type = va_arg(args, int); - new_comp_index = light_create(entity->node, light_type); - new_comp = light_get(new_comp_index); - } - break; - case C_SOUND_SOURCE: - { - new_comp_index = sound_source_create(entity->node); - new_comp = sound_source_get(new_comp_index); - } - break; - case C_RIGIDBODY: - log_error("entity:component_add", "Unsupported component 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)) + for(int i = 0; i < array_len(entity_list); i++) { - struct Camera* camera = entity_component_get(entity, C_CAMERA); - camera_update_view(camera); - } + struct Entity* entity = &entity_list[i]; + if(entity->id == -1) continue; - if(entity_has_component(entity, C_SOUND_SOURCE)) - { - struct Sound_Source* source = entity_component_get(entity, C_SOUND_SOURCE); - sound_source_update(source); - } + if(entity->transform.is_modified) + { + if(entity->type == ET_CAMERA) + camera_update_view(&entity->camera, &entity->transform); + else if(entity->type == ET_SOUND_SOURCE) + sound_source_update(&entity->sound_source, &entity->transform); - if(entity->is_listener) sound_listener_update(); + if(entity->is_listener) sound_listener_update(); + } + } } struct Entity* entity_get_all(void) @@ -269,6 +149,6 @@ struct Entity* entity_get_parent(int node) { struct Entity* parent = NULL; struct Entity* entity = entity_get(node); - if(entity) parent = entity_get(entity->node); + if(entity) parent = entity_get(entity->transform.parent); return parent; } diff --git a/src/entity.h b/src/entity.h index 8a85f39..c7475cf 100644 --- a/src/entity.h +++ b/src/entity.h @@ -1,31 +1,123 @@ -#ifndef entity_H -#define entity_H +#ifndef ENTITY_H +#define ENTITY_H -#include "components.h" +#include "linmath.h" +#include "num_types.h" + +struct Material_Param; + +enum Entity_Type +{ + ET_PLAYER, + ET_ROOT, + ET_CAMERA, + ET_LIGHT, + ET_STATIC_MESH, + ET_SOUND_SOURCE, + ET_MAX +}; + +enum LightType +{ + LT_SPOT = 0, + LT_DIR, + LT_POINT, + LT_INVALID, + LT_MAX +}; + +struct Transform +{ + vec3 position; + vec3 scale; + quat rotation; + mat4 trans_mat; + int parent; + int* children; + bool is_modified; +}; + +struct Model +{ + int geometry_index; + int material; + struct Material_Param* material_params; +}; + +struct Sound_Source +{ + uint al_source_handle; + uint al_buffer_handle; + bool active; +}; + +struct Camera +{ + mat4 proj_mat; + mat4 view_mat; + mat4 view_proj_mat; + float fov; + float aspect_ratio; + float nearz; + float farz; + bool ortho; + int fbo; + int render_tex; + int depth_tex; + vec4 clear_color; + vec4 frustum[6]; + bool resizeable; +}; + +struct Light +{ + float outer_angle; + float inner_angle; + float falloff; + float intensity; + vec3 color; + bool cast_shadow; + bool pcf_enabled; + bool valid; + int type; + int radius; + int shadow_map[4]; + float depth_bias; +}; struct Entity { - int node; - char* name; - char* tag; - int components[NUM_COMPONENTS]; - int parent; - int* children; - int is_listener; + int id; + int type; + char* name; + bool is_listener; /* TODO: Replace all booleans with flags */ + bool marked_for_deletion; + bool renderable; + struct Transform transform; + + union + { + struct + { + struct Model model; + int health; + } Player; + + struct Model model; + struct Camera camera; + struct Light light; + struct Sound_Source sound_source; + }; }; void entity_init(void); void entity_cleanup(void); void entity_remove(int index); -struct Entity* entity_create(const char* name, const char* tag); +void entity_post_update(void); +struct Entity* entity_create(const char* name, const int type, int parent_id); struct Entity* entity_get(int index); struct Entity* entity_find(const char* name); struct Entity* entity_get_all(void); struct Entity* entity_get_parent(int node); -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, ...); -int entity_has_component(struct Entity* entity, enum Component component); -void entity_sync_components(struct Entity* entity); #endif diff --git a/src/game.c b/src/game.c index ccc23b5..7adbff9 100644 --- a/src/game.c +++ b/src/game.c @@ -72,9 +72,7 @@ int game_init(struct Window* window) framebuffer_init(); geom_init(); renderer_init(); - transform_init(); light_init(); - camera_init(); material_init(); editor_init(); model_init(); @@ -89,10 +87,10 @@ int game_init(struct Window* window) void scene_setup(void) { - struct Entity* player = scene_add_new("player", "None"); - game_state->player_node = player->node; + struct Entity* player = scene_add_new("player", ET_CAMERA); + game_state->player_node = player->id; vec3 viewer_pos = {10, 5, 100}; - struct Transform* viewer_tran = entity_component_get(player, C_TRANSFORM); + struct Transform* viewer_tran = &player->transform; /* struct Model* player_model = entity_component_add(player, C_MODEL, "sphere.pamesh", NULL); */ /* model_set_material_param(player_model, "diffuse_color", &color); */ /* vec4_fill(&color, 1.f, 1.f, 1.f, 1.f); */ @@ -100,25 +98,28 @@ void scene_setup(void) int render_width, render_height; render_width = 1024; render_height = 768; - struct Camera* camera = entity_component_add(player, C_CAMERA, render_width, render_height); + struct Camera* camera = &player->camera; + camera_create(camera, &player->transform, render_width, render_height); camera_attach_fbo(camera, render_width, render_height, 1, 1, 1); vec4_fill(&camera->clear_color, 0.3f, 0.6f, 0.9f, 1.0f); - camera_set_primary_viewer(camera); - sound_listener_set(player->node); + sound_listener_set(player->id); vec4 color = {0.f, 1.f, 1.f, 1.f }; - struct Entity* new_ent = scene_add_new("Model_Entity", NULL); - struct Transform* tran = entity_component_get(new_ent, C_TRANSFORM); + struct Entity* new_ent = scene_add_new("Model_Entity", ET_STATIC_MESH); + struct Transform* tran = &new_ent->transform; vec3 position = {0, 0, -5}; transform_translate(tran, &position, TS_WORLD); - struct Model* box_model = entity_component_add(new_ent, C_MODEL, "default.pamesh", "Blinn_Phong"); + struct Model* box_model = &new_ent->model; + model_create(box_model, new_ent->id, "default.pamesh", "Blinn_Phong"); model_set_material_param(box_model, "diffuse_color", &color); int tex = texture_create_from_file("white.tga", TU_DIFFUSE); model_set_material_param(box_model, "diffuse_texture", &tex); - struct Transform* model_tran = entity_component_get(new_ent, C_TRANSFORM); vec3 scale = {1, 1, 1}; - transform_scale(model_tran, &scale); - struct Sound_Source* source = entity_component_add(new_ent, C_SOUND_SOURCE); + transform_scale(tran, &scale); + + struct Entity* sound_ent = scene_add_as_child("Sound_ENT", ET_SOUND_SOURCE, new_ent->id); + struct Sound_Source* source = &sound_ent->sound_source; + sound_source_create(source, &new_ent->transform); if(source) { sound_source_load_wav(source, "BigExplosion.wav"); @@ -128,7 +129,7 @@ void scene_setup(void) sound_source_play(source); } - int parent_node = new_ent->node; + int parent_node = new_ent->id; int num_suz = 2; srand(time(NULL)); for(int i = 0; i < num_suz; i++) @@ -137,30 +138,29 @@ void scene_setup(void) int y = rand() % num_suz; int z = rand() % num_suz; x++; y++; z++; - struct Entity* suz = scene_add_as_child("Suzanne", NULL, parent_node); - //struct Entity* suz = scene_add_new("Suzanne", NULL); - struct Model* suz_model = entity_component_add(suz, C_MODEL, "suzanne.pamesh", "Blinn_Phong"); + struct Entity* suz = scene_add_as_child("Suzanne", ET_STATIC_MESH, parent_node); + struct Model* suz_model = &suz->model; + model_create(suz_model, suz->id, "suzanne.pamesh", "Blinn_Phong"); model_set_material_param(suz_model, "diffuse_color", &color); float spec_str = 80.f; model_set_material_param(suz_model, "specular_strength", &spec_str); - struct Transform* s_tran = entity_component_get(suz, C_TRANSFORM); vec3 s_pos = {x, 5, z}; - transform_translate(s_tran, &s_pos, TS_WORLD); + transform_translate(&suz->transform, &s_pos, TS_WORLD); } - struct Entity* ground = scene_add_new("Ground", NULL); - struct Model* ground_model = entity_component_add(ground, C_MODEL, "plane.pamesh", "Blinn_Phong"); + struct Entity* ground = scene_add_new("Ground", ET_STATIC_MESH); + struct Model* ground_model = &ground->model; + model_create(ground_model, ground->id, "plane.pamesh", "Blinn_Phong"); model_set_material_param(ground_model, "diffuse_color", &color); int white_tex = texture_create_from_file("white.tga", TU_DIFFUSE); model_set_material_param(ground_model, "diffuse_texture", &white_tex); float spec_str = 80.f; model_set_material_param(ground_model, "specular_strength", &spec_str); - struct Transform* ground_tran = entity_component_get(ground, C_TRANSFORM); vec3 pos = {0, -15, 0}; - vec3 scale_ground = {200.f, 200.f, 200.f}; - transform_set_position(ground_tran, &pos); - transform_scale(ground_tran, &scale_ground); + vec3 scale_ground = {200.f, 1.f, 200.f}; + transform_set_position(&ground->transform, &pos); + transform_scale(&ground->transform, &scale_ground); /* struct Entity* screen = scene_add_new("Screen", NULL); */ /* struct Model* screen_model = entity_component_add(screen, C_MODEL, NULL, NULL); */ @@ -182,11 +182,11 @@ void scene_setup(void) int x = rand() % MAX_LIGHTS; int z = rand() % MAX_LIGHTS; x++; z++; - struct Entity* light_ent = scene_add_new("Light_Ent", NULL); - struct Transform* light_tran = entity_component_get(light_ent, C_TRANSFORM); + struct Entity* light_ent = scene_add_new("Light_Ent", ET_LIGHT); vec3 lt_pos = {x * 20, 0, z * 20}; - transform_set_position(light_tran, <_pos); - struct Light* light_comp = entity_component_add(light_ent, C_LIGHT, LT_POINT); + transform_set_position(&light_ent->transform, <_pos); + struct Light* light_comp = &light_ent->light; + light_create(&light_ent->light, light_ent->id, LT_POINT); vec3_fill(&light_comp->color, 1.f / (float)x, 1.f / ((rand() % 10) + 1.f), 1.f / (float)z); light_comp->intensity = 1.f; } @@ -200,9 +200,8 @@ void debug(float dt) { //struct Entity* entity = entity_get(player_node); struct Entity* entity = entity_get(game_state->player_node); - struct Camera* cam = entity_component_get(entity, C_CAMERA); - camera_set_primary_viewer(cam); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + struct Camera* cam = &entity->camera; + struct Transform* transform = &entity->transform; float move_speed = 5.f, move_scale = 3.f, turn_speed = 50.f; vec3 offset = {0, 0, 0}; float turn_up_down = 0.f; @@ -291,29 +290,26 @@ void debug(float dt) if(input_is_key_pressed(KEY_SPACE)) { struct Entity* model = scene_find("Model_Entity"); - 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); + transform_rotate(&model->transform, &x_axis, 25.f * dt, TS_WORLD); } if(input_is_key_pressed(KEY_M)) { struct Entity* model = scene_find("Model_Entity"); - struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM); //vec3 y_axis = {0, 0, 1}; //transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL); vec3 amount = {0, 0, -5 * dt}; - transform_translate(mod_tran, &amount, TS_LOCAL); + transform_translate(&model->transform, &amount, TS_LOCAL); } if(input_is_key_pressed(KEY_N)) { struct Entity* model = scene_find("Model_Entity"); - struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM); /* vec3 y_axis = {0, 0, 1}; */ /* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */ vec3 amount = {0, 0, 5 * dt}; - transform_translate(mod_tran, &amount, TS_LOCAL); + transform_translate(&model->transform, &amount, TS_LOCAL); } } @@ -335,6 +331,7 @@ int run(void) update(delta_time, &should_window_close); render(); window_swap_buffers(game_state->window); + entity_post_update(); } return 1; } @@ -1559,7 +1556,8 @@ void debug_gui(float dt) void render(void) { - renderer_draw(); + struct Entity* viewer = entity_get(game_state->player_node); + renderer_draw(viewer); } void game_cleanup(void) @@ -1575,8 +1573,6 @@ void game_cleanup(void) material_cleanup(); geom_cleanup(); light_cleanup(); - transform_cleanup(); - camera_cleanup(); input_cleanup(); renderer_cleanup(); io_file_cleanup(); diff --git a/src/light.c b/src/light.c index 6867ce2..453241e 100644 --- a/src/light.c +++ b/src/light.c @@ -1,117 +1,70 @@ #include "light.h" -#include "log.h" #include "array.h" -#include -#include +#include "entity.h" -static struct Light* light_list; -static int* empty_indices; -static int* valid_light_indices; -static int max_lights; +#include -struct Light* light_get(int index) -{ - struct Light* light = NULL; - if(index > -1 && index < array_len(light_list)) - light = &light_list[index]; - return light; -} - -struct Light* light_get_all(void) -{ - return light_list; -} +static int* light_list = NULL; void light_init(void) { - max_lights = 128; - light_list = array_new_cap(struct Light, max_lights); - for(int i = 0; i < max_lights; i++) light_list[i].valid = 0; - empty_indices = array_new(int); - valid_light_indices = array_new_cap(int, max_lights); - memset(valid_light_indices, -1, max_lights); + light_list = array_new(int); } void light_cleanup(void) { - for(int i = 0; i < array_len(light_list); i++) - light_remove(i); array_free(light_list); - array_free(empty_indices); - array_free(valid_light_indices); } -void light_remove(int index) + +void light_create(struct Light* light, int entity_id, int light_type) { - if(index > -1 && index < array_len(light_list)) - { - light_list[index].valid = 0; - array_push(empty_indices, index, int); - } + assert(light && entity_id > -1); + + light->valid = true; + light->cast_shadow = 0; + light->depth_bias = 0.0005f; + light->type = light_type; + light->pcf_enabled = false; + light->intensity = 1.f; + light->falloff = 1.5f; + light->outer_angle = TO_RADIANS(30.f); + light->inner_angle = TO_RADIANS(20.f); + light->radius = 20; + vec3_fill(&light->color, 1.f, 1.f, 1.f); + int* new_index = array_grow(light_list, int); + *new_index = entity_id; } -int light_create(int node, int light_type) +void light_destroy(struct Light* light, int entity_id) { - int index = -1; - struct Light* new_light = NULL; - if(array_len(empty_indices) > 0) - { - index = *array_get_last(empty_indices, int); - new_light = &light_list[index]; - array_pop(empty_indices); - } - else + assert(light && entity_id > -1); + + int index_to_remove = -1; + for(int i = 0; i < array_len(light_list); i++) { - for(index = 0; index < max_lights; index++) - { - if(!light_list[index].valid) - break; - } - - if(index == max_lights - 1) + if(light_list[i] == entity_id) { - index = -1; - log_warning("Max light limit(%d) reached, cannot add light", max_lights); - return index; + index_to_remove = i; + break; } - - new_light = &light_list[index]; } - new_light->node = node; - new_light->valid = 1; - new_light->cast_shadow = 0; - vec3_fill(&new_light->color, 1.f, 1.f, 1.f); - new_light->depth_bias = 0.0005f; - new_light->type = light_type; - new_light->pcf_enabled = 0; - new_light->intensity = 1.f; - new_light->falloff = 1.5f; - new_light->outer_angle = TO_RADIANS(30.f); - new_light->inner_angle = TO_RADIANS(20.f); - new_light->radius = 20; - return index; -} - -int light_get_max_lights(void) -{ - return max_lights; + if(index_to_remove != -1) array_remove_at(light_list, index_to_remove); + light->valid = false; + light->cast_shadow = 0; + light->depth_bias = 0.f; + light->type = LT_INVALID; + light->pcf_enabled = false; + light->intensity = 10.f; + light->falloff = 0.f; + light->outer_angle = 0.f; + light->inner_angle = 0.f; + light->radius = 0.f; + vec3_fill(&light->color, 1.f, 0.f, 1.f); } -int* light_get_valid_indices(int* valid_light_count) +int* light_get_valid_indices(int* out_count) { - /* First, get all the valid(active) lights, then sort them in the - order directional, point, spot - */ - int light_count = 0; - for(int i = 0; i < array_len(light_list); i++) - { - if(light_list[i].valid) - { - valid_light_indices[light_count] = i; - light_count++; - } - } - *valid_light_count = light_count; - - return valid_light_indices; + *out_count = array_len(light_list); + return light_list; } diff --git a/src/light.h b/src/light.h index 754e47a..70ad40a 100644 --- a/src/light.h +++ b/src/light.h @@ -1,43 +1,14 @@ #ifndef LIGHT_H #define LIGHT_H -#include "num_types.h" -#include "linmath.h" - #define MAX_SHADOWMAPS 4 -enum LightType -{ - LT_SPOT = 0, - LT_DIR, - LT_POINT -}; - -struct Light -{ - float outer_angle; - float inner_angle; - float falloff; - float intensity; - vec3 color; - int32 node; - uint8 cast_shadow; - uint8 pcf_enabled; - uint8 valid; - int type; - int radius; - int shadow_map[4]; - float depth_bias; -}; +struct Light; -struct Light* light_get(int index); -struct Light* light_get_all(void); void light_init(void); void light_cleanup(void); -void light_remove(int index); -int light_create(int node, int light_type); -void light_set_radius(struct Light* light, int radius); -int light_get_max_lights(void); -int* light_get_valid_indices(int* valid_light_count); +void light_destroy(struct Light* light, int entity_id); +void light_create(struct Light* light, int entity_id, int light_type); +int* light_get_valid_indices(int* out_count); #endif diff --git a/src/material.c b/src/material.c index ff723f8..991f5a3 100644 --- a/src/material.c +++ b/src/material.c @@ -1,6 +1,7 @@ #include "material.h" #include "array.h" #include "shader.h" +#include "entity.h" #include "string_utils.h" #include "log.h" #include "model.h" diff --git a/src/model.c b/src/model.c index 7e9ae5d..004d2f0 100644 --- a/src/model.c +++ b/src/model.c @@ -1,7 +1,6 @@ #include "model.h" #include "array.h" #include "log.h" -#include "camera.h" #include "entity.h" #include "shader.h" #include "transform.h" @@ -10,6 +9,7 @@ #include "material.h" #include "light.h" #include "editor.h" +#include "geometry.h" #include "variant.h" #include "bounding_volumes.h" #include "gl_load.h" @@ -21,100 +21,50 @@ #define MAX_NAME_LEN 64 -static struct Model* model_list; -static int* empty_indices; -static int num_culled = 0, num_rendered = 0, num_indices = 0; -static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1; - -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; -} +static int num_culled = 0, num_rendered = 0, num_indices = 0; +static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1; void model_init(void) { - model_list = array_new(struct Model); - empty_indices = array_new(int); num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); } -int model_create(int node, const char* geo_name, const char* material_name) +void model_create(struct Model* model, int entity_id, const char* geo_name, const char* material_name) { + assert(model); /* if no name is given for geometry, use default */ if(!geo_name) geo_name = "default.pamesh"; int geo_index = geom_create_from_file(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; - if(!material_register_model(new_model, index, material_name ? material_name : "Unshaded")) - { - log_error("model:create", "Unable to register model with Unshaded material, component not added"); - model_remove(index); - index = -1; - } - } - else + + model->geometry_index = geo_index; + if(!material_register_model(model, entity_id, material_name ? material_name : "Unshaded")) { - log_error("model:create", "Geometry '%s' not found.", geo_name); + log_error("model:create", "Unable to register model with Unshaded material, component not added"); + model_destroy(model, entity_id); } - return index; } -void model_remove(int index) +void model_destroy(struct Model* model, int entity_id) { - 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; - material_unregister_model(model, index); - /* deallocate all params */ - for(int i = 0; i < array_len(model->material_params); i++) - free(model->material_params[i].value); + assert(model); + geom_remove(model->geometry_index); + model->geometry_index = -1; + material_unregister_model(model, entity_id); + /* deallocate all params */ + for(int i = 0; i < array_len(model->material_params); i++) + free(model->material_params[i].value); - array_free(model->material_params); - array_push(empty_indices, index, int); - } - else - { - log_error("model:remove", "Invalid index"); - } + array_free(model->material_params); } 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, enum Geometry_Draw_Mode draw_mode) +void model_render_all(struct Entity* camera_entity, int draw_mode) { static mat4 mvp; struct Material* material_list = material_get_all_materials(); @@ -130,9 +80,9 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) for(int j = 0; j < array_len(material->registered_models); j++) { /* for each registered model, set up uniforms and render */ - struct Model* model = &model_list[material->registered_models[j]]; - struct Entity* entity = entity_get(model->node); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + struct Entity* entity = entity_get(material->registered_models[i]); + struct Model* model = &entity->model; + struct Transform* transform = &entity->transform; /* set material params for the model */ for(int k = 0; k < array_len(model->material_params); k++) @@ -152,7 +102,7 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) if(strcmp(uniform->name, "mvp") == 0) { mat4_identity(&mvp); - mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); + mat4_mul(&mvp, &camera_entity->camera.view_proj_mat, &transform->trans_mat); shader_set_uniform(uniform->type, uniform->location, &mvp); renderer_check_glerror("model:render_all:material_pipeline"); } @@ -163,7 +113,7 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) } else if(strcmp(uniform->name, "view_mat") == 0) { - shader_set_uniform(uniform->type, uniform->location, &camera->view_mat); + shader_set_uniform(uniform->type, uniform->location, &camera_entity->camera.view_mat); renderer_check_glerror("model:render_all:material_pipeline"); } else if(strcmp(uniform->name, "inv_model_mat") == 0) @@ -214,16 +164,16 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) memset(uniform_name, '\0', MAX_NAME_LEN); for(int i = 0; i < valid_light_count; i++) { - struct Light* light = light_get(light_index_list[i]); /* TODO: Cull lights according to camera frustum */ - struct Entity* light_entity = entity_get(light->node); - struct Transform* transform = entity_component_get(light_entity, C_TRANSFORM); + struct Entity* light_entity = entity_get(light_index_list[i]); + struct Light* light = &light_entity->light; /* TODO: Cull lights according to camera frustum */ + struct Transform* light_transform = &light_entity->transform; vec3 light_pos = {0, 0, 0}; - transform_get_absolute_pos(transform, &light_pos); + transform_get_absolute_pos(light_transform, &light_pos); if(light->type != LT_POINT) { snprintf(uniform_name, MAX_NAME_LEN, "lights[%d].direction", i); - transform_get_absolute_lookat(transform, &light_pos); + transform_get_absolute_lookat(light_transform, &light_pos); vec3_norm(&light_pos, &light_pos); shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); memset(uniform_name, '\0', MAX_NAME_LEN); @@ -267,15 +217,14 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) } shader_set_uniform_int(material->shader, "total_active_lights", valid_light_count); - struct Entity* camera_entity = entity_get(camera->node); - struct Transform* camera_tran = entity_component_get(camera_entity, C_TRANSFORM); + struct Transform* camera_tran = &camera_entity->transform; vec3 camera_pos = {0, 0, 0}; transform_get_absolute_pos(camera_tran, &camera_pos); shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos); } /* Render the geometry */ - int indices = geom_render_in_frustum(model->geometry_index, &camera->frustum[0], transform, draw_mode); + int indices = geom_render_in_frustum(model->geometry_index, &camera_entity->camera.frustum[0], transform, draw_mode); if(indices > 0) { num_rendered++; @@ -322,27 +271,13 @@ int model_set_material_param(struct Model* model, const char* name, void* value) success = 1; switch(uniform->type) { - case UT_INT: - *((int*)param->value) = *((int*)value); - break; - case UT_FLOAT: - *((float*)param->value) = *((float*)value); - break; - case UT_VEC2: - vec2_assign((vec2*)param->value, (vec2*)value); - break; - case UT_VEC3: - vec3_assign((vec3*)param->value, (vec3*)value); - break; - case UT_VEC4: - vec4_assign((vec4*)param->value, (vec4*)value); - break; - case UT_MAT4: - mat4_assign((mat4*)param->value, (mat4*)value); - break; - case UT_TEX: - *((int*)param->value) = *((int*)value); - break; + case UT_INT: *((int*)param->value) = *((int*)value); break; + case UT_FLOAT: *((float*)param->value) = *((float*)value); break; + case UT_VEC2: vec2_assign((vec2*)param->value, (vec2*)value); break; + case UT_VEC3: vec3_assign((vec3*)param->value, (vec3*)value); break; + case UT_VEC4: vec4_assign((vec4*)param->value, (vec4*)value); break; + case UT_MAT4: mat4_assign((mat4*)param->value, (mat4*)value); break; + case UT_TEX: *((int*)param->value) = *((int*)value); break; default: log_error("model:set_material_param", "Invalid parameter type"); success = 0; @@ -374,36 +309,32 @@ int model_get_material_param(struct Model* model, const char* name, void* value_ case UT_VEC4: vec4_assign((vec4*)value_out, (vec4*)param->value); break; case UT_MAT4: mat4_assign((mat4*)value_out, (mat4*)param->value); break; } - break; /* break for */ success = 1; + break; } } return success; } -struct Model* model_get_all(void) -{ - return model_list; -} - -void model_render_all_debug(struct Camera* camera, - int debug_shader, - enum Geometry_Draw_Mode draw_mode, - const vec4* debug_color) +void model_render_all_debug(struct Entity* camera_entity, + int debug_shader, + int draw_mode, + const vec4* debug_color) { assert(debug_shader > -1); shader_bind(debug_shader); { static mat4 mvp; shader_set_uniform_vec4(debug_shader, "debug_color", debug_color); - for(int i = 0; i < array_len(model_list); i++) + struct Entity* entity_list = entity_get_all(); + for(int i = 0; i < array_len(entity_list); i++) { - struct Model* model = &model_list[i]; - struct Entity* entity = entity_get(model->node); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + if(!entity_list[i].renderable) continue; + struct Model* model = &entity_list[i].model; + struct Transform* transform = &entity_list[i].transform; int geometry = model->geometry_index; mat4_identity(&mvp); - mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); + mat4_mul(&mvp, &camera_entity->camera.view_proj_mat, &transform->trans_mat); shader_set_uniform_mat4(debug_shader, "mvp", &mvp); geom_render(geometry, draw_mode); } diff --git a/src/model.h b/src/model.h index ca2c09e..3218f4e 100644 --- a/src/model.h +++ b/src/model.h @@ -2,31 +2,22 @@ #define MODEL_H #include "linmath.h" -#include "geometry.h" struct Camera; struct Material_Param; +struct Model; +struct Entity; -struct Model -{ - int node; - int geometry_index; - int material; - struct Material_Param* material_params; -}; - -struct Model* model_get(int index); -struct Model* model_get_all(void); void model_init(void); -int model_create(int node, const char* geo_name, const char* material_name); -void model_remove(int index); +void model_create(struct Model* model, int entity_id, const char* geo_name, const char* material_name); +void model_destroy(struct Model* model, int entity_id); void model_cleanup(void); -void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode); +void model_render_all(struct Entity* camera_entity, int draw_mode); int model_set_material_param(struct Model* model, const char* name, void* value); int model_get_material_param(struct Model* model, const char* name, void* value_out); -void model_render_all_debug(struct Camera* camera, - int debug_shader, - enum Geometry_Draw_Mode draw_mode, - const vec4* debug_color); +void model_render_all_debug(struct Entity* camera_entity, + int debug_shader, + int draw_mode, + const vec4* debug_color); #endif diff --git a/src/num_types.h b/src/num_types.h index 7e8ad85..2b4b47b 100644 --- a/src/num_types.h +++ b/src/num_types.h @@ -2,6 +2,7 @@ #define num_types_H #include +#include typedef int8_t int8; typedef int32_t int32; diff --git a/src/renderer.c b/src/renderer.c index 7b9511c..ca8ff7d 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -16,6 +16,7 @@ #include "gui.h" #include "config_vars.h" #include "hashmap.h" +#include "geometry.h" static int def_fbo = -1; static int def_albedo_tex = -1; @@ -122,14 +123,14 @@ void renderer_init(void) debug_shader = shader_create("debug.vert", "debug.frag"); } -void renderer_draw(void) +void renderer_draw(struct Entity* active_viewer) { - struct Camera* camera_list = camera_get_all(); - for(int i = 0; i < array_len(camera_list); i++) + struct Entity* entity_list = entity_get_all(); + for(int i = 0; i < array_len(entity_list); i++) { - struct Camera* camera = &camera_list[i]; - if(camera->node < 0) - continue; + struct Entity* viewer = &entity_list[i]; + if(entity_list[i].type != ET_CAMERA) continue; + struct Camera* camera = &viewer->camera; /* if(camera->fbo == -1) continue; */ int fbo = camera->fbo == -1 ? def_fbo : camera->fbo; @@ -145,7 +146,7 @@ void renderer_draw(void) glEnable(GL_CULL_FACE ); glCullFace(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - model_render_all(camera, GDM_TRIANGLES); + model_render_all(viewer, GDM_TRIANGLES); } framebuffer_unbind(); glDisable(GL_DEPTH_TEST); @@ -176,7 +177,7 @@ void renderer_draw(void) glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader_bind(composition_shader); - struct Camera* active_camera = camera_get_primary(); + struct Camera* active_camera = &active_viewer->camera; int final_render_tex = active_camera->render_tex == -1 ? def_albedo_tex : active_camera->render_tex; texture_bind(final_render_tex); geom_render(quad_geo, GDM_TRIANGLES); @@ -186,7 +187,7 @@ void renderer_draw(void) if(settings.debug_draw_enabled) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - model_render_all_debug(active_camera, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color); + model_render_all_debug(active_viewer, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } @@ -204,7 +205,17 @@ void renderer_cleanup(void) void on_framebuffer_size_change(int width, int height) { - camera_resize_all(width, height); + struct Entity* entity_list = entity_get_all(); + float aspect = (float)width / (float)height; + for(int i = 0; i < array_len(entity_list); i++) + { + struct Entity* viewer = &entity_list[i]; + if(viewer->type != ET_CAMERA) continue; + + viewer->camera.aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; + camera_update_proj(&viewer->camera); + } + framebuffer_resize_all(width, height); } diff --git a/src/renderer.h b/src/renderer.h index 59ef0a2..a947f97 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -2,7 +2,6 @@ #define renderer_H #include "linmath.h" -#include "geometry.h" enum Fog_Mode { @@ -24,18 +23,20 @@ struct Fog struct Render_Settings { - struct Fog fog; - vec3 ambient_light; - int max_gui_vertex_memory; - int max_gui_element_memory; - int debug_draw_enabled; - vec4 debug_draw_color; - enum Geometry_Draw_Mode debug_draw_mode; + struct Fog fog; + vec3 ambient_light; + int max_gui_vertex_memory; + int max_gui_element_memory; + int debug_draw_enabled; + vec4 debug_draw_color; + int debug_draw_mode; }; +struct Entity; + struct Render_Settings* renderer_settings_get(void); void renderer_init(void); -void renderer_draw(void); +void renderer_draw(struct Entity* active_viewer); void renderer_cleanup(void); void renderer_clearcolor_set(float r, float g, float b, float a); void renderer_debug_draw_enabled(int enabled); diff --git a/src/scene.c b/src/scene.c index a164f2b..344be35 100644 --- a/src/scene.c +++ b/src/scene.c @@ -12,52 +12,50 @@ 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* root = entity_create("ROOT", ET_ROOT, -1); + root_node = root->id; } -struct Entity* scene_add_new(const char* name, const char* tag) +struct Entity* scene_add_new(const char* name, const int type) { - return scene_add_as_child(name, tag, root_node); + return scene_add_as_child(name, type, root_node); } -struct Entity* scene_add_as_child(const char* name, const char* tag, int parent_node) +struct Entity* scene_add_as_child(const char* name, const int type, int parent_id) { - assert(parent_node > -1); + assert(parent_id > -1); struct Entity* new_entity = NULL; - new_entity = entity_create(name, tag); - struct Entity* parent = entity_get(parent_node); - 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); + new_entity = entity_create(name, type, parent_id); + struct Entity* parent = entity_get(parent_id); + new_entity->transform.parent = parent->id; + transform_update_transmat(&new_entity->transform); return new_entity; } void scene_remove(struct Entity* entity) { assert(entity); - for(int i = 0; i < array_len(entity->children); i++) + for(int i = 0; i < array_len(entity->transform.children); i++) { - struct Entity* child = entity_get(entity->children[i]); + struct Entity* child = entity_get(entity->transform.children[i]); scene_remove(child); } - entity_remove(entity->node); + entity_remove(entity->id); } void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) { assert(entity && new_parent); - struct Entity* curr_parent = entity_get(entity->parent); + struct Entity* curr_parent = entity_get(entity->transform.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++) + for(int i = 0; i < array_len(curr_parent->transform.children); i++) { - if(curr_parent->children[i] == entity->node) + if(curr_parent->transform.children[i] == entity->id) { index = i; break; @@ -66,11 +64,10 @@ void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) 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); + array_remove_at(curr_parent->transform.children, index); + entity->transform.parent = new_parent->id; + array_push(new_parent, entity->id, int); + transform_update_transmat(&entity->transform); } else { @@ -88,9 +85,10 @@ 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) + if(entity_list[i].id != -1) entity_remove(i); } + entity_post_update(); } struct Entity* scene_find(const char* name) @@ -107,9 +105,9 @@ 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++) + for(int i = 0; i < array_len(parent->transform.children); i++) { - struct Entity* curr_child = entity_get(parent->children[i]); + struct Entity* curr_child = entity_get(parent->transform.children[i]); if(strcmp(curr_child->name, name) == 0) { child = curr_child; @@ -123,7 +121,7 @@ struct Entity* scene_get_parent(struct Entity* entity) { assert(entity); struct Entity* parent = NULL; - if(entity->parent != -1) - parent = entity_get(entity->parent); + if(entity->transform.parent != -1) + parent = entity_get(entity->transform.parent); return parent; } diff --git a/src/scene.h b/src/scene.h index 04fc54b..f4942ab 100644 --- a/src/scene.h +++ b/src/scene.h @@ -1,5 +1,5 @@ -#ifndef scene_H -#define scene_H +#ifndef SCENE_H +#define SCENE_H struct Entity; @@ -7,8 +7,8 @@ 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, int parent_node); +struct Entity* scene_add_new(const char* name, const int type); /* Add as child of Root */ +struct Entity* scene_add_as_child(const char* name, const int type, int 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); diff --git a/src/sound.c b/src/sound.c index 4a8f27e..7d3b309 100644 --- a/src/sound.c +++ b/src/sound.c @@ -22,14 +22,10 @@ struct Sound_State }; static struct Sound_State sound_state; -static struct Sound_Source* sound_sources_list = NULL; -static int* empty_indices = NULL; -int sound_init(void) +bool sound_init(void) { - int success = 0; - sound_sources_list = array_new(struct Sound_Source); - empty_indices = array_new(int); + bool success = false; sound_state.device = alcOpenDevice(NULL); if(!sound_state.device) @@ -61,7 +57,7 @@ int sound_init(void) al_check(alListener3f(AL_POSITION, 0.f, 0.f, 0.f)) al_check(alListenerfv(AL_ORIENTATION, orientation)) - success = 1; + success = true; return success; } @@ -71,27 +67,26 @@ void sound_listener_set(int listener_entity) if(sound_state.listener_entity != -1) { struct Entity* current_listener = entity_get(sound_state.listener_entity); - current_listener->is_listener = 0; + current_listener->is_listener = false; } sound_state.listener_entity = listener_entity; struct Entity* entity = entity_get(listener_entity); - entity->is_listener = 1; + entity->is_listener = true; sound_listener_update(); } void sound_listener_update(void) { if(sound_state.listener_entity == -1) return; - struct Entity* entity = entity_get(sound_state.listener_entity); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); + struct Entity* entity = entity_get(sound_state.listener_entity); vec3 abs_pos = {0.f, 0.f, 0.f}; vec3 abs_up = {0.f, 1.f, 0.f}; vec3 abs_forward = {0.f, 0.f, -1.f}; - transform_get_absolute_pos(transform, &abs_pos); - transform_get_absolute_up(transform, &abs_up); - transform_get_absolute_forward(transform, &abs_forward); + transform_get_absolute_pos(&entity->transform, &abs_pos); + transform_get_absolute_up(&entity->transform, &abs_up); + transform_get_absolute_forward(&entity->transform, &abs_forward); float orientation[] = { abs_forward.x, abs_forward.y, abs_forward.z, @@ -112,10 +107,9 @@ void sound_volume_set(float volume) al_check(alListenerf(AL_GAIN, volume)) } -void sound_source_remove(int index) +void sound_source_destroy(struct Sound_Source* source) { - assert(index > -1 && index < array_len(sound_sources_list)); - struct Sound_Source* source = &sound_sources_list[index]; + assert(source); if(!source->active) return; if(alIsBuffer(source->al_buffer_handle) == AL_TRUE) { @@ -124,21 +118,13 @@ void sound_source_remove(int index) al_check(alDeleteBuffers(1, &source->al_buffer_handle)) } if(alIsSource(source->al_source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source->al_source_handle)) - source->entity = -1; source->al_buffer_handle = 0; source->al_source_handle = 0; - source->active = 0; - array_push(empty_indices, index, int); + source->active = false; } void sound_cleanup(void) -{ - for(int i = 0; i < array_len(sound_sources_list); i++) - sound_source_remove(i); - - array_free(sound_sources_list); - array_free(empty_indices); - +{ alcMakeContextCurrent(NULL); alcDestroyContext(sound_state.context); alcCloseDevice(sound_state.device); @@ -162,39 +148,21 @@ void sound_error_check(const char* file, unsigned int line, const char* expressi } } -int sound_source_create(int entity) +void sound_source_create(struct Sound_Source* source, struct Transform* transform) { - int index = -1; - struct Sound_Source* new_source = NULL; - if(array_len(empty_indices) > 0) - { - index = *array_get_last(empty_indices, int); - array_pop(empty_indices); - new_source = &sound_sources_list[index]; - } - else - { - new_source = array_grow(sound_sources_list, struct Sound_Source); - index = array_len(sound_sources_list) - 1; - } - - new_source->entity = entity; - new_source->active = 1; - al_check(alGenSources(1, &new_source->al_source_handle)) - al_check(alGenBuffers(1, &new_source->al_buffer_handle)) - sound_source_volume_set(new_source, 1.f); - if(entity > -1) - sound_source_update(new_source); + assert(source); + source->active = true; + al_check(alGenSources(1, &source->al_source_handle)) + al_check(alGenBuffers(1, &source->al_buffer_handle)) + sound_source_volume_set(source, 1.f); + if(transform) + sound_source_update(source, transform); else - sound_source_relative_set(new_source, 1); - return index; + sound_source_relative_set(source, 1); } -void sound_source_update(struct Sound_Source* source) +void sound_source_update(struct Sound_Source* source, struct Transform* transform) { - if(source->entity < 0) return; - struct Entity* entity = entity_get(source->entity); - struct Transform* transform = entity_component_get(entity, C_TRANSFORM); vec3 abs_pos = {0.f, 0.f, 0.f}; vec3 abs_up = {0.f, 1.f, 0.f}; vec3 abs_forward = {0.f, 0.f, -1.f}; @@ -223,13 +191,13 @@ void sound_source_pitch_set(struct Sound_Source* source, float pitch) al_check(alSourcef(source->al_source_handle, AL_PITCH, pitch)) } -void sound_source_loop_set(struct Sound_Source* source, int loop) +void sound_source_loop_set(struct Sound_Source* source, bool loop) { loop = loop ? AL_TRUE : AL_FALSE; al_check(alSourcei(source->al_source_handle, AL_LOOPING, loop)) } -void sound_source_relative_set(struct Sound_Source* source, int relative) +void sound_source_relative_set(struct Sound_Source* source, bool relative) { relative = relative ? AL_TRUE : AL_FALSE; al_check(alSourcei(source->al_source_handle, AL_SOURCE_RELATIVE, relative)); @@ -263,7 +231,7 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name) return; } - int mono = wav_spec.channels == 1 ? 1 : 0; + bool mono = wav_spec.channels == 1 ? true : false; int format = -1; if(mono) { @@ -277,10 +245,12 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name) else { /* TODO: FIX THIS!!!! This should resemble the if condition */ - if(wav_spec.format == AUDIO_U8) + if(wav_spec.format == AUDIO_U8 || wav_spec.format == AUDIO_S8) format = AL_FORMAT_STEREO8; - else if(wav_spec.format == AUDIO_S16) + else if(wav_spec.format == AUDIO_S16 || wav_spec.format == AUDIO_S16LSB || wav_spec.format == AUDIO_S16MSB || wav_spec.format == AUDIO_S16SYS) format = AL_FORMAT_STEREO16; + else if(wav_spec.format == AUDIO_F32 || wav_spec.format == AUDIO_F32LSB || wav_spec.format == AUDIO_F32MSB || wav_spec.format == AUDIO_F32SYS || wav_spec.format == AUDIO_S32 || wav_spec.format == AUDIO_S32LSB) + format = AL_FORMAT_STEREO_FLOAT32; } if(format == -1) @@ -295,12 +265,6 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name) SDL_FreeWAV(wav_data); } -struct Sound_Source* sound_source_get(int index) -{ - assert(index > -1 && index < array_len(sound_sources_list)); - return &sound_sources_list[index]; -} - void sound_source_play(struct Sound_Source* source) { al_check(alSourcePlay(source->al_source_handle)) } void sound_source_pause(struct Sound_Source* source) { al_check(alSourcePause(source->al_source_handle)) } void sound_source_rewind(struct Sound_Source* source) { al_check(alSourceRewind(source->al_source_handle)) } diff --git a/src/sound.h b/src/sound.h index 3442334..c4943ac 100644 --- a/src/sound.h +++ b/src/sound.h @@ -9,15 +9,10 @@ #define al_check(expr) expr; #endif -struct Sound_Source -{ - int entity; - uint al_source_handle; - uint al_buffer_handle; - int active; -}; +struct Sound_Source; +struct Transform; -int sound_init(void); +bool sound_init(void); void sound_cleanup(void); void sound_volume_set(float volume); void sound_error_check(const char* file, unsigned int line, const char* expression); @@ -26,18 +21,17 @@ void sound_listener_set(int entity); int sound_listener_get(void); void sound_listener_update(void); -struct Sound_Source* sound_source_get(int index); -int sound_source_create(int entity); -void sound_source_remove(int index); -void sound_source_update(struct Sound_Source* source); -void sound_source_volume_set(struct Sound_Source* source, float volume); -void sound_source_pitch_set(struct Sound_Source* source, float pitch); -void sound_source_load_wav(struct Sound_Source* source, const char* file_name); -void sound_source_loop_set(struct Sound_Source* source, int loop); -void sound_source_relative_set(struct Sound_Source* source, int relative); -void sound_source_play(struct Sound_Source* source); -void sound_source_pause(struct Sound_Source* source); -void sound_source_rewind(struct Sound_Source* source); -void sound_source_stop(struct Sound_Source* source); +void sound_source_create(struct Sound_Source* source, struct Transform* transform); +void sound_source_destroy(struct Sound_Source* source); +void sound_source_update(struct Sound_Source* source, struct Transform* transform); +void sound_source_volume_set(struct Sound_Source* source, float volume); +void sound_source_pitch_set(struct Sound_Source* source, float pitch); +void sound_source_load_wav(struct Sound_Source* source, const char* file_name); +void sound_source_loop_set(struct Sound_Source* source, bool loop); +void sound_source_relative_set(struct Sound_Source* source, bool relative); +void sound_source_play(struct Sound_Source* source); +void sound_source_pause(struct Sound_Source* source); +void sound_source_rewind(struct Sound_Source* source); +void sound_source_stop(struct Sound_Source* source); #endif diff --git a/src/texture.c b/src/texture.c index 62cdf6b..3af6e48 100644 --- a/src/texture.c +++ b/src/texture.c @@ -380,7 +380,7 @@ int texture_create(const char* name, int type, const void* data) { - assert(name && texture_unit > -1 && texture_unit <= TU_SHADOWMAP4); + assert(texture_unit > -1 && texture_unit <= TU_SHADOWMAP4); int index = -1; uint handle = 0; int success = create_gl_texture(&handle, width, height, format, internal_format, type, data); @@ -398,7 +398,7 @@ int texture_create(const char* name, new_tex = array_grow(texture_list, struct Texture); index = array_len(texture_list) - 1; } - new_tex->name = str_new(name); + new_tex->name = name ? str_new(name) : str_new("texture_%d", index); new_tex->handle = handle; new_tex->ref_count = 1; new_tex->texture_unit = texture_unit; diff --git a/src/transform.c b/src/transform.c index d221dea..1ceee55 100644 --- a/src/transform.c +++ b/src/transform.c @@ -5,46 +5,16 @@ #include "utils.h" #include -static struct Transform* transform_list; -static int* empty_indices; - -void transform_init(void) +void transform_create(struct Transform* transform, int parent_entity) { - transform_list = array_new(struct Transform); - empty_indices = array_new(int); -} - -void transform_cleanup(void) -{ - array_free(transform_list); - array_free(empty_indices); -} - -int transform_create(int node) -{ - int index = -1; - if(node > -1) - { - struct Transform* new_transform = NULL; - if(array_len(empty_indices) > 0) - { - index = *array_get_last(empty_indices, int); - array_pop(empty_indices); - new_transform = &transform_list[index]; - } - else - { - new_transform = array_grow(transform_list, struct Transform); - index = array_len(transform_list) - 1; - } - new_transform->node = node; - vec3_fill(&new_transform->position, 0.f, 0.f, 0.f); - vec3_fill(&new_transform->scale, 1.f, 1.f, 1.f); - quat_identity(&new_transform->rotation); - mat4_identity(&new_transform->trans_mat); - transform_update_transmat(new_transform); - } - return index; + assert(transform); + vec3_fill(&transform->position, 0.f, 0.f, 0.f); + vec3_fill(&transform->scale, 1.f, 1.f, 1.f); + quat_identity(&transform->rotation); + mat4_identity(&transform->trans_mat); + transform->parent = parent_entity; + transform->children = array_new(int); + transform_update_transmat(transform); } void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space) @@ -57,16 +27,20 @@ void transform_translate(struct Transform* transform, vec3* amount, enum Transfo } else if(space == TS_PARENT) { - struct Entity* parent = entity_get_parent(transform->node); - struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); - quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount); + struct Entity* parent = entity_get_parent(transform->parent); + if(parent) + { + struct Transform* parent_tran = &parent->transform; + quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount); + } } vec3_add(&transform->position, &transform->position, &translation_amount); transform_update_transmat(transform); } -void transform_rotate(struct Transform* transform, - vec3* axis, - float angle, + +void transform_rotate(struct Transform* transform, + vec3* axis, + float angle, enum Transform_Space space) { quat new_rot; @@ -158,42 +132,48 @@ void transform_update_transmat(struct Transform* transform) mat4_mul(&transform->trans_mat, &transform->trans_mat, &rotation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &scale); - struct Entity* entity = entity_get(transform->node); - if(entity) /* Only update if transform is attached to an entity */ + struct Entity* parent = entity_get(transform->parent); + if(parent) { - 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); - } + struct Transform* parent_tran = &parent->transform; + mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat); + } - /* Update all children */ - int children = array_len(entity->children); - if(children > 0) + /* Update all children */ + int children = array_len(transform->children); + if(children > 0) + { + for(int i = 0; i < children; i++) { - for(int i = 0; i < 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); - } + struct Entity* child = entity_get(transform->children[i]); + struct Transform* child_tran = &child->transform; + transform_update_transmat(child_tran); } - entity_sync_components(entity); } + transform->is_modified = true; } -struct Transform* transform_get(int index) +void transform_destroy(struct Transform* transform) { - assert(index > -1 && index < array_len(transform_list)); - return &transform_list[index]; -} - -void transform_remove(int index) -{ - assert(index > -1 && index < array_len(transform_list)); - transform_list[index].node = -1; - array_push(empty_indices, index, int); + assert(transform); + int children = array_len(transform->children); + if(children > 0) + { + for(int i = 0; i < children; i++) + { + struct Entity* child = entity_get(transform->children[i]); + child->marked_for_deletion = true; + } + } + + /* Remove transform */ + array_free(transform->children); + vec3_fill(&transform->position, 0.f, 0.f, 0.f); + vec3_fill(&transform->scale, 1.f, 1.f, 1.f); + quat_identity(&transform->rotation); + mat4_identity(&transform->trans_mat); + transform->parent = -1; + transform->is_modified = false; } void transform_set_position(struct Transform* transform, vec3* new_position) @@ -204,11 +184,10 @@ void transform_set_position(struct Transform* transform, vec3* new_position) void transform_get_absolute_pos(struct Transform* transform, vec3* res) { - struct Entity* entity = entity_get(transform->node); - struct Entity* parent = entity_get(entity->parent); + struct Entity* parent = entity_get(transform->parent); if(parent) { - struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); + struct Transform* parent_tran = &parent->transform; transform_get_absolute_pos(parent_tran, res); } vec3_add(res, res, &transform->position); @@ -216,11 +195,10 @@ void transform_get_absolute_pos(struct Transform* transform, vec3* res) void transform_get_absolute_scale(struct Transform* transform, vec3* res) { - struct Entity* entity = entity_get(transform->node); - struct Entity* parent = entity_get(entity->parent); + struct Entity* parent = entity_get(transform->parent); if(parent) { - struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); + struct Transform* parent_tran = &parent->transform; transform_get_absolute_scale(parent_tran, res); } vec3_add(res, res, &transform->scale); @@ -228,11 +206,10 @@ void transform_get_absolute_scale(struct Transform* transform, vec3* res) void transform_get_absolute_rot(struct Transform* transform, quat* res) { - struct Entity* entity = entity_get(transform->node); - struct Entity* parent = entity_get(entity->parent); + struct Entity* parent = entity_get(transform->parent); if(parent) { - struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); + struct Transform* parent_tran = &parent->transform; transform_get_absolute_rot(parent_tran, res); } quat_mul(res, res, &transform->rotation); diff --git a/src/transform.h b/src/transform.h index 51489f6..7e456dc 100644 --- a/src/transform.h +++ b/src/transform.h @@ -1,24 +1,14 @@ -#ifndef _transform_H -#define _transform_H +#ifndef TRANSFORM_H +#define TRANSFORM_H #include "linmath.h" enum Transform_Space { TS_LOCAL, TS_PARENT, TS_WORLD}; -struct Transform -{ - int node; - vec3 position; - vec3 scale; - quat rotation; - mat4 trans_mat; -}; +struct Transform; -struct Transform* transform_get(int index); -void transform_remove(int index); -void transform_init(void); -void transform_cleanup(void); -int transform_create(int node); +void transform_create(struct Transform* transform, int parent_entity); +void transform_destroy(struct Transform* transform); void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space); void transform_rotate(struct Transform* transform, vec3* axis,