diff --git a/README.md b/README.md index 0f2e3be..75775df 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,26 @@ - ## TODO + - Re-Implement player logic + - Re-Implement saving/loading scene to/from files + - Bring back functionality and complete overhaul + - Break-up entity into base and derived entities + - Move/Modify logic as necessary + - Scene should contain fixed size lists of entites according to their types for example, separate lists of Lights, Static_Meshes, + AI entities, Particles etc + - Entity post-update logic would move to scene as well, after update scene iterates through each specific list and does whatever + is necessary + - All this would enable us to hold valid poiniters to other entites, I suspect that would result in some other changes as well + - Make materials/uniforms simpler. No need for generic materials defined in text + - Possibly embed material into model somehow to make it easier to set material uniforms like colour etc + - Create new system inside game_state to handle non-spatial sounds for music/ui etc + - Setup scene such that player and editor camera are always added to every scene + - Try to remove as much unnecessary global state as possible for example move textures/shaders/framebuffers or create a resource + system and move textures/shaders/sounds/geometry etc to that and framebuffer/shaders to renderer - Work on (yet another)entity refactor before moving on to serialization + - Implement cross-hatching shader + - Update README's TODO section to reflect the current state of things and the things that are actually left to do + - Implement collision/physics data serialization, read and write. - Physics forces/torque etc - Implement physics debug visualizations for other primitives and tri mesh shapes @@ -373,3 +392,4 @@ * Implemented immediate mode renderer that can draw arbitrary points, lines and triangles * Converted IM_Vertex array to only be used as temporary storage for vertices between begin and end calls * Implemented Debug physics mesh drawing for box and sphere primitives + * Completed Phase 1 of codebase refactoring diff --git a/src/game/sound.c b/src/game/sound.c index a6f7c5c..41c0009 100644 --- a/src/game/sound.c +++ b/src/game/sound.c @@ -199,9 +199,6 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) struct Sound_Source_Buffer* source = NULL; - long size = 0L; - char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); - //See if we've already loaded this file if(hashmap_value_exists(sound_sources, filename)) { @@ -209,6 +206,9 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) return source; } + long size = 0L; + char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); + source = malloc(sizeof(*source)); if(!source) { @@ -245,10 +245,11 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) source->type = ST_WAV_STREAM; } break; - default: log_error("sound:source_create", "Invalid source type %d", type); return 0; + default: log_error("sound:source_create", "Invalid source type %d", type); break; } hashmap_ptr_set(sound_sources, filename, (void*)source); + if(memory) free(memory); return source; } diff --git a/src/libsymmetry/bounding_volumes.c b/src/libsymmetry/bounding_volumes.c index 1491865..c7b2128 100644 --- a/src/libsymmetry/bounding_volumes.c +++ b/src/libsymmetry/bounding_volumes.c @@ -1,12 +1,9 @@ #include "bounding_volumes.h" -#include "entity.h" -#include "transform.h" #include -int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Entity* entity) +int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale) { - struct Transform* transform = &entity->transform; vec3 min, max, size, center, half_ext, half_size; vec3_fill(&min, 0.f, 0.f, 0.f); vec3_fill(&max, 0.f, 0.f, 0.f); @@ -15,10 +12,10 @@ int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Ent vec3_fill(&half_ext, 0.f, 0.f, 0.f); vec3_fill(&half_size, 0.f, 0.f, 0.f); - vec3_add(&min, &box->min, &transform->position); - vec3_mul(&min, &min, &transform->scale); - vec3_add(&max, &box->max, &transform->position); - vec3_mul(&min, &min, &transform->scale); + vec3_add(&min, &box->min, box_abs_position); + vec3_mul(&min, &min, box_abs_scale); + vec3_add(&max, &box->max, box_abs_position); + vec3_mul(&min, &min, box_abs_scale); vec3_sub(&size, &max, &min); vec3_add(¢er, &max, &min); vec3_scale(¢er, ¢er, 0.5f); @@ -37,22 +34,18 @@ int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Ent return IT_INSIDE; } -int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Entity* entity) +int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, vec3* sphere_abs_pos, vec3* sphere_abs_scale) { int intersect_type = IT_INSIDE; - vec3 center, abs_pos, abs_scale; + vec3 center; float radius = sphere->radius; vec3_fill(¢er, 0.f, 0.f, 0.f); - vec3_fill(&abs_pos, 0.f, 0.f, 0.f); - vec3_fill(&abs_scale, 0.f, 0.f, 0.f); - transform_get_absolute_position(entity, &abs_pos); - transform_get_absolute_scale(entity, &abs_scale); - float max_scale_dimension = fabsf(abs_scale.x); - if(fabsf(abs_scale.y) > max_scale_dimension) max_scale_dimension = fabsf(abs_scale.y); - if(fabsf(abs_scale.z) > max_scale_dimension) max_scale_dimension = fabsf(abs_scale.z); + float max_scale_dimension = fabsf(sphere_abs_scale->x); + if(fabsf(sphere_abs_scale->y) > max_scale_dimension) max_scale_dimension = fabsf(sphere_abs_scale->y); + if(fabsf(sphere_abs_scale->z) > max_scale_dimension) max_scale_dimension = fabsf(sphere_abs_scale->z); radius *= max_scale_dimension; - vec3_add(¢er, &sphere->center, &abs_pos); + vec3_add(¢er, &sphere->center, sphere_abs_pos); //vec3_mul(¢er, ¢er, &transform->scale); for(int i = 0; i < 6; i++) diff --git a/src/libsymmetry/bounding_volumes.h b/src/libsymmetry/bounding_volumes.h index ecae08d..4c4377e 100644 --- a/src/libsymmetry/bounding_volumes.h +++ b/src/libsymmetry/bounding_volumes.h @@ -4,8 +4,6 @@ #include "../common/linmath.h" #include "../common/num_types.h" -struct Entity; - struct Bounding_Box { vec3 min; @@ -36,8 +34,8 @@ enum Frustum_Planes FP_NUM_PLANES }; -int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Entity* entity); -int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Entity* entity); +int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale); +int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Transform* transform); bool bv_intersect_frustum_point(vec4* frustum, const vec3* point); #endif diff --git a/src/libsymmetry/camera.c b/src/libsymmetry/camera.c index ebe21d4..44ce2e3 100644 --- a/src/libsymmetry/camera.c +++ b/src/libsymmetry/camera.c @@ -19,9 +19,8 @@ static void update_frustum(struct Camera* camera); -void camera_destroy(struct Entity* entity) +void camera_reset(struct Camera* camera) { - struct Camera* camera = &entity->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); @@ -36,9 +35,8 @@ void camera_destroy(struct Entity* entity) vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0); } -void camera_create(struct Entity* entity, int width, int height) +void camera_init(struct Camera* camera, int width, int height) { - struct Camera* camera = &entity->camera; camera->fbo = -1; camera->render_tex = -1; camera->depth_tex = -1; @@ -55,35 +53,32 @@ void camera_create(struct Entity* entity, int width, int height) 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); - camera_update_view(entity); - camera_update_proj(entity); + camera_update_view(camera); + camera_update_proj(camera); vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f); } -void camera_update_view_proj(struct Entity* entity) +void camera_update_view_proj(struct Camera* camera) { - struct Camera* camera = &entity->camera; mat4_identity(&camera->view_proj_mat); mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat); update_frustum(camera); } -void camera_update_view(struct Entity* entity) +void camera_update_view(struct Camera* camera) { - struct Camera* camera = &entity->camera; vec3 lookat = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f}; - transform_get_absolute_lookat(entity, &lookat); - transform_get_absolute_up(entity, &up); - transform_get_absolute_position(entity, &position); + transform_get_absolute_lookat(&camera->base, &lookat); + transform_get_absolute_up(&camera->base, &up); + transform_get_absolute_position(&camera->base, &position); mat4_lookat(&camera->view_mat, &position, &lookat, &up); - camera_update_view_proj(entity); + camera_update_view_proj(&camera->base); } -void camera_update_proj(struct Entity* entity) +void camera_update_proj(struct Camera* camera) { - struct Camera* camera = &entity->camera; if(!camera->ortho) { mat4_perspective(&camera->proj_mat, @@ -105,10 +100,10 @@ void camera_update_proj(struct Entity* entity) camera->nearz, camera->farz); } - camera_update_view_proj(entity); + camera_update_view_proj(camera); } -void camera_attach_fbo(struct Entity* entity, +void camera_attach_fbo(struct Camera* camera, int width, int height, bool has_depth, @@ -116,7 +111,6 @@ void camera_attach_fbo(struct Entity* entity, bool resizeable) { assert(width > 0 && height > 0); - struct Camera* camera = &entity->camera; if(camera->fbo != -1) { log_error("camera:attach_fbo", "Camera already has fbo attached!"); @@ -206,17 +200,4 @@ static void update_frustum(struct Camera* camera) float length = fabsf(vec3_len(&plane_xyz)); vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length)); } -} - -/* 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); */ -/* } */ -/* } */ +} \ No newline at end of file diff --git a/src/libsymmetry/camera.h b/src/libsymmetry/camera.h index c1bad1d..ea66a86 100644 --- a/src/libsymmetry/camera.h +++ b/src/libsymmetry/camera.h @@ -3,14 +3,14 @@ #include "../common/num_types.h" -struct Entity; +struct Camera; -void camera_destroy(struct Entity* entity); -void camera_create(struct Entity* entity, int width, int height); -void camera_update_view_proj(struct Entity* entity); -void camera_update_view(struct Entity* entity); -void camera_update_proj(struct Entity* entity); -void camera_attach_fbo(struct Entity* entity, +void camera_reset(struct Camera* camera); +void camera_init(struct Camera* camera, int width, int height); +void camera_update_view_proj(struct Camera* camera); +void camera_update_view(struct Camera* camera); +void camera_update_proj(struct Camera* camera); +void camera_attach_fbo(struct Camera* camera, int width, int height, bool has_depth, diff --git a/src/libsymmetry/editor.c b/src/libsymmetry/editor.c index 3786b89..f74617a 100644 --- a/src/libsymmetry/editor.c +++ b/src/libsymmetry/editor.c @@ -201,7 +201,7 @@ void editor_update(float dt) /* Entities List */ if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED)) { - nk_layout_row_dynamic(context, 250, 1); + /*nk_layout_row_dynamic(context, 250, 1); if(nk_group_begin(context, "Entity Name", NK_WINDOW_SCROLL_AUTO_HIDE)) { struct Entity* entity_list = entity_get_all(); @@ -228,7 +228,7 @@ void editor_update(float dt) } } nk_group_end(context); - } + }*/ nk_tree_pop(context); } @@ -264,186 +264,186 @@ void editor_update(float dt) if(nk_group_begin(context, "Editor Right", NK_WINDOW_NO_SCROLLBAR)) { /* Entity Inspector */ - if(nk_tree_push(context, NK_TREE_TAB, "Inspector", NK_MAXIMIZED)) - { - const int row_height = 18; - if(editor_state.selected_entity_id != -1) - { - struct Entity* entity = entity_get(editor_state.selected_entity_id); - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT); - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id); - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity)); - nk_layout_row_dynamic(context, row_height, 2); - struct Entity* parent_ent = entity_get(entity->transform.parent); - nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT); - - /* Transform */ - { - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED); - vec3 abs_pos = {0.f, 0.f, 0.f}; - transform_get_absolute_position(entity, &abs_pos); - if(editor_widget_v3(context, &abs_pos, "Px", "Py", "Pz", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED); - quat abs_rot = {0.f, 0.f, 0.f, 1.f}; - transform_get_absolute_rot(entity, &abs_rot); - vec3 rot_angles = {0.f, 0.f, 0.f}; - rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot)); - rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot)); - rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot)); - vec3 curr_rot = {rot_angles.x, rot_angles.y, rot_angles.z}; - - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rx", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f); - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Ry", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f); - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rz", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f); - - vec3 delta = {0.f, 0.f, 0.f}; - vec3_sub(&delta, &rot_angles, &curr_rot); - - vec3 AXIS_X = {1.f, 0.f, 0.f}; - vec3 AXIS_Y = {0.f, 1.f, 0.f}; - vec3 AXIS_Z = {0.f, 0.f, 1.f}; - - const float epsilon = 0.0001f; - if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD); - if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD); - if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED); - vec3 abs_scale = {0.f, 0.f, 0.f}; - transform_get_absolute_scale(entity, &abs_scale); - if(editor_widget_v3(context, &abs_scale, "SX", "SY", "SZ", 0.1f, FLT_MAX, 1.f, 0.1f, row_height)) - { - entity->transform.scale = abs_scale; - transform_update_transmat(entity); - } - } - - /* Light */ - if(entity->type == ET_LIGHT) - { - if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED)) - { - struct Light* light = &entity->light; - if(light->type > LT_POINT) - { - nk_layout_row_dynamic(context, row_height, 1); - nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED); - } - else - { - static const char* light_types[] = {"Spot", "Directional", "Point"}; - float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX); - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT); - nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height)); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED); - nk_layout_row_dynamic(context, row_height, 1); - editor_widget_color_combov3(context, &light->color, 200, 300); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f); - - if(light->type != LT_DIR) - { - nk_layout_row_dynamic(context, row_height, 1); - light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f)); - - nk_layout_row_dynamic(context, row_height, 1); - light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f)); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f); - } - } - nk_tree_pop(context); - } - } - - /* Camera */ - if(entity->type == ET_CAMERA) - { - if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) - { - bool update = false; - struct Camera* camera = &entity->camera; - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); - bool ortho = nk_checkbox_label(context, "", &camera->ortho); - if(ortho != camera->ortho) - { - update = true; - } - - - if(!camera->ortho) - { - nk_layout_row_dynamic(context, row_height, 1); - float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); - if(new_fov != camera->fov) - { - camera->fov = new_fov; - update = true; - } - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); - } - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); - nk_layout_row_dynamic(context, row_height, 1); - editor_widget_color_combov4(context, &camera->clear_color, 200, 300); - - nk_layout_row_dynamic(context, row_height, 1); - float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f); - if(new_zoom != camera->zoom) - { - camera->zoom = new_zoom; - update = true; - } - - nk_layout_row_dynamic(context, row_height, 1); - float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); - if(new_near_z != camera->nearz) - { - camera->nearz = new_near_z; - update = true; - } - - nk_layout_row_dynamic(context, row_height, 1); - float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); - if(new_far_z != camera->farz) - { - camera->farz = new_far_z; - update = true; - } - - if(update) - { - camera_update_view(entity); - camera_update_proj(entity); - } - - nk_tree_pop(context); - } - } - } - else - { - nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED); - } - nk_tree_pop(context); - } - + //if(nk_tree_push(context, NK_TREE_TAB, "Inspector", NK_MAXIMIZED)) + //{ + // const int row_height = 18; + // if(editor_state.selected_entity_id != -1) + // { + // struct Entity* entity = entity_get(editor_state.selected_entity_id); + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT); + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id); + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity)); + // nk_layout_row_dynamic(context, row_height, 2); + // struct Entity* parent_ent = entity_get(entity->transform.parent); + // nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT); + + // /* Transform */ + // { + // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED); + // vec3 abs_pos = {0.f, 0.f, 0.f}; + // transform_get_absolute_position(entity, &abs_pos); + // if(editor_widget_v3(context, &abs_pos, "Px", "Py", "Pz", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos); + + // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED); + // quat abs_rot = {0.f, 0.f, 0.f, 1.f}; + // transform_get_absolute_rot(entity, &abs_rot); + // vec3 rot_angles = {0.f, 0.f, 0.f}; + // rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot)); + // rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot)); + // rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot)); + // vec3 curr_rot = {rot_angles.x, rot_angles.y, rot_angles.z}; + + // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rx", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f); + // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Ry", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f); + // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rz", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f); + + // vec3 delta = {0.f, 0.f, 0.f}; + // vec3_sub(&delta, &rot_angles, &curr_rot); + + // vec3 AXIS_X = {1.f, 0.f, 0.f}; + // vec3 AXIS_Y = {0.f, 1.f, 0.f}; + // vec3 AXIS_Z = {0.f, 0.f, 1.f}; + + // const float epsilon = 0.0001f; + // if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD); + // if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD); + // if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD); + + // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED); + // vec3 abs_scale = {0.f, 0.f, 0.f}; + // transform_get_absolute_scale(entity, &abs_scale); + // if(editor_widget_v3(context, &abs_scale, "SX", "SY", "SZ", 0.1f, FLT_MAX, 1.f, 0.1f, row_height)) + // { + // entity->transform.scale = abs_scale; + // transform_update_transmat(entity); + // } + // } + + // /* Light */ + // if(entity->type == ET_LIGHT) + // { + // if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED)) + // { + // struct Light* light = &entity->light; + // if(light->type > LT_POINT) + // { + // nk_layout_row_dynamic(context, row_height, 1); + // nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED); + // } + // else + // { + // static const char* light_types[] = {"Spot", "Directional", "Point"}; + // float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX); + // + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT); + // nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height)); + // + // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED); + // nk_layout_row_dynamic(context, row_height, 1); + // editor_widget_color_combov3(context, &light->color, 200, 300); + + // nk_layout_row_dynamic(context, row_height, 1); + // nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f); + + // if(light->type != LT_DIR) + // { + // nk_layout_row_dynamic(context, row_height, 1); + // light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f)); + + // nk_layout_row_dynamic(context, row_height, 1); + // light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f)); + + // nk_layout_row_dynamic(context, row_height, 1); + // nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1); + + // nk_layout_row_dynamic(context, row_height, 1); + // nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f); + // } + // } + // nk_tree_pop(context); + // } + // } + + // /* Camera */ + // if(entity->type == ET_CAMERA) + // { + // if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) + // { + // bool update = false; + // struct Camera* camera = &entity->camera; + // + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); + // bool ortho = nk_checkbox_label(context, "", &camera->ortho); + // if(ortho != camera->ortho) + // { + // update = true; + // } + // + + // if(!camera->ortho) + // { + // nk_layout_row_dynamic(context, row_height, 1); + // float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); + // if(new_fov != camera->fov) + // { + // camera->fov = new_fov; + // update = true; + // } + + // nk_layout_row_dynamic(context, row_height, 2); + // nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); + // } + + // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); + // nk_layout_row_dynamic(context, row_height, 1); + // editor_widget_color_combov4(context, &camera->clear_color, 200, 300); + + // nk_layout_row_dynamic(context, row_height, 1); + // float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f); + // if(new_zoom != camera->zoom) + // { + // camera->zoom = new_zoom; + // update = true; + // } + + // nk_layout_row_dynamic(context, row_height, 1); + // float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); + // if(new_near_z != camera->nearz) + // { + // camera->nearz = new_near_z; + // update = true; + // } + // + // nk_layout_row_dynamic(context, row_height, 1); + // float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); + // if(new_far_z != camera->farz) + // { + // camera->farz = new_far_z; + // update = true; + // } + + // if(update) + // { + // camera_update_view(entity); + // camera_update_proj(entity); + // } + + // nk_tree_pop(context); + // } + // } + // } + // else + // { + // nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED); + // } + // nk_tree_pop(context); + //} + // nk_group_end(context); } } diff --git a/src/libsymmetry/entity.c b/src/libsymmetry/entity.c index b0b0996..73762cb 100644 --- a/src/libsymmetry/entity.c +++ b/src/libsymmetry/entity.c @@ -25,345 +25,171 @@ #define MAX_ENTITY_PROP_LEN 256 #define MAX_LINE_LEN 512 -static struct Entity* entity_list; -static int* empty_indices; - -void entity_init(void) -{ - entity_list = array_new(struct Entity); - empty_indices = array_new(int); -} - -void entity_cleanup(void) +void entity_init(struct Entity* entity, const char* name, struct Entity* parent) { - if(array_len(empty_indices) < array_len(entity_list)) - { - for(int i = 0; i < array_len(entity_list); i++) - entity_remove(i); - } + assert(entity); - array_free(entity_list); - array_free(empty_indices); + strncpy(entity->name, name ? name : "DEFAULT_ENTITY_NAME", MAX_ENTITY_NAME_LEN); + entity->name[MAX_ENTITY_NAME_LEN - 1] = '\0'; + entity->type = ET_DEFAULT; + entity->active = true; + entity->marked_for_deletion = false; + entity->editor_selected = false; + transform_init(entity, parent); } -void entity_remove(int index) +void entity_reset(struct Entity * entity, int id) { - struct Entity* entity = &entity_list[index]; - - transform_destroy(entity); - switch(entity->type) - { - case ET_CAMERA: camera_destroy(entity); break; - case ET_LIGHT: light_destroy(entity); break; - case ET_STATIC_MESH: model_destroy(entity); break; - case ET_SOUND_SOURCE: - { - platform->sound.source_instance_destroy(entity->sound_source.source_instance); - entity->sound_source.source_instance = 0; - } - break; - case ET_ROOT: break; - default: log_error("entity:remove", "Invalid entity type"); break; - }; - - if(entity->has_collision) - { - if(entity->collision.rigidbody) - platform->physics.body_remove(entity->collision.rigidbody); - else - platform->physics.cs_remove(entity->collision.collision_shape); - entity->has_collision = false; - entity->collision.rigidbody = NULL; - entity->collision.on_collision = NULL; - } - - if(entity->is_listener) - { - platform->sound.listener_update(0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 1.f, 0.f); - entity->is_listener = false; - } - - entity->id = -1; + assert(entity); + entity->id = id; + entity->active = false; entity->marked_for_deletion = false; - entity->editor_selected = 0; - entity->renderable = false; + entity->editor_selected = false; memset(entity->name, '\0', MAX_ENTITY_NAME_LEN); - array_push(empty_indices, index, int); -} - -struct Entity* entity_create(const char* name, const int type, int parent_id) -{ - struct Entity* new_entity = NULL; - int index = -1; - - if(array_len(empty_indices) > 0) - { - index = *array_get_last(empty_indices, int); - array_pop(empty_indices); - new_entity = &entity_list[index]; - } - else - { - new_entity = array_grow(entity_list, struct Entity); - index = array_len(entity_list) - 1; - } - - strncpy(new_entity->name, name ? name : "DEFAULT_ENTITY_NAME", MAX_ENTITY_NAME_LEN); - new_entity->name[MAX_ENTITY_NAME_LEN - 1] = '\0'; - new_entity->id = index; - new_entity->is_listener = false; - new_entity->type = type; - new_entity->marked_for_deletion = false; - new_entity->renderable = false; - new_entity->has_collision = false; - new_entity->collision.on_collision = NULL; - new_entity->collision.rigidbody = NULL; - new_entity->editor_selected = 0; - transform_create(new_entity, parent_id); - return new_entity; -} - -struct Entity* entity_get(int index) -{ - struct Entity* entity = NULL; - if(index >= 0 && index < array_len(entity_list)) - entity = &entity_list[index]; - return entity; -} - -struct Entity* entity_find(const char* name) -{ - /* Bruteforce search all entities and return the first match */ - struct Entity* entity = NULL; - for(int i = 0; i < array_len(entity_list); i++) - { - struct Entity* curr_ent = &entity_list[i]; - if(curr_ent->id == -1) - continue; - if(strcmp(curr_ent->name, name) == 0) - { - entity = curr_ent; - break; - } - } - return entity; -} - -void entity_post_update(void) -{ - for(int i = 0; i < array_len(entity_list); i++) - { - struct Entity* entity = &entity_list[i]; - if(entity->id == -1) continue; - - if(entity->marked_for_deletion) - { - entity_remove(i); - continue; - } - } - - for(int i = 0; i < array_len(entity_list); i++) - { - struct Entity* entity = &entity_list[i]; - if(entity->id == -1) continue; - - if(entity->transform.is_modified) - { - if(entity->type == ET_CAMERA) - { - camera_update_view(entity); - } - else - { - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_fwd = {0.f, 0.f, -1.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - transform_get_absolute_position(entity, &abs_pos); - transform_get_absolute_forward(entity, &abs_fwd); - transform_get_absolute_up(entity, &abs_up); - - if(entity->type == ET_SOUND_SOURCE) - platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); - - if(entity->is_listener) - { - platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, - abs_fwd.x, abs_fwd.y, abs_fwd.z, - abs_up.x, abs_up.y, abs_up.z); - } - - - if(entity->has_collision && entity->transform.sync_physics) - { - if(entity->collision.rigidbody) - { - quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; - transform_get_absolute_rot(entity, &abs_rot); - platform->physics.body_rotation_set(entity->collision.rigidbody, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w); - platform->physics.body_position_set(entity->collision.rigidbody, abs_pos.x, abs_pos.y, abs_pos.z); - } - entity->transform.sync_physics = false; - } - } - } - } } -struct Entity* entity_get_all(void) -{ - return entity_list; -} - -struct Entity* entity_get_parent(int node) -{ - struct Entity* parent = NULL; - struct Entity* entity = entity_get(node); - if(entity) parent = entity_get(entity->transform.parent); - return parent; -} bool entity_write(struct Entity* entity, struct Parser_Object* object) { - if(!object) - { - log_error("entity:write", "Invalid object"); - return false; - } - - /* First write all properties common to all entity types */ - struct Hashmap* entity_data = object->data; - - hashmap_str_set(entity_data, "name", entity->name); - hashmap_int_set(entity_data, "type", entity->type); - hashmap_bool_set(entity_data, "is_listener", entity->is_listener); - hashmap_bool_set(entity_data, "renderable", entity->renderable); - hashmap_bool_set(entity_data, "has_collision", entity->has_collision); - - if(entity->has_collision) - { - if(entity->collision.rigidbody) - hashmap_bool_set(entity_data, "has_rigidbody", true); - else - hashmap_bool_set(entity_data, "has_rigidbody", false); - - int shape_type = platform->physics.cs_type_get(entity->collision.collision_shape); - hashmap_int_set(entity_data, "collision_shape_type", shape_type); - switch(shape_type) - { - case CST_BOX: - { - float x, y, z; - x = y = z = 0.f; - platform->physics.cs_box_params_get(entity->collision.collision_shape, &x, &y, &z); - hashmap_float_set(entity_data, "collision_shape_x", x); - hashmap_float_set(entity_data, "collision_shape_y", y); - hashmap_float_set(entity_data, "collision_shape_z", z); - } - break; - case CST_SPHERE: - { - float radius = 0.f; - platform->physics.cs_sphere_radius_get(entity->collision.collision_shape); - hashmap_float_set(entity_data, "collision_shape_radius", radius); - } - break; - case CST_CAPSULE: - { - float length = 0.f, radius = 0.f; - platform->physics.cs_capsule_params_get(entity->collision.collision_shape, &radius, &length); - hashmap_float_set(entity_data, "collision_shape_length", length); - hashmap_float_set(entity_data, "collision_shape_radius", radius); - } - break; - case CST_PLANE: - { - float a, b, c, d; - platform->physics.cs_plane_params_get(entity->collision.collision_shape, &a, &b, &c, &d); - hashmap_float_set(entity_data, "collision_shape_a", a); - hashmap_float_set(entity_data, "collision_shape_b", b); - hashmap_float_set(entity_data, "collision_shape_c", c); - hashmap_float_set(entity_data, "collision_shape_d", d); - } - break; - default: break; - } - - } - - struct Entity* parent = entity_get_parent(entity->id); - hashmap_str_set(entity_data, "parent", parent ? parent->name : "NONE"); - - /* Transform */ - hashmap_vec3_set(entity_data, "position", &entity->transform.position); - hashmap_vec3_set(entity_data, "scale", &entity->transform.scale); - hashmap_quat_set(entity_data, "rotation", &entity->transform.rotation); - switch(entity->type) - { - case ET_CAMERA: - { - struct Camera* camera = &entity->camera; - hashmap_bool_set(entity_data, "ortho", camera->ortho); - hashmap_bool_set(entity_data, "resizeable", camera->resizeable); - hashmap_float_set(entity_data, "fov", camera->fov); - hashmap_float_set(entity_data, "zoom", camera->zoom); - hashmap_float_set(entity_data, "nearz", camera->nearz); - hashmap_float_set(entity_data, "farz", camera->farz); - hashmap_vec4_set(entity_data, "clear_color", &camera->clear_color); - if(entity->camera.fbo != -1) - { - hashmap_bool_set(entity_data, "has_fbo", true); - hashmap_int_set(entity_data, "fbo_height", framebuffer_height_get(camera->fbo)); - hashmap_int_set(entity_data, "fbo_width", framebuffer_width_get(camera->fbo)); - hashmap_bool_set(entity_data, "fbo_has_render_tex", camera->render_tex == -1 ? false : true); - hashmap_bool_set(entity_data, "fbo_has_depth_tex", camera->depth_tex == -1 ? false : true); - } - else - { - hashmap_bool_set(entity_data, "has_fbo", true); - } - break; - } - case ET_STATIC_MESH: - { - /* TODO: Change this after adding proper support for exported models from blender */ - struct Material* material = material_get(entity->model.material); - struct Geometry* geom = geom_get(entity->model.geometry_index); - hashmap_str_set(entity_data, "material", material->name); - hashmap_str_set(entity_data, "geometry", geom->filename); - break; - } - case ET_LIGHT: - { - struct Light* light = &entity->light; - hashmap_int_set(entity_data, "light_type", light->type); - hashmap_float_set(entity_data, "outer_angle", light->outer_angle); - hashmap_float_set(entity_data, "inner_angle", light->inner_angle); - hashmap_float_set(entity_data, "falloff", light->falloff); - hashmap_float_set(entity_data, "radius", light->radius); - hashmap_float_set(entity_data, "intensity", light->intensity); - hashmap_float_set(entity_data, "depth_bias", light->depth_bias); - hashmap_bool_set(entity_data, "valid", light->valid); - hashmap_bool_set(entity_data, "cast_shadow", light->cast_shadow); - hashmap_bool_set(entity_data, "pcf_enabled", light->pcf_enabled); - hashmap_vec3_set(entity_data, "color", &light->color); - break; - } - case ET_SOUND_SOURCE: - { - struct Sound_Source* sound_source = &entity->sound_source; - hashmap_str_set(entity_data, "source_filename", sound_source->source_filename); - hashmap_bool_set(entity_data, "playing", sound_source->playing); - hashmap_int_set(entity_data, "sound_type", sound_source->type); - hashmap_bool_set(entity_data, "loop", sound_source->loop); - hashmap_float_set(entity_data, "volume", sound_source->volume); - hashmap_float_set(entity_data, "sound_min_distance", sound_source->min_distance); - hashmap_float_set(entity_data, "sound_max_distance", sound_source->max_distance); - hashmap_float_set(entity_data, "rolloff_factor", sound_source->rolloff_factor); - hashmap_int_set(entity_data, "sound_attenuation_type", sound_source->attenuation_type); - break; - } - }; + //if(!object) + //{ + // log_error("entity:write", "Invalid object"); + // return false; + //} + + ///* First write all properties common to all entity types */ + //struct Hashmap* entity_data = object->data; + + //hashmap_str_set(entity_data, "name", entity->name); + //hashmap_int_set(entity_data, "type", entity->type); + //hashmap_bool_set(entity_data, "is_listener", entity->is_listener); + //hashmap_bool_set(entity_data, "renderable", entity->renderable); + //hashmap_bool_set(entity_data, "has_collision", entity->has_collision); + + //if(entity->has_collision) + //{ + // if(entity->collision.rigidbody) + // hashmap_bool_set(entity_data, "has_rigidbody", true); + // else + // hashmap_bool_set(entity_data, "has_rigidbody", false); + + // int shape_type = platform->physics.cs_type_get(entity->collision.collision_shape); + // hashmap_int_set(entity_data, "collision_shape_type", shape_type); + // switch(shape_type) + // { + // case CST_BOX: + // { + // float x, y, z; + // x = y = z = 0.f; + // platform->physics.cs_box_params_get(entity->collision.collision_shape, &x, &y, &z); + // hashmap_float_set(entity_data, "collision_shape_x", x); + // hashmap_float_set(entity_data, "collision_shape_y", y); + // hashmap_float_set(entity_data, "collision_shape_z", z); + // } + // break; + // case CST_SPHERE: + // { + // float radius = 0.f; + // platform->physics.cs_sphere_radius_get(entity->collision.collision_shape); + // hashmap_float_set(entity_data, "collision_shape_radius", radius); + // } + // break; + // case CST_CAPSULE: + // { + // float length = 0.f, radius = 0.f; + // platform->physics.cs_capsule_params_get(entity->collision.collision_shape, &radius, &length); + // hashmap_float_set(entity_data, "collision_shape_length", length); + // hashmap_float_set(entity_data, "collision_shape_radius", radius); + // } + // break; + // case CST_PLANE: + // { + // float a, b, c, d; + // platform->physics.cs_plane_params_get(entity->collision.collision_shape, &a, &b, &c, &d); + // hashmap_float_set(entity_data, "collision_shape_a", a); + // hashmap_float_set(entity_data, "collision_shape_b", b); + // hashmap_float_set(entity_data, "collision_shape_c", c); + // hashmap_float_set(entity_data, "collision_shape_d", d); + // } + // break; + // default: break; + // } + + //} + + //struct Entity* parent = entity_get_parent(entity->id); + //hashmap_str_set(entity_data, "parent", parent ? parent->name : "NONE"); + + ///* Transform */ + //hashmap_vec3_set(entity_data, "position", &entity->transform.position); + //hashmap_vec3_set(entity_data, "scale", &entity->transform.scale); + //hashmap_quat_set(entity_data, "rotation", &entity->transform.rotation); + //switch(entity->type) + //{ + //case ET_CAMERA: + //{ + // struct Camera* camera = &entity->camera; + // hashmap_bool_set(entity_data, "ortho", camera->ortho); + // hashmap_bool_set(entity_data, "resizeable", camera->resizeable); + // hashmap_float_set(entity_data, "fov", camera->fov); + // hashmap_float_set(entity_data, "zoom", camera->zoom); + // hashmap_float_set(entity_data, "nearz", camera->nearz); + // hashmap_float_set(entity_data, "farz", camera->farz); + // hashmap_vec4_set(entity_data, "clear_color", &camera->clear_color); + // if(entity->camera.fbo != -1) + // { + // hashmap_bool_set(entity_data, "has_fbo", true); + // hashmap_int_set(entity_data, "fbo_height", framebuffer_height_get(camera->fbo)); + // hashmap_int_set(entity_data, "fbo_width", framebuffer_width_get(camera->fbo)); + // hashmap_bool_set(entity_data, "fbo_has_render_tex", camera->render_tex == -1 ? false : true); + // hashmap_bool_set(entity_data, "fbo_has_depth_tex", camera->depth_tex == -1 ? false : true); + // } + // else + // { + // hashmap_bool_set(entity_data, "has_fbo", true); + // } + // break; + //} + //case ET_STATIC_MODEL: + //{ + // /* TODO: Change this after adding proper support for exported models from blender */ + // struct Material* material = material_get(entity->model.material); + // struct Geometry* geom = geom_get(entity->model.geometry_index); + // hashmap_str_set(entity_data, "material", material->name); + // hashmap_str_set(entity_data, "geometry", geom->filename); + // break; + //} + //case ET_LIGHT: + //{ + // struct Light* light = &entity->light; + // hashmap_int_set(entity_data, "light_type", light->type); + // hashmap_float_set(entity_data, "outer_angle", light->outer_angle); + // hashmap_float_set(entity_data, "inner_angle", light->inner_angle); + // hashmap_float_set(entity_data, "falloff", light->falloff); + // hashmap_float_set(entity_data, "radius", light->radius); + // hashmap_float_set(entity_data, "intensity", light->intensity); + // hashmap_float_set(entity_data, "depth_bias", light->depth_bias); + // hashmap_bool_set(entity_data, "valid", light->valid); + // hashmap_bool_set(entity_data, "cast_shadow", light->cast_shadow); + // hashmap_bool_set(entity_data, "pcf_enabled", light->pcf_enabled); + // hashmap_vec3_set(entity_data, "color", &light->color); + // break; + //} + //case ET_SOUND_SOURCE: + //{ + // struct Sound_Source* sound_source = &entity->sound_source; + // hashmap_str_set(entity_data, "source_filename", sound_source->source_filename); + // hashmap_bool_set(entity_data, "playing", sound_source->playing); + // hashmap_int_set(entity_data, "sound_type", sound_source->type); + // hashmap_bool_set(entity_data, "loop", sound_source->loop); + // hashmap_float_set(entity_data, "volume", sound_source->volume); + // hashmap_float_set(entity_data, "sound_min_distance", sound_source->min_distance); + // hashmap_float_set(entity_data, "sound_max_distance", sound_source->max_distance); + // hashmap_float_set(entity_data, "rolloff_factor", sound_source->rolloff_factor); + // hashmap_int_set(entity_data, "sound_attenuation_type", sound_source->attenuation_type); + // break; + //} + //}; return true; } @@ -396,232 +222,233 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type struct Entity* entity_read(struct Parser_Object* object) { - assert(object); - - if(object->type != PO_ENTITY) - { - log_error("entity:read", "Invalid object type"); - return NULL; - } - - const char* name = hashmap_str_get(object->data, "name"); - const char* parent_name = hashmap_str_get(object->data, "parent"); - int type = hashmap_int_get(object->data, "type"); - - if(!name) - { - log_error("entity:read", "No entity name provided"); - return NULL; - } - - if(!parent_name) - { - log_error("entity:read", "No parent name provided"); - return NULL; - } - - if(type < 0 || type >= ET_MAX) - { - log_error("entity:read", "Invalid entity type"); - return NULL; - } - - struct Entity* parent = entity_find(parent_name); - struct Entity* entity = entity_create(name, type, parent ? parent->id : -1); - if(!entity) - { - log_error("entity:read", "Failed to create new entity"); - return NULL; - } - - // Common entity properties - if(hashmap_value_exists(object->data, "is_listener")) - entity->is_listener = hashmap_bool_get(object->data, "is_listener"); - else - entity->is_listener = false; - - if(hashmap_value_exists(object->data, "renderable")) - entity->renderable= hashmap_bool_get(object->data, "renderable"); - else - entity->renderable= false; - - // Transform properties - if(hashmap_value_exists(object->data, "position")) - { - vec3 position = hashmap_vec3_get(object->data, "position"); - transform_translate(entity, &position, TS_PARENT); - } - - if(hashmap_value_exists(object->data, "rotation")) - { - quat rotation = hashmap_quat_get(object->data, "rotation"); - quat_assign(&entity->transform.rotation, &rotation); - } - - if(hashmap_value_exists(object->data, "scale")) - { - vec3 scale = hashmap_vec3_get(object->data, "scale"); - transform_scale(entity, &scale); - } - - switch(entity->type) - { - case ET_CAMERA: - { - bool has_fbo = false; - bool fbo_has_depth_tex = false; - bool fbo_has_render_tex = false; - int fbo_width = -1; - int fbo_height = -1; - - if(hashmap_value_exists(object->data, "fov")) entity->camera.fov = hashmap_float_get(object->data, "fov"); - if(hashmap_value_exists(object->data, "resizeable")) entity->camera.resizeable = hashmap_bool_get(object->data, "resizeable"); - if(hashmap_value_exists(object->data, "zoom")) entity->camera.zoom = hashmap_float_get(object->data, "zoom"); - if(hashmap_value_exists(object->data, "nearz")) entity->camera.nearz = hashmap_float_get(object->data, "nearz"); - if(hashmap_value_exists(object->data, "farz")) entity->camera.farz = hashmap_float_get(object->data, "farz"); - if(hashmap_value_exists(object->data, "ortho")) entity->camera.ortho = hashmap_bool_get(object->data, "ortho"); - if(hashmap_value_exists(object->data, "has_fbo")) has_fbo = hashmap_bool_get(object->data, "has_fbo"); - if(hashmap_value_exists(object->data, "fbo_has_depth_tex")) fbo_has_depth_tex = hashmap_bool_get(object->data, "fbo_has_depth_tex"); - if(hashmap_value_exists(object->data, "fbo_has_render_tex")) fbo_has_render_tex = hashmap_bool_get(object->data, "fbo_has_render_tex"); - if(hashmap_value_exists(object->data, "fbo_width")) fbo_width = hashmap_int_get(object->data, "fbo_width"); - if(hashmap_value_exists(object->data, "fbo_height")) fbo_height = hashmap_int_get(object->data, "fbo_height"); - if(hashmap_value_exists(object->data, "clear_color")) - { - vec4 color = hashmap_vec4_get(object->data, "clear_color"); - vec4_assign(&entity->camera.clear_color, &color); - } - - float aspect_ratio = (float)fbo_width / (float)fbo_height; - entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; - - entity->camera.fbo = -1; - entity->camera.render_tex = -1; - entity->camera.depth_tex = -1; - - if(has_fbo) - { - camera_attach_fbo(entity, fbo_width, fbo_height, fbo_has_depth_tex, fbo_has_render_tex, entity->camera.resizeable); - } - - camera_update_proj(entity); - camera_update_view(entity); - - } - break; - case ET_LIGHT: - { - if(hashmap_value_exists(object->data, "light_type")) entity->light.type = hashmap_int_get(object->data, "type"); - if(hashmap_value_exists(object->data, "outer_angle")) entity->light.outer_angle = hashmap_float_get(object->data, "outer_angle"); - if(hashmap_value_exists(object->data, "inner_angle")) entity->light.inner_angle = hashmap_float_get(object->data, "inner_angle"); - if(hashmap_value_exists(object->data, "falloff")) entity->light.falloff = hashmap_float_get(object->data, "falloff"); - if(hashmap_value_exists(object->data, "intensity")) entity->light.intensity = hashmap_float_get(object->data, "intensity"); - if(hashmap_value_exists(object->data, "depth_bias")) entity->light.depth_bias = hashmap_float_get(object->data, "depth_bias"); - if(hashmap_value_exists(object->data, "color")) entity->light.color = hashmap_vec3_get(object->data, "color"); - if(hashmap_value_exists(object->data, "cast_shadow")) entity->light.cast_shadow = hashmap_bool_get(object->data, "cast_shadow"); - if(hashmap_value_exists(object->data, "pcf_enabled")) entity->light.pcf_enabled = hashmap_bool_get(object->data, "pcf_enabled"); - if(hashmap_value_exists(object->data, "radius")) entity->light.radius = hashmap_int_get(object->data, "radius"); - light_add(entity); - } - break; - case ET_SOUND_SOURCE: - { - struct Sound_Source* sound_source = &entity->sound_source; - sound_source->type = ST_WAV; - sound_source->playing = false; - sound_source->loop = false; - sound_source->source_instance = 0; - sound_source->min_distance = 1.f; - sound_source->max_distance = 1000.f; - sound_source->volume = 1.f; - sound_source->rolloff_factor = 1.f; - sound_source->attenuation_type = SA_EXPONENTIAL; - sound_source->source = NULL; - sound_source->source_filename = NULL; - - if(hashmap_value_exists(object->data, "playing")) sound_source->playing = hashmap_bool_get(object->data, "playing"); - if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); - if(hashmap_value_exists(object->data, "sound_min_distance")) sound_source->min_distance = hashmap_float_get(object->data, "sound_min_distance"); - if(hashmap_value_exists(object->data, "sound_max_distance")) sound_source->max_distance = hashmap_float_get(object->data, "sound_max_distance"); - if(hashmap_value_exists(object->data, "volume")) sound_source->volume = hashmap_float_get(object->data, "volume"); - if(hashmap_value_exists(object->data, "rolloff_factor")) sound_source->rolloff_factor = hashmap_float_get(object->data, "rolloff_factor"); - if(hashmap_value_exists(object->data, "source_filename")) sound_source->source_filename = str_new(hashmap_str_get(object->data, "source_filename")); - if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); - if(hashmap_value_exists(object->data, "sound_attenuation_type")) sound_source->attenuation_type = hashmap_int_get(object->data, "sound_attenuation_type"); - if(sound_source->source_filename) - { - sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type); - if(sound_source->source) - { - sound_source->source_instance = platform->sound.source_instance_create(sound_source->source, true); - - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_fwd = {0.f, 0.f, -1.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - transform_get_absolute_position(entity, &abs_pos); - transform_get_absolute_forward(entity, &abs_fwd); - transform_get_absolute_up(entity, &abs_up); - platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); - - platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); - platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); - platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); - platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); - - platform->sound.update_3d(); - if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); - } - else - { - log_error("Failed to create sound source from '%s'", sound_source->source_filename); - free(sound_source->source_filename); - sound_source->source_filename = NULL; - } - } - else - { - log_error("entity:read", "No filename provided for sound source for entity '%s'", entity->name); - } - } - break; - case ET_PLAYER: - { - - } - break; - case ET_STATIC_MESH: - { - char* geometry_name = NULL; - char* material_name = NULL; - if(hashmap_value_exists(object->data, "geometry")) geometry_name = hashmap_str_get(object->data, "geometry"); - if(hashmap_value_exists(object->data, "material")) material_name = hashmap_str_get(object->data, "material"); - model_create(entity, geometry_name, material_name); - } - break; - case ET_ROOT: - { - scene_root_set(entity); - } - break; - default: - log_warning("Unhandled Entity type '%d' detected", entity->type); - break; - } - - if(entity->is_listener) - { - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_fwd = {0.f, 0.f, -1.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - transform_get_absolute_position(entity, &abs_pos); - transform_get_absolute_forward(entity, &abs_fwd); - transform_get_absolute_up(entity, &abs_up); - - platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, - abs_fwd.x, abs_fwd.y, abs_fwd.z, - abs_up.x, abs_up.y, abs_up.z); - } - - return entity; + return NULL; + //assert(object); + + //if(object->type != PO_ENTITY) + //{ + // log_error("entity:read", "Invalid object type"); + // return NULL; + //} + + //const char* name = hashmap_str_get(object->data, "name"); + //const char* parent_name = hashmap_str_get(object->data, "parent"); + //int type = hashmap_int_get(object->data, "type"); + + //if(!name) + //{ + // log_error("entity:read", "No entity name provided"); + // return NULL; + //} + + //if(!parent_name) + //{ + // log_error("entity:read", "No parent name provided"); + // return NULL; + //} + + //if(type < 0 || type >= ET_MAX) + //{ + // log_error("entity:read", "Invalid entity type"); + // return NULL; + //} + + //struct Entity* parent = entity_find(parent_name); + //struct Entity* entity = entity_create(name, type, parent ? parent->id : -1); + //if(!entity) + //{ + // log_error("entity:read", "Failed to create new entity"); + // return NULL; + //} + + //// Common entity properties + //if(hashmap_value_exists(object->data, "is_listener")) + // entity->is_listener = hashmap_bool_get(object->data, "is_listener"); + //else + // entity->is_listener = false; + + //if(hashmap_value_exists(object->data, "renderable")) + // entity->renderable= hashmap_bool_get(object->data, "renderable"); + //else + // entity->renderable= false; + + //// Transform properties + //if(hashmap_value_exists(object->data, "position")) + //{ + // vec3 position = hashmap_vec3_get(object->data, "position"); + // transform_translate(entity, &position, TS_PARENT); + //} + + //if(hashmap_value_exists(object->data, "rotation")) + //{ + // quat rotation = hashmap_quat_get(object->data, "rotation"); + // quat_assign(&entity->transform.rotation, &rotation); + //} + + //if(hashmap_value_exists(object->data, "scale")) + //{ + // vec3 scale = hashmap_vec3_get(object->data, "scale"); + // transform_scale(entity, &scale); + //} + + //switch(entity->type) + //{ + //case ET_CAMERA: + //{ + // bool has_fbo = false; + // bool fbo_has_depth_tex = false; + // bool fbo_has_render_tex = false; + // int fbo_width = -1; + // int fbo_height = -1; + + // if(hashmap_value_exists(object->data, "fov")) entity->camera.fov = hashmap_float_get(object->data, "fov"); + // if(hashmap_value_exists(object->data, "resizeable")) entity->camera.resizeable = hashmap_bool_get(object->data, "resizeable"); + // if(hashmap_value_exists(object->data, "zoom")) entity->camera.zoom = hashmap_float_get(object->data, "zoom"); + // if(hashmap_value_exists(object->data, "nearz")) entity->camera.nearz = hashmap_float_get(object->data, "nearz"); + // if(hashmap_value_exists(object->data, "farz")) entity->camera.farz = hashmap_float_get(object->data, "farz"); + // if(hashmap_value_exists(object->data, "ortho")) entity->camera.ortho = hashmap_bool_get(object->data, "ortho"); + // if(hashmap_value_exists(object->data, "has_fbo")) has_fbo = hashmap_bool_get(object->data, "has_fbo"); + // if(hashmap_value_exists(object->data, "fbo_has_depth_tex")) fbo_has_depth_tex = hashmap_bool_get(object->data, "fbo_has_depth_tex"); + // if(hashmap_value_exists(object->data, "fbo_has_render_tex")) fbo_has_render_tex = hashmap_bool_get(object->data, "fbo_has_render_tex"); + // if(hashmap_value_exists(object->data, "fbo_width")) fbo_width = hashmap_int_get(object->data, "fbo_width"); + // if(hashmap_value_exists(object->data, "fbo_height")) fbo_height = hashmap_int_get(object->data, "fbo_height"); + // if(hashmap_value_exists(object->data, "clear_color")) + // { + // vec4 color = hashmap_vec4_get(object->data, "clear_color"); + // vec4_assign(&entity->camera.clear_color, &color); + // } + + // float aspect_ratio = (float)fbo_width / (float)fbo_height; + // entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; + + // entity->camera.fbo = -1; + // entity->camera.render_tex = -1; + // entity->camera.depth_tex = -1; + + // if(has_fbo) + // { + // camera_attach_fbo(entity, fbo_width, fbo_height, fbo_has_depth_tex, fbo_has_render_tex, entity->camera.resizeable); + // } + + // camera_update_proj(entity); + // camera_update_view(entity); + + //} + //break; + //case ET_LIGHT: + //{ + // if(hashmap_value_exists(object->data, "light_type")) entity->light.type = hashmap_int_get(object->data, "type"); + // if(hashmap_value_exists(object->data, "outer_angle")) entity->light.outer_angle = hashmap_float_get(object->data, "outer_angle"); + // if(hashmap_value_exists(object->data, "inner_angle")) entity->light.inner_angle = hashmap_float_get(object->data, "inner_angle"); + // if(hashmap_value_exists(object->data, "falloff")) entity->light.falloff = hashmap_float_get(object->data, "falloff"); + // if(hashmap_value_exists(object->data, "intensity")) entity->light.intensity = hashmap_float_get(object->data, "intensity"); + // if(hashmap_value_exists(object->data, "depth_bias")) entity->light.depth_bias = hashmap_float_get(object->data, "depth_bias"); + // if(hashmap_value_exists(object->data, "color")) entity->light.color = hashmap_vec3_get(object->data, "color"); + // if(hashmap_value_exists(object->data, "cast_shadow")) entity->light.cast_shadow = hashmap_bool_get(object->data, "cast_shadow"); + // if(hashmap_value_exists(object->data, "pcf_enabled")) entity->light.pcf_enabled = hashmap_bool_get(object->data, "pcf_enabled"); + // if(hashmap_value_exists(object->data, "radius")) entity->light.radius = hashmap_int_get(object->data, "radius"); + // light_add(entity); + //} + //break; + //case ET_SOUND_SOURCE: + //{ + // struct Sound_Source* sound_source = &entity->sound_source; + // sound_source->type = ST_WAV; + // sound_source->playing = false; + // sound_source->loop = false; + // sound_source->source_instance = 0; + // sound_source->min_distance = 1.f; + // sound_source->max_distance = 1000.f; + // sound_source->volume = 1.f; + // sound_source->rolloff_factor = 1.f; + // sound_source->attenuation_type = SA_EXPONENTIAL; + // sound_source->source_buffer = NULL; + // sound_source->source_filename = NULL; + + // if(hashmap_value_exists(object->data, "playing")) sound_source->playing = hashmap_bool_get(object->data, "playing"); + // if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); + // if(hashmap_value_exists(object->data, "sound_min_distance")) sound_source->min_distance = hashmap_float_get(object->data, "sound_min_distance"); + // if(hashmap_value_exists(object->data, "sound_max_distance")) sound_source->max_distance = hashmap_float_get(object->data, "sound_max_distance"); + // if(hashmap_value_exists(object->data, "volume")) sound_source->volume = hashmap_float_get(object->data, "volume"); + // if(hashmap_value_exists(object->data, "rolloff_factor")) sound_source->rolloff_factor = hashmap_float_get(object->data, "rolloff_factor"); + // if(hashmap_value_exists(object->data, "source_filename")) sound_source->source_filename = str_new(hashmap_str_get(object->data, "source_filename")); + // if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); + // if(hashmap_value_exists(object->data, "sound_attenuation_type")) sound_source->attenuation_type = hashmap_int_get(object->data, "sound_attenuation_type"); + // if(sound_source->source_filename) + // { + // sound_source->source_buffer = platform->sound.source_create(sound_source->source_filename, sound_source->type); + // if(sound_source->source_buffer) + // { + // sound_source->source_instance = platform->sound.source_instance_create(sound_source->source_buffer, true); + + // vec3 abs_pos = {0.f, 0.f, 0.f}; + // vec3 abs_fwd = {0.f, 0.f, -1.f}; + // vec3 abs_up = {0.f, 1.f, 0.f}; + // transform_get_absolute_position(entity, &abs_pos); + // transform_get_absolute_forward(entity, &abs_fwd); + // transform_get_absolute_up(entity, &abs_up); + // platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); + + // platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); + // platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); + // platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); + // platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); + + // platform->sound.update_3d(); + // if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); + // } + // else + // { + // log_error("Failed to create sound source from '%s'", sound_source->source_filename); + // free(sound_source->source_filename); + // sound_source->source_filename = NULL; + // } + // } + // else + // { + // log_error("entity:read", "No filename provided for sound source for entity '%s'", entity->name); + // } + //} + //break; + //case ET_PLAYER: + //{ + + //} + //break; + //case ET_STATIC_MODEL: + //{ + // char* geometry_name = NULL; + // char* material_name = NULL; + // if(hashmap_value_exists(object->data, "geometry")) geometry_name = hashmap_str_get(object->data, "geometry"); + // if(hashmap_value_exists(object->data, "material")) material_name = hashmap_str_get(object->data, "material"); + // model_create(entity, geometry_name, material_name); + //} + //break; + //case ET_ROOT: + //{ + // scene_root_set(entity); + //} + //break; + //default: + // log_warning("Unhandled Entity type '%d' detected", entity->type); + // break; + //} + + //if(entity->is_listener) + //{ + // vec3 abs_pos = {0.f, 0.f, 0.f}; + // vec3 abs_fwd = {0.f, 0.f, -1.f}; + // vec3 abs_up = {0.f, 1.f, 0.f}; + // transform_get_absolute_position(entity, &abs_pos); + // transform_get_absolute_forward(entity, &abs_fwd); + // transform_get_absolute_up(entity, &abs_up); + + // platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, + // abs_fwd.x, abs_fwd.y, abs_fwd.z, + // abs_up.x, abs_up.y, abs_up.z); + //} + + //return entity; } bool entity_load(const char* filename, int directory_type) @@ -685,58 +512,17 @@ const char* entity_type_name_get(struct Entity* entity) case ET_PLAYER: typename = "Player"; break; case ET_ROOT: typename = "Root"; break; case ET_SOUND_SOURCE: typename = "Sound Source"; break; - case ET_STATIC_MESH: typename = "Static Mesh"; break; + case ET_STATIC_MODEL: typename = "Static Mesh"; break; default: typename = "Unknown"; break; }; return typename; } -void entity_apply_sound_params(struct Entity* entity) -{ - if(entity->type != ET_SOUND_SOURCE) return; - - struct Sound_Source* sound_source = &entity->sound_source; - - // Check if sound source has no buffer attached but filename exists, this would mean we have to load the file first - if(!sound_source->source && sound_source->source_filename) - { - sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type); - if(!sound_source->source) - { - log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", sound_source->source_filename, entity->name); - free(sound_source->source_filename); - sound_source->source_filename = NULL; - sound_source->source_instance = 0; - return; - } - } - - if(sound_source->source_instance == 0) sound_source->source_instance = platform->sound.source_instance_create(sound_source->source, true); - - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_fwd = {0.f, 0.f, -1.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - transform_get_absolute_position(entity, &abs_pos); - transform_get_absolute_forward(entity, &abs_fwd); - transform_get_absolute_up(entity, &abs_up); - platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); - - platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); - platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); - platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); - platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); - - platform->sound.update_3d(); - if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); -} - - void entity_rigidbody_on_move(Rigidbody body) { - int id = platform->physics.body_data_get(body); - struct Entity* entity = entity_get(id); - vec3 pos = {0}; - quat rot = {0}; + struct Entity* entity = platform->physics.body_data_get(body); + vec3 pos = {0.f}; + quat rot = {0.f}; platform->physics.body_position_get(body, &pos.x, &pos.y, &pos.z); platform->physics.body_rotation_get(body, &rot.x, &rot.y, &rot.z, &rot.w); @@ -753,25 +539,23 @@ void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B) if(body_A) { - int id_A = platform->physics.body_data_get(body_A); - ent_A = entity_get(id_A); + ent_A = platform->physics.body_data_get(body_A); } if(body_B) { - int id_B = platform->physics.body_data_get(body_B); - ent_B = entity_get(id_B); + ent_B = platform->physics.body_data_get(body_B); } - if(ent_A && ent_A->collision.on_collision) - { - ent_A->collision.on_collision(ent_A, ent_B ? ent_B : NULL, body_A, body_B ? body_B : NULL); - } + //if(ent_A && ent_A->collision.on_collision) + //{ + // ent_A->collision.on_collision(ent_A, ent_B ? ent_B : NULL, body_A, body_B ? body_B : NULL); + //} - if(ent_B && ent_B->collision.on_collision) - { - ent_B->collision.on_collision(ent_B, ent_A ? ent_A : NULL, body_B, body_A ? body_A : NULL); - } + //if(ent_B && ent_B->collision.on_collision) + //{ + // ent_B->collision.on_collision(ent_B, ent_A ? ent_A : NULL, body_B, body_A ? body_A : NULL); + //} if(ent_A && ent_B) { @@ -779,28 +563,27 @@ void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B) } } -void entity_rigidbody_set(struct Entity * entity, Rigidbody body) +void entity_rigidbody_set(struct Entity * entity, struct Collision* collision, Rigidbody body) { assert(entity && body); //Remove previous rigidbody if there is any - if(entity->has_collision && (entity->collision.rigidbody || entity->collision.collision_shape)) + if(collision->rigidbody || collision->collision_shape) { - if(entity->collision.rigidbody) + if(collision->rigidbody) { - platform->physics.body_remove(entity->collision.rigidbody); + platform->physics.body_remove(collision->rigidbody); } - else if(entity->collision.collision_shape) + else if(collision->collision_shape) { - platform->physics.cs_remove(entity->collision.collision_shape); + platform->physics.cs_remove(collision->collision_shape); } - entity->collision.rigidbody = NULL; - entity->collision.collision_shape = NULL; + collision->rigidbody = NULL; + collision->collision_shape = NULL; } - entity->has_collision = true; - entity->collision.rigidbody = body; - entity->collision.collision_shape = platform->physics.body_cs_get(body); + collision->rigidbody = body; + collision->collision_shape = platform->physics.body_cs_get(body); vec3 abs_pos = {0.f, 0.f, 0.f}; quat abs_rot = {0.f, 0.f, 0.f, 1.f}; @@ -809,28 +592,27 @@ void entity_rigidbody_set(struct Entity * entity, Rigidbody body) platform->physics.body_rotation_set(body, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w); platform->physics.body_position_set(body, abs_pos.x, abs_pos.y, abs_pos.z); - platform->physics.body_data_set(body, (void*)entity->id); + platform->physics.body_data_set(body, entity); } -void entity_collision_shape_set(struct Entity* entity, Collision_Shape shape) +void entity_collision_shape_set(struct Entity* entity, struct Collision* collision, Collision_Shape shape) { assert(entity && shape); - if(entity->has_collision && (entity->collision.rigidbody || entity->collision.collision_shape)) + if(collision->rigidbody || collision->collision_shape) { - if(entity->collision.rigidbody) + if(collision->rigidbody) { - platform->physics.body_remove(entity->collision.rigidbody); + platform->physics.body_remove(collision->rigidbody); } - else if(entity->collision.collision_shape) + else if(collision->collision_shape) { - platform->physics.cs_remove(entity->collision.collision_shape); + platform->physics.cs_remove(collision->collision_shape); } - entity->collision.rigidbody = NULL; - entity->collision.collision_shape = NULL; + collision->rigidbody = NULL; + collision->collision_shape = NULL; } - entity->has_collision = true; - entity->collision.collision_shape = shape; - platform->physics.cs_data_set(shape, (void*)entity->id); + collision->collision_shape = shape; + platform->physics.cs_data_set(shape, entity); } diff --git a/src/libsymmetry/entity.h b/src/libsymmetry/entity.h index 4865600..9b6e8e1 100644 --- a/src/libsymmetry/entity.h +++ b/src/libsymmetry/entity.h @@ -4,10 +4,13 @@ #include "../common/linmath.h" #include "../common/num_types.h" #include "../common/common.h" +#include "material.h" #define MAX_ENTITY_NAME_LEN 128 #define MAX_SOUND_SOURCE_BUFFERS 5 + +struct Entity; struct Material_Param; struct Parser_Object; @@ -16,11 +19,12 @@ typedef void (*Collision_CB)(struct Entity* this_entity, struct Entity* other_en enum Entity_Type { ET_NONE, + ET_DEFAULT, ET_PLAYER, ET_ROOT, ET_CAMERA, ET_LIGHT, - ET_STATIC_MESH, + ET_STATIC_MODEL, ET_SOUND_SOURCE, ET_MAX }; @@ -34,73 +38,93 @@ enum LightType LT_MAX }; +enum Camera_Type +{ + CT_EDITOR = 0, + CT_GAME, + CT_MAX +}; + struct Transform { - vec3 position; - vec3 scale; - quat rotation; - mat4 trans_mat; - int parent; - int* children; - bool is_modified; - bool sync_physics; + vec3 position; + vec3 scale; + quat rotation; + mat4 trans_mat; + bool is_modified; + bool sync_physics; + struct Entity* parent; + struct Entity** children; +}; + +struct Entity +{ + int id; + int type; + char name[MAX_ENTITY_NAME_LEN]; + bool marked_for_deletion; + bool active; + bool editor_selected; + struct Transform transform; }; struct Model { - int geometry_index; - int material; - struct Material_Param* material_params; + int geometry_index; + struct Material* material; + struct Variant material_params[MMP_MAX]; }; struct Sound_Source { + struct Entity base; int type; bool playing; bool loop; - char* source_filename; uint source_instance; float min_distance; float max_distance; float rolloff_factor; float volume; int attenuation_type; - struct Sound_Source_Buffer* source; + struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played }; struct Camera { - mat4 proj_mat; - mat4 view_mat; - mat4 view_proj_mat; - float fov; - float aspect_ratio; - float nearz; - float farz; - float zoom; - bool ortho; - int fbo; - int render_tex; - int depth_tex; - vec4 clear_color; - vec4 frustum[6]; - bool resizeable; + struct Entity base; + mat4 proj_mat; + mat4 view_mat; + mat4 view_proj_mat; + float fov; + float aspect_ratio; + float nearz; + float farz; + float zoom; + 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 base; + 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 Collision @@ -110,52 +134,28 @@ struct Collision Collision_CB on_collision; }; -struct Entity +struct Static_Mesh { - int id; - int type; - char name[MAX_ENTITY_NAME_LEN]; - bool is_listener; /* TODO: Replace all booleans with flags */ - bool marked_for_deletion; - bool renderable; - bool has_collision; - int editor_selected; - struct Transform transform; + struct Entity base; + struct Model model; struct Collision collision; +}; - union - { - struct - { - struct Model model; - int health; - } Player; - - struct Model model; - struct Camera camera; - struct Light light; - struct Sound_Source sound_source; - }; +struct Player +{ + struct Entity base; }; -void entity_init(void); -void entity_cleanup(void); -void entity_remove(int index); -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); +void entity_init(struct Entity* entity, const char* name, struct Entity* parent); +void entity_reset(struct Entity* entity, int id); bool entity_save(struct Entity* entity, const char* filename, int directory_type); bool entity_load(const char* filename, int directory_type); bool entity_write(struct Entity* entity, struct Parser_Object* object); struct Entity* entity_read(struct Parser_Object* object); const char* entity_type_name_get(struct Entity* entity); -void entity_apply_sound_params(struct Entity* entity); // Convenience function to sync the data set in entity's sound_source with the actual sound source's instance void entity_rigidbody_on_move(Rigidbody body); void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B); -void entity_rigidbody_set(struct Entity* entity, Rigidbody body); -void entity_collision_shape_set(struct Entity* entity, Collision_Shape shape); // Only used for collision shapes like plane which can't have a rigidbody attached to collision shape +void entity_rigidbody_set(struct Entity* entity, struct Collision* collision, Rigidbody body); +void entity_collision_shape_set(struct Entity* entity, struct Collision* collision, Collision_Shape shape); // Only used for collision shapes like plane which can't have a rigidbody attached to collision shape #endif diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index 5f20fab..7c86e26 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -76,38 +76,38 @@ bool game_init(struct Window* window, struct Platform_Api* platform_api) else { game_state->window = window; - game_state->player_node = -1; - game_state->player_pitch_node = -1; + game_state->player_node = NULL; + game_state->player_pitch_node = NULL; game_state->is_initialized = false; - } + game_state->renderer = malloc(sizeof(*game_state->renderer)); + game_state->scene = malloc(sizeof(*game_state->scene)); - /* TODO: Decouple systems' init/cleanup from game, they should exist and run even if there's no "game" */ - /* Init systems */ - log_file_handle_set(platform->log.file_handle_get()); - if(!gl_load_extentions()) - { - log_error("game:init", "Failed to load GL extentions"); - return false; - } - else - { - log_message("Loaded GL extentions"); - } - input_init(); - shader_init(); - texture_init(); - framebuffer_init(); - geom_init(); - editor_init(); - renderer_init(); - light_init(); - material_init(); - entity_init(); - platform->physics.init(); - platform->physics.gravity_set(0.f, -9.8f, 0.f); - platform->physics.body_set_moved_callback(entity_rigidbody_on_move); - platform->physics.body_set_collision_callback(entity_rigidbody_on_collision); - scene_init(); + log_file_handle_set(platform->log.file_handle_get()); + if(!gl_load_extentions()) + { + log_error("game:init", "Failed to load GL extentions"); + return false; + } + else + { + log_message("Loaded GL extentions"); + } + + + input_init(); + shader_init(); + texture_init(); + framebuffer_init(); + geom_init(); + editor_init(); + platform->physics.init(); + platform->physics.gravity_set(0.f, -9.8f, 0.f); + platform->physics.body_set_moved_callback(entity_rigidbody_on_move); + platform->physics.body_set_collision_callback(entity_rigidbody_on_collision); + + scene_init(game_state->scene); + renderer_init(game_state->renderer); + } /* Debug scene setup */ scene_setup(); @@ -239,49 +239,48 @@ void scene_setup(void) // scene_save("test_scene.symtres", DIRT_INSTALL); - if(scene_load("test_scene.symtres", DIRT_INSTALL)) - { - log_message("Scene loaded!"); - struct Entity* player = entity_find("player"); - game_state->player_node = player->id; - - struct Entity* suz = entity_find("Model_Entity"); - suz_id = suz->id; - /*struct Camera* camera = &player->camera; - camera->ortho = true; - camera->farz = 500.f; - camera->nearz = -500.f; - camera_update_proj(player);*/ - } - - platform->physics.cs_plane_create(0, 1, 0, 0); - //Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5); - Rigidbody box = platform->physics.body_sphere_create(3.5); - /*platform->physics.body_position_set(box, 0.f, 50.f, 0.f); - platform->physics.body_mass_set(box, 10.f);*/ - /*platform->physics.body_data_set(box, (void*)suz_id);*/ - //platform->physics.body_force_add(box, -100.f, 0.f, 0.f); - struct Entity* suz = entity_find("Model_Entity"); - entity_rigidbody_set(suz, box); - suz->collision.on_collision = &on_collision_test; - - Rigidbody sphere = platform->physics.body_sphere_create(3.5f); - struct Entity* sphere_ent = entity_find("Sphere_Ent"); - entity_rigidbody_set(sphere_ent, sphere); - - //Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0); - Rigidbody ground_box = platform->physics.body_box_create(10, 5, 10); - platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f); - /*platform->physics.body_kinematic_set(ground_box);*/ - struct Entity* ground = entity_find("Ground"); - //entity_collision_shape_set(ground, plane); - entity_rigidbody_set(ground, ground_box); + // if(scene_load("test_scene.symtres", DIRT_INSTALL)) + // { + // log_message("Scene loaded!"); + // struct Entity* player = entity_find("player"); + // game_state->player_node = player->id; + + //struct Entity* suz = entity_find("Model_Entity"); + //suz_id = suz->id; + // /*struct Camera* camera = &player->camera; + // camera->ortho = true; + // camera->farz = 500.f; + // camera->nearz = -500.f; + // camera_update_proj(player);*/ + // } + + //platform->physics.cs_plane_create(0, 1, 0, 0); + ////Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5); + //Rigidbody box = platform->physics.body_sphere_create(3.5); + ///*platform->physics.body_position_set(box, 0.f, 50.f, 0.f); + //platform->physics.body_mass_set(box, 10.f);*/ + ///*platform->physics.body_data_set(box, (void*)suz_id);*/ + ////platform->physics.body_force_add(box, -100.f, 0.f, 0.f); + //struct Entity* suz = entity_find("Model_Entity"); + //entity_rigidbody_set(suz, box); + //suz->collision.on_collision = &on_collision_test; + + //Rigidbody sphere = platform->physics.body_sphere_create(3.5f); + //struct Entity* sphere_ent = entity_find("Sphere_Ent"); + //entity_rigidbody_set(sphere_ent, sphere); + + ////Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0); + //Rigidbody ground_box = platform->physics.body_box_create(10, 5, 10); + //platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f); + ///*platform->physics.body_kinematic_set(ground_box);*/ + //struct Entity* ground = entity_find("Ground"); + ////entity_collision_shape_set(ground, plane); + //entity_rigidbody_set(ground, ground_box); } void debug(float dt) { //struct Entity* entity = entity_get(player_node); - struct Entity* player_entity = entity_get(game_state->player_node); float move_speed = 5.f, move_scale = 3.f, turn_speed = 50.f; vec3 offset = {0, 0, 0}; float turn_up_down = 0.f; @@ -334,25 +333,25 @@ void debug(float dt) if(turn_left_right != 0.f) { - transform_rotate(player_entity, &rot_axis_left_right, -turn_left_right, TS_WORLD); + /*transform_rotate(player_entity, &rot_axis_left_right, -turn_left_right, TS_WORLD); vec3 up = {0.f, 0.f, 0.f}; vec3 forward = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f}; transform_get_up(player_entity, &up); transform_get_forward(player_entity, &forward); - transform_get_lookat(player_entity, &lookat); + transform_get_lookat(player_entity, &lookat);*/ /* log_message("Up : %s", tostr_vec3(&up)); */ /* log_message("FR : %s", tostr_vec3(&forward)); */ } if(turn_up_down != 0.f) { - transform_rotate(player_entity, &rot_axis_up_down, turn_up_down, TS_LOCAL); + /*transform_rotate(player_entity, &rot_axis_up_down, turn_up_down, TS_LOCAL); vec3 up = {0.f, 0.f, 0.f}; vec3 forward = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f}; transform_get_up(player_entity, &up); transform_get_forward(player_entity, &forward); - transform_get_lookat(player_entity, &lookat); + transform_get_lookat(player_entity, &lookat);*/ /* log_message("Up : %s", tostr_vec3(&up)); */ /* log_message("FR : %s", tostr_vec3(&forward)); */ } @@ -369,20 +368,20 @@ void debug(float dt) vec3_scale(&offset, &offset, dt); if(offset.x != 0 || offset.y != 0 || offset.z != 0) { - transform_translate(player_entity, &offset, TS_LOCAL); + //transform_translate(player_entity, &offset, TS_LOCAL); //log_message("Position : %s", tostr_vec3(&transform->position)); } if(input_is_key_pressed(KEY_SPACE)) { - struct Entity* model = scene_find("Light_Ent"); + struct Entity* model = scene_find(game_state->scene, "Light_Ent"); vec3 x_axis = {0, 1, 0}; transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); } if(input_is_key_pressed(KEY_M)) { - struct Entity* model = scene_find("Model_Entity"); + struct Entity* model = scene_find(game_state->scene, "Model_Entity"); //vec3 y_axis = {0, 0, 1}; //transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL); vec3 amount = {0, 0, -5 * dt}; @@ -391,7 +390,7 @@ void debug(float dt) if(input_is_key_pressed(KEY_N)) { - struct Entity* model = scene_find("Model_Entity"); + struct Entity* model = scene_find(game_state->scene, "Model_Entity"); /* vec3 y_axis = {0, 0, 1}; */ /* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */ vec3 amount = {0, 0, 5 * dt}; @@ -404,7 +403,7 @@ void debug(float dt) vec3 amount = {0, 0, -5 * dt}; transform_translate(model, &amount, TS_LOCAL);*/ - struct Sprite_Batch* batch = get_batch(); + struct Sprite_Batch* batch = game_state->renderer->sprite_batch; sprite_batch_begin(batch); static struct Sprite sprite; @@ -437,7 +436,7 @@ void debug(float dt) //Raycast test if(input_is_key_pressed(KEY_R)) { - Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true); + /*Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true); vec3 position = {0.f, 0.f, 0.f}; vec3 direction = {0.f, 0.f, 0.f}; transform_get_absolute_forward(player_entity, &direction); @@ -452,7 +451,7 @@ void debug(float dt) { log_message("Ray didn't hit anything!"); } - platform->physics.cs_remove(ray); + platform->physics.cs_remove(ray);*/ } // Immediate geometry test @@ -556,7 +555,7 @@ bool run(void) platform->physics.step(delta_time); render(); platform->window.swap_buffers(game_state->window); - entity_post_update(); + scene_post_update(game_state->scene); platform->sound.update_3d(); } return true; @@ -1788,8 +1787,7 @@ void debug_gui(float dt) void render(void) { - struct Entity* viewer = entity_get(game_state->player_node); - renderer_draw(viewer); + renderer_draw(game_state->renderer, game_state->scene); } void game_cleanup(void) @@ -1799,16 +1797,16 @@ void game_cleanup(void) if(game_state->is_initialized) { editor_cleanup(); - scene_cleanup(); - entity_cleanup(); - material_cleanup(); - light_cleanup(); + scene_destroy(game_state->scene); input_cleanup(); - renderer_cleanup(); + renderer_cleanup(game_state->renderer); geom_cleanup(); framebuffer_cleanup(); texture_cleanup(); shader_cleanup(); + + free(game_state->scene); + free(game_state->renderer); } free(game_state); game_state = NULL; diff --git a/src/libsymmetry/game.h b/src/libsymmetry/game.h index 928308f..8a1bcf4 100644 --- a/src/libsymmetry/game.h +++ b/src/libsymmetry/game.h @@ -11,13 +11,19 @@ struct Window; struct Platform_Api; +struct Renderer; +struct Scene; +struct Entity; +struct Player; struct Game_State { - struct Window* window; - int player_node; - int player_pitch_node; - bool is_initialized; + bool is_initialized; + struct Window* window; + struct Player* player_node; + struct Entity* player_pitch_node; + struct Renderer* renderer; + struct Scene* scene; }; diff --git a/src/libsymmetry/im_render.c b/src/libsymmetry/im_render.c index 2cf770c..227ccbc 100644 --- a/src/libsymmetry/im_render.c +++ b/src/libsymmetry/im_render.c @@ -155,7 +155,7 @@ void im_end(void) memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES); } -void im_render(struct Entity* active_viewer) +void im_render(struct Camera* active_viewer) { if(IM_State.curr_geom == -1) return; @@ -182,7 +182,7 @@ void im_render(struct Entity* active_viewer) mat4_mul(&mvp, &mvp, &rotation); mat4_mul(&mvp, &mvp, &scale); - mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &mvp); + mat4_mul(&mvp, &active_viewer->view_proj_mat, &mvp); shader_set_uniform_mat4(IM_State.im_shader, "mvp", &mvp); shader_set_uniform_vec4(IM_State.im_shader, "geom_color", &geom->color); diff --git a/src/libsymmetry/im_render.h b/src/libsymmetry/im_render.h index 45a6b32..778e198 100644 --- a/src/libsymmetry/im_render.h +++ b/src/libsymmetry/im_render.h @@ -34,7 +34,7 @@ struct IM_Geom int draw_mode; }; -struct Entity; +struct Camera; void im_init(void); void im_cleanup(void); @@ -43,6 +43,6 @@ void im_pos(float x, float y, float z); void im_box(float x, float y, float z, vec3 position, quat rotation, vec4 color, int draw_mode); void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode); void im_end(void); -void im_render(struct Entity* active_viewer); +void im_render(struct Camera* active_viewer); #endif \ No newline at end of file diff --git a/src/libsymmetry/light.c b/src/libsymmetry/light.c index 87107f2..ff421cc 100644 --- a/src/libsymmetry/light.c +++ b/src/libsymmetry/light.c @@ -4,23 +4,8 @@ #include -static int* light_list = NULL; - -void light_init(void) -{ - light_list = array_new(int); -} - -void light_cleanup(void) -{ - array_free(light_list); - light_list = NULL; -} - - -void light_create(struct Entity* entity, int light_type) +void light_init(struct Light* light, int light_type) { - struct Light* light = &entity->light; light->valid = true; light->cast_shadow = 0; light->depth_bias = 0.0005f; @@ -32,30 +17,10 @@ void light_create(struct Entity* entity, int light_type) light->inner_angle = TO_RADIANS(20.f); light->radius = 20; vec3_fill(&light->color, 1.f, 1.f, 1.f); - light_add(entity); } -void light_add(struct Entity* entity) +void light_reset(struct Light* light) { - assert(entity->type == ET_LIGHT); - int* new_index = array_grow(light_list, int); - *new_index = entity->id; -} - -void light_destroy(struct Entity* entity) -{ - assert(entity && entity->type == ET_LIGHT); - struct Light* light = &entity->light; - int index_to_remove = -1; - for(int i = 0; i < array_len(light_list); i++) - { - if(light_list[i] == entity->id) - { - index_to_remove = i; - break; - } - } - 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; @@ -67,10 +32,4 @@ void light_destroy(struct Entity* entity) 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* out_count) -{ - *out_count = array_len(light_list); - return light_list; -} +} \ No newline at end of file diff --git a/src/libsymmetry/light.h b/src/libsymmetry/light.h index 8aae134..c99762b 100644 --- a/src/libsymmetry/light.h +++ b/src/libsymmetry/light.h @@ -3,13 +3,7 @@ #define MAX_SHADOWMAPS 4 -struct Entity; - -void light_init(void); -void light_cleanup(void); -void light_destroy(struct Entity* entity); -void light_create(struct Entity* entity, int light_type); -void light_add(struct Entity* entity); -int* light_get_valid_indices(int* out_count); +void light_init(struct Light* light); +void light_reset(struct Light* light); #endif diff --git a/src/libsymmetry/material.c b/src/libsymmetry/material.c index b99b750..b6bdf8c 100644 --- a/src/libsymmetry/material.c +++ b/src/libsymmetry/material.c @@ -12,312 +12,156 @@ #include #include -static struct Material* material_list; -static int* empty_indices; - -void material_init(void) +bool material_init(struct Material* material, int material_type) { - material_list = array_new(struct Material); - empty_indices = array_new(int); - - /* TODO: implement reading material definitions from files */ - /* Simple unshaded material */ - struct Material* unshaded_mat = array_grow(material_list, struct Material); - unshaded_mat->name = str_new("Unshaded"); - unshaded_mat->shader = shader_create("unshaded.vert", "unshaded.frag"); - unshaded_mat->registered_models = array_new(int); - unshaded_mat->model_params = array_new(struct Uniform); - unshaded_mat->pipeline_params = array_new(struct Uniform); - unshaded_mat->active = 1; - unshaded_mat->lit = 0; - - /* Pipeline params/uniforms */ - struct Uniform* uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("mvp"); - uniform->type = UT_MAT4; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("model_mat"); - uniform->type = UT_MAT4; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.mode"); - uniform->type = UT_INT; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.density"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.start_dist"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.max_dist"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.color"); - uniform->type = UT_VEC3; - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - /* Material params */ - uniform = array_grow(unshaded_mat->model_params, struct Uniform); - uniform->name = str_new("diffuse_color"); - uniform->type = UT_VEC4; - vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f); - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - uniform = array_grow(unshaded_mat->model_params, struct Uniform); - uniform->name = str_new("diffuse_texture"); - uniform->type = UT_TEX; - uniform->d_int = texture_find("default.tga"); - uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name); - - /* Simple blinn_phong material */ - struct Material* blinn_phong_mat = array_grow(material_list, struct Material); - blinn_phong_mat->name = str_new("Blinn_Phong"); - blinn_phong_mat->shader = shader_create("blinn_phong.vert", "blinn_phong.frag"); - blinn_phong_mat->registered_models = array_new(int); - blinn_phong_mat->model_params = array_new(struct Uniform); - blinn_phong_mat->pipeline_params = array_new(struct Uniform); - blinn_phong_mat->active = 1; - blinn_phong_mat->lit = 1; - - /* Pipeline params/uniforms */ - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("mvp"); - uniform->type = UT_MAT4; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("model_mat"); - uniform->type = UT_MAT4; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - /* uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); */ - /* uniform->name = str_new("view_mat"); */ - /* uniform->type = UT_MAT4; */ - /* uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); */ - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("inv_model_mat"); - uniform->type = UT_MAT4; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.mode"); - uniform->type = UT_INT; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.density"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.start_dist"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.max_dist"); - uniform->type = UT_FLOAT; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("fog.color"); - uniform->type = UT_VEC3; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); - uniform->name = str_new("ambient_light"); - uniform->type = UT_VEC3; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - /* Material params */ - uniform = array_grow(blinn_phong_mat->model_params, struct Uniform); - uniform->name = str_new("diffuse_color"); - uniform->type = UT_VEC4; - vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f); - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->model_params, struct Uniform); - uniform->name = str_new("diffuse_texture"); - uniform->type = UT_TEX; - uniform->d_int = texture_find("default.tga"); - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->model_params, struct Uniform); - uniform->name = str_new("specular"); - uniform->type = UT_FLOAT; - uniform->d_float = 1.f; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->model_params, struct Uniform); - uniform->name = str_new("diffuse"); - uniform->type = UT_FLOAT; - uniform->d_float = 1.f; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); - - uniform = array_grow(blinn_phong_mat->model_params, struct Uniform); - uniform->name = str_new("specular_strength"); - uniform->type = UT_FLOAT; - uniform->d_float = 50.f; - uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); -} + assert(material && material_type > -1 && material_type < MAT_MAX); -struct Material* material_get_all_materials(void) -{ - return material_list; + material->type = material_type; + memset(material->registered_models, 0, sizeof(struct Model*) * MAX_MATERIAL_REGISTERED_MODELS); + memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX); + memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX); + + switch(material_type) + { + case MAT_BLINN: + { + material->lit = true; + material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag"); + + material->pipeline_params[MPP_INV_MODEL_MAT].type = UT_MAT4; + material->pipeline_params[MPP_INV_MODEL_MAT].location = shader_get_uniform_location(material->shader, "inv_model_mat"); + + material->pipeline_params[MPP_VIEW_MAT].type = UT_MAT4; + material->pipeline_params[MPP_VIEW_MAT].location = shader_get_uniform_location(material->shader, "view_mat"); + + material->pipeline_params[MPP_CAM_POS].type = UT_VEC3; + material->pipeline_params[MPP_CAM_POS].location = shader_get_uniform_location(material->shader, "camera_pos"); + + material->pipeline_params[MPP_TOTAL_LIGHTS].type = UT_INT; + material->pipeline_params[MPP_TOTAL_LIGHTS].location = shader_get_uniform_location(material->shader, "total_active_lights"); + + material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX; + material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture"); + + material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4; + material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color"); + + material->model_params[MMP_DIFFUSE].type = UT_FLOAT; + material->model_params[MMP_DIFFUSE].location = shader_get_uniform_location(material->shader, "diffuse"); + + material->model_params[MMP_SPECULAR].type = UT_FLOAT; + material->model_params[MMP_SPECULAR].location = shader_get_uniform_location(material->shader, "specular"); + + material->model_params[MMP_SPECULAR_STRENGTH].type = UT_FLOAT; + material->model_params[MMP_SPECULAR_STRENGTH].location = shader_get_uniform_location(material->shader, "specular"); + } + break; + case MAT_UNSHADED: + { + material->lit = false; + material->shader = shader_create("unshaded.vert", "unshaded.frag"); + + material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX; + material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture"); + + material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4; + material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color"); + }; + break; + default: + log_error("material:init", "Invalid material type"); + return false; + } + + // Setup common pipeline parameters + material->pipeline_params[MPP_FOG_MODE].type = UT_INT; + material->pipeline_params[MPP_FOG_MODE].location = shader_get_uniform_location(material->shader, "fog.mode"); + + material->pipeline_params[MPP_FOG_DENSITY].type = UT_FLOAT; + material->pipeline_params[MPP_FOG_DENSITY].location = shader_get_uniform_location(material->shader, "fog.density"); + + material->pipeline_params[MPP_FOG_START_DIST].type = UT_FLOAT; + material->pipeline_params[MPP_FOG_START_DIST].location = shader_get_uniform_location(material->shader, "fog.start_dist"); + + material->pipeline_params[MPP_FOG_MAX_DIST].type = UT_FLOAT; + material->pipeline_params[MPP_FOG_MAX_DIST].location = shader_get_uniform_location(material->shader, "fog.max_dist"); + + material->pipeline_params[MPP_FOG_COLOR].type = UT_VEC3; + material->pipeline_params[MPP_FOG_COLOR].location = shader_get_uniform_location(material->shader, "fog.color"); + + material->pipeline_params[MPP_MVP].type = UT_MAT4; + material->pipeline_params[MPP_MVP].location = shader_get_uniform_location(material->shader, "mvp"); + + material->pipeline_params[MPP_MODEL_MAT].type = UT_MAT4; + material->pipeline_params[MPP_MODEL_MAT].location = shader_get_uniform_location(material->shader, "model_mat"); + + material->pipeline_params[MPP_AMBIENT_LIGHT].type = UT_VEC3; + material->pipeline_params[MPP_AMBIENT_LIGHT].location = shader_get_uniform_location(material->shader, "ambient_light"); + + return true; } -void material_cleanup(void) +void material_reset(struct Material* material) { - for(int i = 0; i < array_len(material_list); i++) - material_remove(i); - array_free(empty_indices); - array_free(material_list); + assert(material); + + material->type = -1; + memset(material->registered_models, 0, sizeof(struct Model*) * MAX_MATERIAL_REGISTERED_MODELS); + memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX); + memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX); } -bool material_register_model(struct Entity* entity, const char* material_name) +bool material_register_model(struct Material* material, struct Model* model) { - assert(material_name && entity); - bool success = false; - int index = material_get_index(material_name); - if(index <= -1) - { - log_error("material:register_model", "Material '%s' not found", material_name); - return success; - } + assert(model && material); - struct Model* model = &entity->model; - struct Material* material = &material_list[index]; - model->material = index; - model->material_params = array_new(struct Material_Param); - for(int i = 0; i < array_len(material->model_params); i++) + for(int i = 0; i < MAX_MATERIAL_REGISTERED_MODELS; i++) { - /* set up parameters */ - struct Uniform* uniform = &material->model_params[i]; - struct Material_Param* param = array_grow(model->material_params, struct Material_Param); - param->uniform_index = i; - switch(uniform->type) + if(!material->registered_models[i]) { - case UT_INT: - param->value = malloc(sizeof(int)); - *((int*)param->value) = uniform->d_int; - break; - case UT_FLOAT: - param->value = malloc(sizeof(float)); - *((float*)param->value) = uniform->d_float; - break; - case UT_VEC2: - param->value = malloc(sizeof(vec2)); - vec2_assign((vec2*)param->value, &uniform->d_vec2); - break; - case UT_VEC3: - param->value = malloc(sizeof(vec3)); - vec3_assign((vec3*)param->value, &uniform->d_vec3); - break; - case UT_VEC4: - param->value = malloc(sizeof(vec4)); - vec4_assign((vec4*)param->value, &uniform->d_vec4); + material->registered_models[i] = model; + + // Set default values for instance parameters + switch(material->type) + { + case MAT_BLINN: + { + variant_assign_vec4f(&model->material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f); + variant_assign_float(&model->material_params[MMP_DIFFUSE], 1.f); + variant_assign_int(&model->material_params[MMP_DIFFUSE_TEX], texture_find("default.tga")); + variant_assign_float(&model->material_params[MMP_SPECULAR], 1.f); + variant_assign_float(&model->material_params[MMP_SPECULAR_STRENGTH], 50.f); + } break; - case UT_MAT4: - param->value = malloc(sizeof(mat4)); - mat4_identity((mat4*)param->value); - break; - case UT_TEX: - param->value = malloc(sizeof(int)); - *((int*)param->value) = texture_create_from_file("default.tga", TU_DIFFUSE); + case MAT_UNSHADED: + { + variant_assign_vec4f(&model->material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f); + variant_assign_int(&model->material_params[MMP_DIFFUSE_TEX], texture_find("default.tga")); + } break; + default: + log_error("material:register_model", "Invalid material type"); + break; + } + return true; } } - - array_push(material->registered_models, entity->id, int); - success = true; - return success; -} -void material_unregister_model(struct Entity* entity) -{ - assert(entity); - struct Model* model = &entity->model; - struct Material* material = &material_list[model->material]; - /* Remove textures, if any */ - for(int i = 0; i < array_len(model->material_params); i++) - { - struct Material_Param* param = &model->material_params[i]; - struct Uniform* uniform = &material->model_params[param->uniform_index]; - if(uniform->type == UT_TEX) - texture_remove(*(int*)param->value); - } - /* Remove model index from material registry*/ - for(int i = 0; i < array_len(material->registered_models); i++) - { - if(material->registered_models[i] == entity->id) - { - array_remove_at(material->registered_models, i); - break; - } - } + return false; } -struct Material* material_find(const char* material_name) +void material_unregister_model(struct Material* material, struct Model* model) { - struct Material* material = NULL; - int index = material_get_index(material_name); - if(index > -1) material = &material_list[index]; - return material; -} + assert(model && material); -int material_get_index(const char* material_name) -{ - int index = -1; - for(int i = 0; i < array_len(material_list); i++) + for(int i = 0; i < MAX_MATERIAL_REGISTERED_MODELS; i++) { - if(!material_list[i].name) continue; - - if(strcmp(material_name, material_list[i].name) == 0) + if(material->registered_models[i] == model) { - index = i; + material->registered_models[i] = NULL; + for(int i = 0; i < MMP_MAX; i++) + variant_free(&model->material_params[i]); break; } } - return index; -} - -struct Material* material_get(int index) -{ - struct Material* material = NULL; - if(index > -1 && index < array_len(material_list)) - material = &material_list[index]; - return material; -} - -void material_remove(int index) -{ - assert(index > -1 && index < array_len(material_list)); - struct Material* material = &material_list[index]; - if(!material->active) - return; - material->active = 0; - array_free(material->registered_models); - for(int i = 0; i < array_len(material->model_params); i++) - free(material->model_params[i].name); - array_free(material->model_params); - - for(int i = 0; i < array_len(material->pipeline_params); i++) - free(material->pipeline_params[i].name); - array_free(material->pipeline_params); - - log_message("Removed material '%s'", material->name); - free(material->name); - array_push(empty_indices, index, int); -} +} \ No newline at end of file diff --git a/src/libsymmetry/material.h b/src/libsymmetry/material.h index 1526f1c..3a963eb 100644 --- a/src/libsymmetry/material.h +++ b/src/libsymmetry/material.h @@ -3,49 +3,67 @@ #include "../common/linmath.h" #include "../common/num_types.h" +#include "../common/variant.h" -struct Entity; +struct Model; + +#define MAX_UNIFORM_NAME_LEN 64 +#define MAX_MATERIAL_REGISTERED_MODELS 1024 struct Uniform { - int location; - char* name; - int type; - union /* Default values */ - { - vec2 d_vec2; - vec3 d_vec3; - vec4 d_vec4; - int d_int; - float d_float; - }; + int location; + int type; +}; + +enum Mat_Type +{ + MAT_BLINN = 0, + MAT_UNSHADED, + MAT_MAX }; -struct Material_Param +enum Mat_Model_Param { - int uniform_index; /* Index of the corresponding uniform in the material's model_params */ - void* value; /* Actual value of the uniform */ + MMP_DIFFUSE_TEX = 0, + MMP_DIFFUSE_COL, + MMP_DIFFUSE, + MMP_SPECULAR_STRENGTH, + MMP_SPECULAR, + MMP_MAX +}; + +enum Mat_Pipeline_Param +{ + MPP_MODEL_MAT = 0, + MPP_INV_MODEL_MAT, + MPP_VIEW_MAT, + MPP_MVP, + MPP_FOG_MODE, + MPP_FOG_DENSITY, + MPP_FOG_START_DIST, + MPP_FOG_MAX_DIST, + MPP_FOG_COLOR, + MPP_CAM_POS, + MPP_TOTAL_LIGHTS, + MPP_AMBIENT_LIGHT, + MPP_MAX }; struct Material { - char* name; - int shader; - int* registered_models; - bool active; - bool lit; /* If material uses light information */ - struct Uniform* model_params; /* uniforms related to models */ - struct Uniform* pipeline_params; /* general uniforms like matrices etc */ + int type; + int shader; + struct Model* registered_models[MAX_MATERIAL_REGISTERED_MODELS]; + bool lit; + struct Uniform model_params[MMP_MAX]; + struct Uniform pipeline_params[MPP_MAX]; }; -struct Material* material_get_all_materials(void); -struct Material* material_find(const char* material_name); -struct Material* material_get(int index); -int material_get_index(const char* material_name); -void material_init(void); -void material_cleanup(void); -bool material_register_model(struct Entity* entity, const char* material_name); -void material_unregister_model(struct Entity* entity); -void material_remove(int index); +bool material_init(struct Material* material, int material_type); +void material_reset(struct Material* material); +bool material_register_model(struct Material* material, struct Model* model); +void material_unregister_model(struct Material* material, struct Model* model); + #endif diff --git a/src/libsymmetry/model.c b/src/libsymmetry/model.c index 46fa831..06f9943 100644 --- a/src/libsymmetry/model.c +++ b/src/libsymmetry/model.c @@ -1,6 +1,8 @@ #include "model.h" #include "../common/array.h" #include "../common/log.h" +#include "game.h" +#include "renderer.h" #include "entity.h" #include "texture.h" #include "material.h" @@ -11,103 +13,41 @@ #include #include -void model_create(struct Entity* entity, const char* geo_name, const char* material_name) +void model_init(struct Model* model, const char* geometry_name, int material_type) { - struct Model* model = &entity->model; + assert(model && material_type > -1 && material_type < MAT_MAX); + /* if no name is given for geometry, use default */ - int geo_index = geom_create_from_file(geo_name ? geo_name : "default.pamesh"); + int geo_index = geom_create_from_file(geometry_name ? geometry_name : "default.pamesh"); if(geo_index == -1) { - log_error("model:create", "Failed to load model %s", geo_name); + log_error("model:init", "Failed to load model %s", geometry_name); geo_index = geom_create_from_file("default.pamesh"); if(geo_index == -1) { - log_error("model:create", "Could not load default model 'default.pamesh' "); + log_error("model:init", "Could not load default model 'default.pamesh' "); return; } } model->geometry_index = geo_index; - if(!material_register_model(entity, material_name ? material_name : "Unshaded")) + if(!material_register_model(model, material_type)) { log_error("model:create", "Unable to register model with Unshaded material, component not added"); - model_destroy(entity); + model_reset(model); } } -void model_destroy(struct Entity* entity) +void model_reset(struct Model* model) { - struct Model* model = &entity->model; + assert(model); geom_remove(model->geometry_index); model->geometry_index = -1; - material_unregister_model(entity); - /* 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); - model->material_params = NULL; - model->material = -1; -} - -int model_set_material_param(struct Entity* entity, const char* name, void* value) -{ - assert(name && value); - struct Model* model = &entity->model; - int success = 0; - struct Material* material = material_get(model->material); - for(int i = 0; i < array_len(model->material_params); i++) + struct Renderer* renderer = game_state_get()->renderer; + if(model->material) { - struct Material_Param* param = &model->material_params[i]; - struct Uniform* uniform = &material->model_params[param->uniform_index]; - if(strcmp(uniform->name, name) == 0) - { - 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; - default: - log_error("model:set_material_param", "Invalid parameter type"); - success = 0; - break; - } - break; /* break for */ - } + struct Material* material = &renderer->materials[model->material->type]; + material_unregister_model(material, model); } - return success; -} - -int model_get_material_param(struct Entity* entity, const char* name, void* value_out) -{ - assert(name && value_out); - struct Model* model = &entity->model; - int success = 0; - struct Material* material = material_get(model->material); - for(int i = 0; i < array_len(model->material_params); i++) - { - struct Material_Param* param = &model->material_params[i]; - struct Uniform* uniform = &material->model_params[param->uniform_index]; - if(strcmp(uniform->name, name) == 0) - { - switch(uniform->type) - { - case UT_INT: *((int*)value_out) = *((int*)param->value); break; - case UT_FLOAT: *((float*)value_out) = *((float*)param->value); break; - case UT_VEC2: vec2_assign((vec2*)value_out, (vec2*)param->value); break; - case UT_VEC3: vec3_assign((vec3*)value_out, (vec3*)param->value); break; - case UT_VEC4: vec4_assign((vec4*)value_out, (vec4*)param->value); break; - case UT_MAT4: mat4_assign((mat4*)value_out, (mat4*)param->value); break; - } - success = 1; - break; - } - } - return success; -} +} \ No newline at end of file diff --git a/src/libsymmetry/model.h b/src/libsymmetry/model.h index 28a5821..66bcc73 100644 --- a/src/libsymmetry/model.h +++ b/src/libsymmetry/model.h @@ -1,13 +1,9 @@ #ifndef MODEL_H #define MODEL_H -#include "../common/linmath.h" +struct Model; -struct Entity; - -void model_create(struct Entity* entity, const char* geo_name, const char* material_name); -void model_destroy(struct Entity* entity); -int model_set_material_param(struct Entity* entity, const char* name, void* value); -int model_get_material_param(struct Entity* entity, const char* name, void* value_out); +void model_init(struct Model* model, const char* geometry_name, int material_type); +void model_reset(struct Model* model); #endif diff --git a/src/libsymmetry/renderer.c b/src/libsymmetry/renderer.c index 592655a..bd6d04d 100644 --- a/src/libsymmetry/renderer.c +++ b/src/libsymmetry/renderer.c @@ -22,31 +22,19 @@ #include "im_render.h" #include "../common/variant.h" #include "../common/common.h" +#include "scene.h" #include #include #include - -#define MAX_UNIFORM_NAME_LEN 64 - -/* TODO: Move all this into a struct called renderer state */ -static int def_fbo = -1; -static int def_albedo_tex = -1; -static int def_depth_tex = -1; -static int quad_geo = -1; -static int composition_shader = -1; -static int debug_shader = -1; - -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; - - -static struct Sprite_Batch* sprite_batch = NULL; +#include void on_framebuffer_size_change(int width, int height); -void renderer_init(void) +void renderer_init(struct Renderer* renderer) { + assert(renderer); + glClearColor(0.3f, 0.6f, 0.9f, 1.0f); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); @@ -78,7 +66,7 @@ void renderer_init(void) array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint); array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint); - quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL); + renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL); array_free(vertices); array_free(uvs); array_free(normals); @@ -87,66 +75,70 @@ void renderer_init(void) int width = -1, height = -1; struct Game_State* game_state = game_state_get(); platform->window.get_size(game_state->window, &width, &height); - def_albedo_tex = texture_create("def_albedo_texture", - TU_DIFFUSE, - width, height, - GL_RGB, - GL_RGB16F, - GL_FLOAT, - NULL); - texture_set_param(def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - texture_set_param(def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - texture_set_param(def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - texture_set_param(def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - def_depth_tex = texture_create("def_depth_texture", - TU_SHADOWMAP4, - width, height, - GL_DEPTH_COMPONENT, - GL_DEPTH_COMPONENT32F, - GL_FLOAT, - NULL); - texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - texture_set_param(def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - texture_set_param(def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - - def_fbo = framebuffer_create(width, height, true, false, true); - framebuffer_texture_set(def_fbo, def_albedo_tex, FA_COLOR_ATTACHMENT0); - framebuffer_texture_set(def_fbo, def_depth_tex, FA_DEPTH_ATTACHMENT); - composition_shader = shader_create("fbo.vert", "fbo.frag"); - debug_shader = shader_create("debug.vert", "debug.frag"); - - 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); - - sprite_batch = malloc(sizeof(*sprite_batch)); - if(!sprite_batch) + renderer->def_albedo_tex = texture_create("def_albedo_texture", + TU_DIFFUSE, + width, height, + GL_RGB, + GL_RGB16F, + GL_FLOAT, + NULL); + texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + renderer->def_depth_tex = texture_create("def_depth_texture", + TU_SHADOWMAP4, + width, height, + GL_DEPTH_COMPONENT, + GL_DEPTH_COMPONENT32F, + GL_FLOAT, + NULL); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + + renderer->def_fbo = framebuffer_create(width, height, true, false, true); + framebuffer_texture_set(renderer->def_fbo, renderer->def_albedo_tex, FA_COLOR_ATTACHMENT0); + framebuffer_texture_set(renderer->def_fbo, renderer->def_depth_tex, FA_DEPTH_ATTACHMENT); + renderer->composition_shader = shader_create("fbo.vert", "fbo.frag"); + renderer->debug_shader = shader_create("debug.vert", "debug.frag"); + + renderer->num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); + renderer->num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); + renderer->num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); + + renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch)); + if(!renderer->sprite_batch) { log_error("renderer:init", "Failed to allocated sprite batch"); } else { - sprite_batch_create(sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES); + sprite_batch_create(renderer->sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES); } im_init(); + + // Initialize materials + for(int i = 0; i < MAT_MAX; i++) + { + material_init(&renderer->materials[i], i); + } } -void renderer_draw(struct Entity* active_viewer) +void renderer_draw(struct Renderer* renderer, struct Scene* scene) { /* Render each camera output into it's framebuffer or to the default framebuffer */ - struct Entity* entity_list = entity_get_all(); - for(int i = 0; i < array_len(entity_list); i++) + for(int i = 0; i < MAX_CAMERAS; i++) { - struct Entity* viewer = &entity_list[i]; - if(entity_list[i].type != ET_CAMERA) continue; - struct Camera* camera = &viewer->camera; + struct Camera* camera = &scene->cameras[i]; + if(!camera->base.active) continue; - int fbo = camera->fbo == -1 ? def_fbo : camera->fbo; + int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; framebuffer_bind(fbo); { glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); @@ -160,35 +152,34 @@ void renderer_draw(struct Entity* active_viewer) glCullFace(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); static mat4 mvp; - struct Material* material_list = material_get_all_materials(); - for(int i = 0; i < array_len(material_list); i++) + for(int i = 0; i < MAT_MAX; i++) { /* for each material, get all the registered models and render them */ - struct Material* material = &material_list[i]; - if(!material->active || array_len(material->registered_models) == 0) + struct Material* material = &renderer->materials[i]; + if(array_len(material->registered_models) == 0) continue; - shader_bind(material->shader); - renderer_check_glerror("model:render_all:shader_bind"); + GL_CHECK(shader_bind(material->shader)); if(material->lit) /* Set light information */ { - int valid_light_count = 0; - int* light_index_list = light_get_valid_indices(&valid_light_count); char uniform_name[MAX_UNIFORM_NAME_LEN]; memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - for(int i = 0; i < valid_light_count; i++) + int light_count = 0; + for(int i = 0; i < MAX_LIGHTS; i++) { - struct Entity* light_entity = entity_get(light_index_list[i]); - struct Light* light = &light_entity->light; /* TODO: Cull lights according to camera frustum */ + struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */ + if(!light->base.active) continue; + light_count++; + vec3 light_pos = {0, 0, 0}; - transform_get_absolute_position(light_entity, &light_pos); + transform_get_absolute_position(&light->base, &light_pos); if(light->type != LT_POINT) { - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count); vec3 light_dir = {0.f, 0.f, 0.f}; - transform_get_absolute_lookat(light_entity, &light_dir); + transform_get_absolute_lookat(&light->base, &light_dir); vec3_norm(&light_dir, &light_dir); shader_set_uniform_vec3(material->shader, uniform_name, &light_dir); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); @@ -196,171 +187,123 @@ void renderer_draw(struct Entity* active_viewer) if(light->type != LT_DIR) { - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count); shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count); shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count); shader_set_uniform_float(material->shader, uniform_name, light->inner_angle); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count); shader_set_uniform_float(material->shader, uniform_name, light->falloff); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count); shader_set_uniform_int(material->shader, uniform_name, light->radius); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); } - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count); shader_set_uniform_vec3(material->shader, uniform_name, &light->color); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count); shader_set_uniform_float(material->shader, uniform_name, light->intensity); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", i); + snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count); shader_set_uniform_int(material->shader, uniform_name, light->type); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); } - shader_set_uniform_int(material->shader, "total_active_lights", valid_light_count); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_TOTAL_LIGHTS].type, material->pipeline_params[MPP_TOTAL_LIGHTS].location, &light_count)); vec3 camera_pos = {0, 0, 0}; - transform_get_absolute_position(viewer, &camera_pos); - shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos); + transform_get_absolute_position(&camera->base, &camera_pos); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos)); } /* Set material pipeline uniforms */ - static struct Render_Settings render_settings; - renderer_settings_get(&render_settings); - for(int k = 0; k < array_len(material->pipeline_params); k++) - { - struct Uniform* uniform = &material->pipeline_params[k]; - if(strcmp(uniform->name, "view_mat") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &viewer->camera.view_mat); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "fog.mode") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.mode); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "fog.density") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.density); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "fog.start_dist") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.start_dist); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "fog.max_dist") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.max_dist); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "fog.color") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.color); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "ambient_light") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &render_settings.ambient_light); - renderer_check_glerror("model:render_all:material_pipeline"); - } - } + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_START_DIST].type, material->pipeline_params[MPP_FOG_START_DIST].location, &renderer->settings.fog.start_dist)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MAX_DIST].type, material->pipeline_params[MPP_FOG_MAX_DIST].location, &renderer->settings.fog.max_dist)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light)); + if(material->lit) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); + for(int j = 0; j < array_len(material->registered_models); j++) { /* for each registered model, set up uniforms and render */ - struct Entity* entity = entity_get(material->registered_models[j]); - struct Model* model = &entity->model; - struct Transform* transform = &entity->transform; - struct Geometry* geometry = geom_get(model->geometry_index); + struct Static_Mesh* mesh = material->registered_models[i]; + struct Geometry* geometry = geom_get(mesh->model.geometry_index); /* Check if model is in frustum */ - int intersection = bv_intersect_frustum_sphere(viewer->camera.frustum, &geometry->bounding_sphere, entity); + vec3 abs_pos, abs_scale; + transform_get_absolute_position(&mesh->base, &abs_pos); + transform_get_absolute_scale(&mesh->base, &abs_scale); + int intersection = bv_intersect_frustum_sphere(&camera->frustum, &geometry->bounding_sphere, &abs_pos, &abs_scale); if(intersection == IT_OUTSIDE) { - num_culled++; + renderer->num_culled++; continue; } else { - num_indices += array_len(geometry->indices); - num_rendered++; + renderer->num_indices += array_len(geometry->indices); + renderer->num_rendered++; } - /* set material params for the model */ - for(int k = 0; k < array_len(model->material_params); k++) + for(int k = 0; k < MMP_MAX; k++) { - struct Material_Param* param = &model->material_params[k]; - struct Uniform* uniform = &material->model_params[param->uniform_index]; - shader_set_uniform(uniform->type, uniform->location, param->value); - renderer_check_glerror("model:render_all:material_param"); + switch(mesh->model.material_params[i].type) + { + case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_int)); break; + case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_float)); break; + case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_vec3)); break; + case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_vec4)); break; + } } /* Set pipeline uniforms that are derived per model */ - for(int k = 0; k < array_len(material->pipeline_params); k++) + mat4_identity(&mvp); + mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MVP].type, material->pipeline_params[MPP_MVP].location, &mvp)); + + if(material->lit) { - /* TODO: change this into something better */ - struct Uniform* uniform = &material->pipeline_params[k]; - if(strcmp(uniform->name, "mvp") == 0) - { - mat4_identity(&mvp); - mat4_mul(&mvp, &viewer->camera.view_proj_mat, &transform->trans_mat); - shader_set_uniform(uniform->type, uniform->location, &mvp); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "model_mat") == 0) - { - shader_set_uniform(uniform->type, uniform->location, &transform->trans_mat); - renderer_check_glerror("model:render_all:material_pipeline"); - } - else if(strcmp(uniform->name, "inv_model_mat") == 0) - { - mat4 inv_mat; - mat4_identity(&inv_mat); - mat4_inverse(&inv_mat, &transform->trans_mat); - shader_set_uniform(uniform->type, uniform->location, &inv_mat); - renderer_check_glerror("model:render_all:material_pipeline"); - } + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); + mat4 inv_mat; + mat4_identity(&inv_mat); + mat4_inverse(&inv_mat, &mesh->base.transform.trans_mat); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_INV_MODEL_MAT].type, material->pipeline_params[MPP_INV_MODEL_MAT].location, &inv_mat)); } /* Render the geometry */ //int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode); //geom_render(model->geometry_index, draw_mode); - geom_render(model->geometry_index, GDM_TRIANGLES); + geom_render(mesh->model.geometry_index, GDM_TRIANGLES); - for(int k = 0; k < array_len(model->material_params); k++) + for(int k = 0; k < MMP_MAX; k++) { /* unbind textures, if any */ - struct Material_Param* param = &model->material_params[k]; - struct Uniform* uniform = &material->model_params[param->uniform_index]; - if(uniform->type == UT_TEX) - { - texture_unbind(*(int*)param->value); - renderer_check_glerror("model:render_all:unbind_texture_uniform"); - } + if(material->model_params[k].type == UT_TEX) + GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int)); } } shader_unbind(); } - editor_debugvar_slot_set_int(num_rendered_slot, num_rendered); - editor_debugvar_slot_set_int(num_culled_slot, num_culled); - editor_debugvar_slot_set_int(num_indices_slot, num_indices); + editor_debugvar_slot_set_int(renderer->num_rendered_slot, renderer->num_rendered); + editor_debugvar_slot_set_int(renderer->num_culled_slot, renderer->num_culled); + editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices); - num_culled = num_rendered = num_indices = 0; + renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; } framebuffer_unbind(); glDisable(GL_DEPTH_TEST); @@ -368,16 +311,16 @@ void renderer_draw(struct Entity* active_viewer) } /* Final Render */ + struct Camera* active_camera = &scene->cameras[scene->active_camera_index]; int width, height; struct Game_State* game_state = game_state_get(); platform->window.get_size(game_state->window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - shader_bind(composition_shader); - struct Camera* active_camera = &active_viewer->camera; - int final_render_tex = active_camera->render_tex == -1 ? def_albedo_tex : active_camera->render_tex; + shader_bind(renderer->composition_shader); + int final_render_tex = active_camera->render_tex == -1 ? renderer->def_albedo_tex : active_camera->render_tex; texture_bind(final_render_tex); - geom_render(quad_geo, GDM_TRIANGLES); + geom_render(renderer->quad_geo, GDM_TRIANGLES); texture_unbind(final_render_tex); shader_unbind(); @@ -387,20 +330,20 @@ void renderer_draw(struct Entity* active_viewer) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); - shader_bind(debug_shader); + shader_bind(renderer->debug_shader); { static mat4 mvp; - shader_set_uniform_vec4(debug_shader, "debug_color", &debug_draw_color); - struct Entity* entity_list = entity_get_all(); - for(int i = 0; i < array_len(entity_list); i++) + shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color); + for(int i = 0; i < MAX_STATIC_MESHES; i++) { - if(!entity_list[i].renderable) continue; - struct Model* model = &entity_list[i].model; - struct Transform* transform = &entity_list[i].transform; + struct Static_Mesh* mesh = &scene->static_meshes[i]; + if(!mesh->base.active) continue; + struct Model* model = &mesh->model; + struct Transform* transform = &mesh->base.transform; int geometry = model->geometry_index; mat4_identity(&mvp); - mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &transform->trans_mat); - shader_set_uniform_mat4(debug_shader, "mvp", &mvp); + mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); + shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode")); } } @@ -412,39 +355,38 @@ void renderer_draw(struct Entity* active_viewer) if(hashmap_bool_get(cvars, "debug_draw_physics")) { static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; - struct Entity* entity_list = entity_get_all(); - for(int i = 0; i < array_len(entity_list); i++) + for(int i = 0; i < MAX_STATIC_MESHES; i++) { - if(!entity_list[i].has_collision) continue; - struct Entity* entity = &entity_list[i]; + struct Static_Mesh* mesh = &scene->static_meshes[i]; + if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue; //Get collision mesh and it's props then render it vec3 pos = {0.f}; quat rot = {0.f, 0.f, 0.f, 1.f }; - if(entity->collision.rigidbody) + if(mesh->collision.rigidbody) { - platform->physics.body_position_get(entity->collision.rigidbody, &pos.x, &pos.y, &pos.z); - platform->physics.body_rotation_get(entity->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w); + platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z); + platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w); } else { - platform->physics.cs_position_get(entity->collision.collision_shape, &pos.x, &pos.y, &pos.z); - platform->physics.cs_rotation_get(entity->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w); + platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z); + platform->physics.cs_rotation_get(mesh->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w); } - int collision_shape_type = platform->physics.cs_type_get(entity->collision.collision_shape); + int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape); switch(collision_shape_type) { case CST_SPHERE: { - float radius = platform->physics.cs_sphere_radius_get(entity->collision.collision_shape); + float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape); im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES); } break; case CST_BOX: { float x = 0.f, y = 0.f, z = 0.f; - platform->physics.cs_box_params_get(entity->collision.collision_shape, &x, &y, &z); + platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z); im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); }; break; @@ -454,11 +396,11 @@ void renderer_draw(struct Entity* active_viewer) } //Immediate mode geometry render - im_render(active_viewer); + im_render(active_camera); /* Render 2D stuff */ - shader_bind(sprite_batch->shader); + shader_bind(renderer->sprite_batch->shader); { static mat4 ortho_mat; mat4_identity(&ortho_mat); @@ -467,9 +409,9 @@ void renderer_draw(struct Entity* active_viewer) platform->window.get_size(game_state->window, &width, &height); mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f); - shader_set_uniform_mat4(sprite_batch->shader, "mvp", &ortho_mat); + shader_set_uniform_mat4(renderer->sprite_batch->shader, "mvp", &ortho_mat); - sprite_batch_render(sprite_batch); + sprite_batch_render(renderer->sprite_batch); } shader_unbind(); @@ -477,28 +419,30 @@ void renderer_draw(struct Entity* active_viewer) gui_render(NK_ANTI_ALIASING_ON); } -void renderer_cleanup(void) +void renderer_cleanup(struct Renderer* renderer) { + for(int i = 0; i < MAT_MAX; i++) + { + material_reset(&renderer->materials[i], i); + } im_cleanup(); - sprite_batch_remove(sprite_batch); - free(sprite_batch); + sprite_batch_remove(renderer->sprite_batch); + free(renderer->sprite_batch); gui_cleanup(); - geom_remove(quad_geo); - framebuffer_remove(def_fbo); - texture_remove(def_albedo_tex); - texture_remove(def_depth_tex); + geom_remove(renderer->quad_geo); + framebuffer_remove(renderer->def_fbo); + texture_remove(renderer->def_albedo_tex); + texture_remove(renderer->def_depth_tex); } void on_framebuffer_size_change(int width, int height) { - struct Entity* entity_list = entity_get_all(); + struct Scene* scene = &game_state_get()->scene; float aspect = (float)width / (float)height; - for(int i = 0; i < array_len(entity_list); i++) + for(int i = 0; i < MAX_CAMERAS; 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; + struct Camera* viewer = &scene->cameras[i]; + viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; camera_update_proj(viewer); } @@ -533,9 +477,9 @@ int renderer_check_glerror(const char* context) return error; } -struct Sprite_Batch * get_batch(void) +struct Material * renderer_material_get(int material_type) { - return sprite_batch; + return NULL; } void renderer_debug_draw_enabled(bool enabled) diff --git a/src/libsymmetry/renderer.h b/src/libsymmetry/renderer.h index 1db71f6..0370854 100644 --- a/src/libsymmetry/renderer.h +++ b/src/libsymmetry/renderer.h @@ -3,6 +3,9 @@ #include "../common/linmath.h" #include "../common/num_types.h" +#include "material.h" + +struct Sprite_Batch; enum Fog_Mode { @@ -14,11 +17,11 @@ enum Fog_Mode struct Fog { - int mode; + int mode; float density; float start_dist; float max_dist; - vec3 color; + vec3 color; }; @@ -32,18 +35,25 @@ struct Render_Settings bool debug_draw_physics; }; -struct Entity; -struct Sprite_Batch; +struct Renderer +{ + int def_fbo; + int def_albedo_tex; + int def_depth_tex; + int quad_geo; + int composition_shader; + int debug_shader; + int num_culled , num_rendered , num_indices; + int num_culled_slot, num_rendered_slot, num_indices_slot; + struct Sprite_Batch* sprite_batch; + struct Render_Settings settings; + struct Material materials[MAT_MAX]; +}; -void renderer_settings_get(struct Render_Settings* settings); -void renderer_settings_set(const struct Render_Settings* settings); -void renderer_init(void); -void renderer_draw(struct Entity* active_viewer); -void renderer_cleanup(void); +void renderer_init(struct Renderer* renderer); +void renderer_draw(struct Renderer* renderer, struct Scene* scene); +void renderer_cleanup(struct Renderer* renderer); void renderer_clearcolor_set(float r, float g, float b, float a); -void renderer_debug_draw_enabled(bool enabled); -int renderer_check_glerror(const char* context); - -struct Sprite_Batch* get_batch(void); +void renderer_debug_draw_enabled(struct Renderer* renderer, bool enabled); #endif diff --git a/src/libsymmetry/scene.c b/src/libsymmetry/scene.c index 866bf95..dc50bf4 100644 --- a/src/libsymmetry/scene.c +++ b/src/libsymmetry/scene.c @@ -3,140 +3,530 @@ #include "entity.h" #include "../common/log.h" #include "transform.h" +#include "camera.h" #include "../common/common.h" #include "../common/parser.h" +#include "model.h" #include #include +#include -static int root_node = -1; +void scene_init(struct Scene* scene) +{ + assert(scene); + //Initialize the root entity + entity_init(&scene->root_entity, "ROOT_ENTITY", NULL); + scene->root_entity.active = true; + scene->root_entity.id = 0; + scene->root_entity.type = ET_ROOT; + + //Initialize player + entity_init(&scene->player, "Player", &scene->root_entity); + scene->player.base.active = true; + scene->player.base.id = 1; + scene->player.base.type = ET_PLAYER; + + for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i); + for(int i = 0; i < MAX_LIGHTS; i++) entity_reset(&scene->lights[i], i); + for(int i = 0; i < MAX_STATIC_MESHES; i++) + { + entity_reset(&scene->static_meshes[i], i); + struct Static_Mesh* mesh = &scene->static_meshes[i]; + mesh->collision.collision_shape = NULL; + mesh->collision.rigidbody = NULL; + mesh->collision.on_collision = NULL; + mesh->model.geometry_index = -1; + mesh->model.material = NULL; + } + for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i); + for(int i = 0; i < MAX_CAMERAS; i++) + { + entity_init(&scene->cameras[i], NULL, &scene->root_entity); + camera_init(&scene->cameras[i], 1024, 768); + scene->cameras[i].base.id = i; + } + + scene->active_camera_index = CT_EDITOR; +} -void scene_init(void) +bool scene_load(struct Scene* scene, const char* filename, int dir_type); +bool scene_save(struct Scene* scene, const char* filename, int dir_type); + +void scene_destroy(struct Scene* scene) { - /* Add root node to scene */ - /*struct Entity* root = entity_create("ROOT", ET_ROOT, -1); - root_node = root->id; */ + assert(scene); + + for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_remove(scene, &scene->entities[i]); + for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]); + for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]); + for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); + for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); + entity_reset(&scene->root_entity, 0); + scene->root_entity.active = false; } -struct Entity* scene_add_new(const char* name, const int type) +void scene_post_update(struct Scene* scene) { - if(root_node == -1) + assert(scene); + + for(int i = 0; i < MAX_ENTITIES; i++) + { + struct Entity* entity = &scene->entities[i]; + if(!entity->active) continue; + + if(entity->marked_for_deletion) + { + scene_entity_remove(scene, entity); + continue; + } + + if(entity->transform.is_modified) entity->transform.is_modified = false; + } + + for(int i = 0; i < MAX_CAMERAS; i++) + { + struct Camera* camera = &scene->cameras[i]; + if(!camera->base.active) continue; + + if(camera->base.marked_for_deletion) + { + scene_camera_remove(scene, camera); + continue; + } + + if(camera->base.transform.is_modified) + { + camera_update_view(camera); + camera->base.transform.is_modified = false; + } + } + + for(int i = 0; i < MAX_SOUND_SOURCES; i++) + { + struct Sound_Source* sound_source = &scene->sound_sources[i]; + if(!sound_source->base.active) continue; + + if(sound_source->base.marked_for_deletion) + { + scene_sound_source_remove(scene, sound_source); + continue; + } + + if(sound_source->base.transform.is_modified) + { + vec3 abs_pos = {0.f, 0.f, 0.f}; + transform_get_absolute_position(&sound_source->base, &abs_pos); + platform->sound.source_instance_update_position(sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); + sound_source->base.transform.is_modified = false; + } + } + + for(int i = 0; i < MAX_STATIC_MESHES; i++) + { + struct Static_Mesh* static_mesh = &scene->static_meshes[i]; + if(!static_mesh->base.active) continue; + + if(static_mesh->base.marked_for_deletion) + { + scene_static_mesh_remove(scene, static_mesh); + continue; + } + + if(static_mesh->base.transform.is_modified) + { + if(static_mesh->collision.rigidbody && static_mesh->base.transform.sync_physics) + { + quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; + vec3 abs_pos = {0.f, 0.f, 0.f}; + transform_get_absolute_rot(&static_mesh->base, &abs_rot); + transform_get_absolute_position(&static_mesh->base, &abs_pos); + platform->physics.body_rotation_set(static_mesh->collision.rigidbody, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w); + platform->physics.body_position_set(static_mesh->collision.rigidbody, abs_pos.x, abs_pos.y, abs_pos.z); + } + static_mesh->base.transform.sync_physics = false; + static_mesh->base.transform.is_modified = false; + } + } + + for(int i = 0; i < MAX_LIGHTS; i++) + { + struct Light* light = &scene->lights[i]; + if(!light->base.active) continue; + + if(light->base.marked_for_deletion) + { + scene_light_remove(scene, light); + continue; + } + + if(light->base.transform.is_modified) light->base.transform.is_modified = false; + } + + for(int i = 0; i < MAX_ENTITIES; i++) { - log_warning("No root node in scene"); - struct Entity* root = entity_create("ROOT", ET_ROOT, -1); - root_node = root->id; + struct Entity* entity = &scene->entities[i]; + if(!entity->active) continue; + } + + if(scene->player.base.transform.is_modified) + { + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_position(&scene->player, &abs_pos); + transform_get_absolute_forward(&scene->player, &abs_fwd); + transform_get_absolute_up(&scene->player, &abs_up); + + platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, + abs_fwd.x, abs_fwd.y, abs_fwd.z, + abs_up.x, abs_up.y, abs_up.z); + scene->player.base.transform.is_modified = false; } - return scene_add_as_child(name, type, root_node); } -struct Entity* scene_add_as_child(const char* name, const int type, int parent_id) +struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent) { - assert(parent_id > -1); - return entity_create(name, type, parent_id); + assert(scene); + + struct Entity* new_entity = NULL; + for(int i = 0; i < MAX_ENTITIES; i++) + { + struct Entity* entity = &scene->entities[i]; + if(!entity->active) + { + new_entity = entity; + break; + } + } + + if(new_entity) + { + if(!parent) + parent = &scene->root_entity; + entity_init(new_entity, name, parent); + } + else + { + log_error("scene:entity_create", "Max entity limit reached!"); + } + + return new_entity; } -void scene_remove(struct Entity* entity) +struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type) { - assert(entity); - for(int i = 0; i < array_len(entity->transform.children); i++) + assert(scene); + struct Light* new_light = NULL; + for(int i = 0; i < MAX_LIGHTS; i++) + { + struct Light* light = &scene->lights[i]; + if(!light->base.active) + { + new_light = light; + break; + } + } + + if(new_light) + { + entity_init(&new_light->base, name, parent); + new_light->base.type = ET_LIGHT; + light_init(new_light, light_type); + } + else { - struct Entity* child = entity_get(entity->transform.children[i]); - scene_remove(child); + log_error("scene:light_create", "Max light limit reached!"); } - entity_remove(entity->id); + + return new_light; } -void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) +struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height) { - assert(entity && new_parent); - struct Entity* curr_parent = entity_get(entity->transform.parent); - if(curr_parent) + assert(scene); + struct Camera* new_camera = NULL; + for(int i = 0; i < MAX_CAMERAS; i++) { - /* 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->transform.children); i++) + struct Camera* camera = &scene->cameras[i]; + if(!camera->base.active) { - if(curr_parent->transform.children[i] == entity->id) - { - index = i; - break; - } + new_camera = camera; + break; } + } - if(index > -1) + if(new_camera) + { + entity_init(&new_camera->base, name, parent); + new_camera->base.type = ET_CAMERA; + camera_init(new_camera, width, height); + } + else + { + log_error("scene:camera_create", "Max camera limit reached!"); + } + + return new_camera; +} + +struct Static_Model* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type) +{ + assert(scene); + struct Static_Mesh* new_static_model = NULL; + for(int i = 0; i < MAX_STATIC_MESHES; i++) + { + struct Static_Mesh* static_model = &scene->static_meshes[i]; + if(!static_model->base.active) + { + new_static_model = static_model; + break; + } + } + + if(new_static_model) + { + entity_init(&new_static_model->base, name, parent); + new_static_model->base.type = ET_STATIC_MODEL; + model_init(&new_static_model->model, geometry_name, material_type); + // TODO: handle creating collision mesh for the model at creation + } + else + { + log_error("scene:model_create", "Max model limit reached!"); + } + + return new_static_model; +} + +struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play) +{ + assert(scene && filename); + struct Sound_Source* new_sound_source = NULL; + for(int i = 0; i < MAX_SOUND_SOURCES; i++) + { + struct Sound_Source* sound_source = &scene->static_meshes[i]; + if(!sound_source->base.active) { - 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); + new_sound_source = sound_source; + break; } - else + } + + if(new_sound_source) + { + entity_init(&new_sound_source->base, name, parent); + new_sound_source->base.type = ET_SOUND_SOURCE; + struct Entity* entity = &new_sound_source->base; + + new_sound_source->source_buffer = platform->sound.source_create(filename, type); + if(!new_sound_source->source_buffer) { - log_error("scene:reset_parent", "Entity %s not found in it's parent '%s''s children array"); + log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name); + new_sound_source->source_instance = 0; + return new_sound_source; } + + new_sound_source->source_instance = platform->sound.source_instance_create(new_sound_source->source_buffer, true); + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_position(entity, &abs_pos); + transform_get_absolute_forward(entity, &abs_fwd); + transform_get_absolute_up(entity, &abs_up); + platform->sound.source_instance_update_position(new_sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z); + + new_sound_source->loop = loop; + new_sound_source->min_distance = 0.f; + new_sound_source->max_distance = 10.f; + new_sound_source->playing = play; + new_sound_source->attenuation_type = SA_INVERSE; + new_sound_source->rolloff_factor = 0.95f; + new_sound_source->volume = 1.f; + new_sound_source->type = type; + + platform->sound.source_instance_loop_set(new_sound_source->source_instance, new_sound_source->loop); + platform->sound.source_instance_min_max_distance_set(new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance); + platform->sound.source_instance_attenuation_set(new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor); + platform->sound.source_instance_volume_set(new_sound_source->source_instance, new_sound_source->volume); + + platform->sound.update_3d(); + if(new_sound_source->playing) platform->sound.source_instance_play(new_sound_source->source_instance); } else { - log_error("scene:reset_parent", "Cannot change parent of ROOT entity"); + log_error("scene:sound_source_create", "Max sound source limit reached!"); } + + return new_sound_source; +} + +struct Player* scene_player_get(struct Scene* scene) +{ + assert(scene); + return &scene->player; +} + +void scene_entity_remove(struct Scene* scene, struct Entity* entity) +{ + assert(scene && entity && entity->id >= 0); + + if(!entity->active) return; + + transform_destroy(entity); + entity->active = false; + entity->editor_selected = false; + entity->marked_for_deletion = false; + memset(entity->name, '\0', MAX_ENTITY_NAME_LEN); +} + +void scene_light_remove(struct Scene* scene, struct Light* light) +{ + assert(scene && light); + scene_entity_remove(scene, &light->base); +} + +void scene_camera_remove(struct Scene* scene, struct Camera* camera) +{ + assert(scene && camera); + scene_entity_remove(scene, &camera->base); } -void scene_cleanup(void) +void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh) { - struct Entity* entity_list = entity_get_all(); - for(int i = 0; i < array_len(entity_list); i++) + assert(scene && mesh); + + mesh->collision.on_collision = NULL; + if(mesh->collision.collision_shape) platform->physics.cs_remove(mesh->collision.collision_shape); + if(mesh->collision.rigidbody) platform->physics.body_remove(mesh->collision.rigidbody); + + model_reset(&mesh->model); + scene_entity_remove(scene, &mesh->base); +} + +void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source) +{ + assert(scene && source); + + platform->sound.source_instance_destroy(source->source_instance); + source->source_instance = 0; + scene_entity_remove(scene, &source->base); +} + +struct Entity* scene_entity_find(struct Scene* scene, const char* name) +{ + assert(scene && name); + struct Entity* entity = NULL; + + for(int i = 0; i < MAX_ENTITIES; i++) { - if(entity_list[i].id != -1) - entity_remove(i); + if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0) + { + entity = &scene->entities[i]; + break; + } } - entity_post_update(); + + return entity; } -struct Entity* scene_find(const char* name) +struct Light* scene_light_find(struct Scene* scene, const char* name) { - return entity_find(name); + assert(scene && name); + struct Light* light = NULL; + + for(int i = 0; i < MAX_ENTITIES; i++) + { + if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0) + { + light = &scene->lights[i]; + break; + } + } + + return light; } -struct Entity* scene_get_root(void) +struct Camera* scene_camera_find(struct Scene* scene, const char* name) { - return entity_get(root_node); -} - -void scene_root_set(struct Entity* entity) -{ - // Only use this function when we know the scene is empty and needs a root node. - // This is just a temporary way of setting root until we finalize how a scene should work - if(root_node == -1) - root_node = entity->id; - else - log_error("scene:root_set", "Scene already has a root node!"); + assert(scene && name); + struct Camera* camera = NULL; + + for(int i = 0; i < MAX_ENTITIES; i++) + { + if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0) + { + camera = &scene->cameras[i]; + break; + } + } + + return camera; } -struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name) +struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name) { - assert(parent); - struct Entity* child = NULL; - for(int i = 0; i < array_len(parent->transform.children); i++) + assert(scene && name); + struct Static_Mesh* static_mesh = NULL; + + for(int i = 0; i < MAX_ENTITIES; i++) + { + if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0) + { + static_mesh = &scene->static_meshes[i]; + break; + } + } + + return static_mesh; +} + +struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name) +{ + assert(scene && name); + struct Sound_Source* sound_source = NULL; + + for(int i = 0; i < MAX_ENTITIES; i++) { - struct Entity* curr_child = entity_get(parent->transform.children[i]); - if(strcmp(curr_child->name, name) == 0) + if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { - child = curr_child; + sound_source = &scene->sound_sources[i]; break; } } - return child; + + return sound_source; +} + +void* scene_find(struct Scene* scene, const char* name) +{ + void* entity = NULL; + + entity = scene_entity_find(scene, name); + if(entity) return entity; + + entity = scene_light_find(scene, name); + if(entity) return entity; + + entity = scene_camera_find(scene, name); + if(entity) return entity; + + entity = scene_static_mesh_find(scene, name); + if(entity) return entity; + + return entity; +} + +void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity) +{ + assert(scene && entity); + transform_parent_set(entity, &scene->root_entity, true); } -struct Entity* scene_get_parent(struct Entity* entity) +void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent) { - assert(entity); - struct Entity* parent = NULL; - if(entity->transform.parent != -1) - parent = entity_get(entity->transform.parent); - return parent; + assert(scene && entity && parent); + transform_parent_set(entity, parent, true); } bool scene_load(const char* filename, int directory_type) @@ -179,7 +569,7 @@ bool scene_load(const char* filename, int directory_type) bool scene_save(const char* filename, int directory_type) { bool success = false; - FILE* scene_file = platform->file.open(directory_type, filename, "w"); + /*FILE* scene_file = platform->file.open(directory_type, filename, "w"); if(!scene_file) { log_error("scene:save", "Failed to create scenefile %s for writing", filename); @@ -236,7 +626,7 @@ bool scene_save(const char* filename, int directory_type) array_free(entities_to_write); parser_free(parser); - fclose(scene_file); + fclose(scene_file);*/ return success; } diff --git a/src/libsymmetry/scene.h b/src/libsymmetry/scene.h index 401747d..bb27bc7 100644 --- a/src/libsymmetry/scene.h +++ b/src/libsymmetry/scene.h @@ -1,23 +1,71 @@ #ifndef SCENE_H #define SCENE_H -#include "../common/num_types.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 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); -void scene_root_set(struct Entity* entity); -struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); -struct Entity* scene_get_parent(struct Entity* entity); -bool scene_load(const char* filename, int directory_type); -bool scene_save(const char* filename, int directory_type); +#include "entity.h" +#include "renderer.h" + +#define MAX_ENTITIES 1024 +#define MAX_LIGHTS 30 +#define MAX_CAMERAS 2 +#define MAX_STATIC_MESHES 1024 +#define MAX_SOUND_SOURCES 128 + +struct Scene +{ + struct Render_Settings renderer_profile; + struct Entity root_entity; + struct Player player; + struct Entity entities[MAX_ENTITIES]; + struct Static_Mesh static_meshes[MAX_STATIC_MESHES]; + struct Camera cameras[MAX_CAMERAS]; + struct Light lights[MAX_LIGHTS]; + struct Sound_Source sound_sources[MAX_SOUND_SOURCES]; + int active_camera_index; +}; + +void scene_init(struct Scene* scene); +bool scene_load(struct Scene* scene, const char* filename, int dir_type); +bool scene_save(struct Scene* scene, const char* filename, int dir_type); +void scene_destroy(struct Scene* scene); +void scene_post_update(struct Scene* scene); + +struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent); +struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type); +struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height); +struct Static_Model* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type); +struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play); +struct Player* scene_player_get(struct Scene* scene); + +void scene_entity_remove(struct Scene* scene, struct Entity* entity); +void scene_light_remove(struct Scene* scene, struct Light* light); +void scene_camera_remove(struct Scene* scene, struct Camera* camera); +void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh); +void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source); + +void* scene_find(struct Scene* scene, const char* name); // Looks in all entity type arrays and returns the first one found. Result should be cast back to expected type +struct Entity* scene_entity_find(struct Scene* scene, const char* name); +struct Light* scene_light_find(struct Scene* scene, const char* name); +struct Camera* scene_camera_find(struct Scene* scene, const char* name); +struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name); +struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name); + +void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent); +void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent + +// +//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 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); +//void scene_root_set(struct Entity* entity); +//struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); +//struct Entity* scene_get_parent(struct Entity* entity); +//bool scene_load(const char* filename, int directory_type); +//bool scene_save(const char* filename, int directory_type); #endif diff --git a/src/libsymmetry/transform.c b/src/libsymmetry/transform.c index 6f8d332..5f49425 100644 --- a/src/libsymmetry/transform.c +++ b/src/libsymmetry/transform.c @@ -5,17 +5,17 @@ #include "../common/utils.h" #include -void transform_create(struct Entity* entity, int parent_entity) +void transform_init(struct Entity* entity, struct Entity* parent) { struct Transform* transform = &entity->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->children = array_new(int); - transform->parent = -1; - if(parent_entity != -1) - transform_parent_set(entity, entity_get(parent_entity), false); + transform->children = array_new(struct Entity*); + transform->parent = NULL; + if(parent) + transform_parent_set(entity, parent, false); transform_update_transmat(entity); } @@ -26,11 +26,11 @@ void transform_child_add(struct Entity* parent, struct Entity* child, bool updat /* Check if already added */ for(int i = 0; i < array_len(parent_transform->children); i++) - if(parent_transform->children[i] == child->id) return; + if(parent_transform->children[i] == child) return; - int* new_child_loc = array_grow(parent_transform->children, int); - *new_child_loc = child->id; - child_transform->parent = parent->id; + struct Entity** new_child_loc = array_grow(parent_transform->children, struct Entity*); + *new_child_loc = child; + child_transform->parent = parent; if(update_transmat) transform_update_transmat(child); } @@ -40,10 +40,10 @@ bool transform_child_remove(struct Entity* parent, struct Entity* child) struct Transform* parent_transform = &parent->transform; for(int i = 0; i < array_len(parent_transform->children); i++) { - if(parent_transform->children[i] == child->id) + if(parent_transform->children[i] == child) { array_remove_at(parent_transform, i); - child->transform.parent = -1; + child->transform.parent = NULL; success = true; return success; }; @@ -53,7 +53,7 @@ bool transform_child_remove(struct Entity* parent, struct Entity* child) void transform_parent_set(struct Entity* child, struct Entity* parent, bool update_transmat) { - if(child->transform.parent == -1) + if(child->transform.parent == NULL) { transform_child_add(parent, child, false); } @@ -77,7 +77,7 @@ void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Spa } else if(space == TS_PARENT) { - struct Entity* parent = entity_get_parent(transform->parent); + struct Entity* parent = transform->parent; if(parent) { struct Transform* parent_tran = &parent->transform; @@ -189,10 +189,9 @@ void transform_update_transmat(struct Entity* entity) mat4_mul(&transform->trans_mat, &transform->trans_mat, &rotation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &scale); - struct Entity* parent = entity_get(transform->parent); - if(parent) + if(transform->parent) { - struct Transform* parent_tran = &parent->transform; + struct Transform* parent_tran = &transform->parent->transform; mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat); } @@ -201,13 +200,10 @@ void transform_update_transmat(struct Entity* entity) if(children > 0) { for(int i = 0; i < children; i++) - { - struct Entity* child = entity_get(transform->children[i]); - transform_update_transmat(child); - } + transform_update_transmat(entity->transform.children[i]); } transform->is_modified = true; - if(entity->has_collision) entity->transform.sync_physics = true; + if(entity->type == ET_STATIC_MODEL) entity->transform.sync_physics = true; // Find a better way to handle this } void transform_destroy(struct Entity* entity) @@ -218,7 +214,7 @@ void transform_destroy(struct Entity* entity) { for(int i = 0; i < children; i++) { - struct Entity* child = entity_get(transform->children[i]); + struct Entity* child = transform->children[i]; child->marked_for_deletion = true; } } @@ -229,7 +225,7 @@ void transform_destroy(struct Entity* entity) vec3_fill(&transform->scale, 1.f, 1.f, 1.f); quat_identity(&transform->rotation); mat4_identity(&transform->trans_mat); - transform->parent = -1; + transform->parent = NULL; transform->is_modified = false; } @@ -244,7 +240,7 @@ void transform_get_absolute_position(struct Entity* entity, vec3* res) { vec3_assign(res, &entity->transform.position); bool done = false; - struct Entity* parent = entity_get(entity->transform.parent); + struct Entity* parent = entity->transform.parent; while(!done) { if(!parent) @@ -253,7 +249,7 @@ void transform_get_absolute_position(struct Entity* entity, vec3* res) break; } vec3_add(res, res, &parent->transform.position); - parent = entity_get(parent->transform.parent); + parent = parent->transform.parent; } } @@ -262,7 +258,7 @@ void transform_get_absolute_scale(struct Entity* entity, vec3* res) struct Transform* transform = &entity->transform; vec3_assign(res, &transform->scale); bool done = false; - struct Entity* parent = entity_get(transform->parent); + struct Entity* parent = transform->parent; while(!done) { if(!parent) @@ -271,7 +267,7 @@ void transform_get_absolute_scale(struct Entity* entity, vec3* res) break; } vec3_mul(res, res, &parent->transform.scale); - parent = entity_get(parent->transform.parent); + parent = parent->transform.parent; } } @@ -280,7 +276,7 @@ void transform_get_absolute_rot(struct Entity* entity, quat* res) { quat_assign(res, &entity->transform.rotation); bool done = false; - struct Entity* parent = entity_get(entity->transform.parent); + struct Entity* parent = entity->transform.parent; while(!done) { if(!parent) @@ -289,6 +285,6 @@ void transform_get_absolute_rot(struct Entity* entity, quat* res) break; } quat_mul(res, res, &parent->transform.rotation); - parent = entity_get(parent->transform.parent); + parent = parent->transform.parent; } } diff --git a/src/libsymmetry/transform.h b/src/libsymmetry/transform.h index 9a2beac..eabded7 100644 --- a/src/libsymmetry/transform.h +++ b/src/libsymmetry/transform.h @@ -8,7 +8,7 @@ enum Transform_Space { TS_LOCAL, TS_PARENT, TS_WORLD}; struct Entity; -void transform_create(struct Entity* entity, int parent_entity); +void transform_init(struct Entity* entity, struct Entity* parent); void transform_destroy(struct Entity* entity); void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Space space); void transform_rotate(struct Entity* transform,