diff --git a/orgfile.org b/orgfile.org index 2e90dc9..c72ad07 100644 --- a/orgfile.org +++ b/orgfile.org @@ -108,8 +108,11 @@ x Font atlas proper cleanup - Decoupled event handling of gui and input if possible - Custom rendering for gui ** TODO Allow passsing base path as commandline argument? +** TODO 3d sound using OpenAL +** TODO Array-based Hashmaps ** TODO Sprite sheet animations ** TODO Replace orgfile with simple text readme and reduce duplication? +** TODO Live data views in editor ** DONE Camera resize on window reisze - State "DONE" from "TODO" [2017-03-20 Mon 15:22] ** DONE Resizable framebuffers and textures diff --git a/src/editor.c b/src/editor.c index d7ec905..56cbc2c 100644 --- a/src/editor.c +++ b/src/editor.c @@ -14,17 +14,31 @@ #include "transform.h" #include "game.h" #include "gui.h" +#include "array.h" +#include "variant.h" +#include "string_utils.h" #include +#include +#include struct Editor_State { int enabled; int renderer_settings_window; + int debug_vars_window; int top_panel_height; }; -static struct Editor_State editor_state; +struct Debug_Variable +{ + struct Variant data; + char* name; +}; + +static struct Editor_State editor_state; +static struct Debug_Variable* debug_vars_list = NULL; +static int* empty_indices = NULL; static void editor_color_combo(struct nk_context* context, vec4* color, int width, int height); @@ -32,7 +46,83 @@ void editor_init(void) { editor_state.enabled = 1; editor_state.renderer_settings_window = 0; + editor_state.debug_vars_window = 0; editor_state.top_panel_height = 30; + debug_vars_list = array_new_cap(struct Debug_Variable, 20); + empty_indices = array_new(int); +} + +int editor_debugvar_slot_create(const char* name, int value_type) +{ + int index = -1; + struct Debug_Variable* debug_var = NULL; + if(array_len(empty_indices) > 0) + { + index = *array_get_last(empty_indices, int); + array_pop(empty_indices); + debug_var = &debug_vars_list[index]; + } + else + { + debug_var = array_grow(debug_vars_list, struct Debug_Variable); + index = array_len(debug_vars_list) - 1; + } + debug_var->name = str_new(name); + debug_var->data.type = value_type; + + return index; +} + +void editor_debugvar_slot_remove(int index) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + struct Debug_Variable* debug_var = &debug_vars_list[index]; + variant_free(&debug_var->data); + if(debug_var->name) free(debug_var->name); + debug_var->name = NULL; + debug_var->data.type = VT_NONE; +} + +void editor_debugvar_slot_set_float(int index, float value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_float(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_int(int index, int value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_int(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_double(int index, double value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_double(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_vec2(int index, vec2* value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_vec2(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_vec3(int index, vec3* value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_vec3(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_vec4(int index, vec4* value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_vec4(&debug_vars_list[index].data, value); +} + +void editor_debugvar_slot_set_quat(int index, quat* value) +{ + assert(index > -1 && index < array_len(debug_vars_list)); + variant_assign_quat(&debug_vars_list[index].data, value); } void editor_update(float dt) @@ -46,13 +136,18 @@ void editor_update(float dt) int win_width = 0, win_height = 0; window_get_drawable_size(game_state->window, &win_width, &win_height); int half_width = win_width / 2, half_height = win_height / 2; - + static int default_window_flags = NK_WINDOW_BORDER | + NK_WINDOW_CLOSABLE | + NK_WINDOW_MOVABLE | + NK_WINDOW_SCROLL_AUTO_HIDE | + NK_WINDOW_SCALABLE | + NK_WINDOW_MINIMIZABLE; /* Top Panel */ if(nk_begin(context, "Top_Panel", nk_recti(0, 0, win_width, win_height - (win_height - editor_state.top_panel_height)), NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR)) { - float ratios[] = {0.1f, 0.8f, 0.1f}; + float ratios[] = {0.1f, 0.1f, 0.7f, 0.1f}; static int frames = 0; static int fps = 0; static float seconds = 0.f; @@ -60,24 +155,24 @@ void editor_update(float dt) frames++; if(seconds >= 1.f) { - fps = frames; + fps = frames; seconds = 0.f; - frames = 0; + frames = 0; } - nk_layout_row(context, NK_DYNAMIC, 22, 3, ratios); + nk_layout_row(context, NK_DYNAMIC, 22, 4, ratios); if(nk_button_label(context, "Render Settings")) editor_state.renderer_settings_window = !editor_state.renderer_settings_window; + if(nk_button_label(context, "Debug Variables")) + editor_state.debug_vars_window = !editor_state.debug_vars_window; nk_spacing(context, 1); nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); } nk_end(context); - /* Debug Window */ + /* Render Settings Window */ if(editor_state.renderer_settings_window) { - if(nk_begin_titled(context, "Renderer_Settings_Window", "Renderer Settings", nk_rect(half_width, half_height, 300, 350), - NK_WINDOW_BORDER | NK_WINDOW_CLOSABLE | NK_WINDOW_MOVABLE | - NK_WINDOW_SCROLL_AUTO_HIDE | NK_WINDOW_SCALABLE | NK_WINDOW_MINIMIZABLE)) + if(nk_begin_titled(context, "Renderer_Settings_Window", "Renderer Settings", nk_rect(half_width, half_height, 300, 350), default_window_flags)) { if(nk_tree_push(context, NK_TREE_TAB, "Debug", NK_MAXIMIZED)) { @@ -144,8 +239,7 @@ void editor_update(float dt) 5.f, 10.f); nk_tree_pop(context); - } - + } } else { @@ -153,6 +247,43 @@ void editor_update(float dt) } nk_end(context); } + + /* Debug Vars Window */ + if(editor_state.debug_vars_window) + { + if(nk_begin_titled(context, "Debug_Variables_Window", "Debug Variables", nk_rect(20, 20, 300, 300), default_window_flags)) + { + nk_layout_row_static(context, 200, 200, 2); + if(nk_group_begin(context, "Name", NK_WINDOW_BORDER | NK_WINDOW_TITLE | NK_WINDOW_SCROLL_AUTO_HIDE)) + { + for(int i = 0; i < array_len(debug_vars_list); i++) + { + struct Debug_Variable* debug_var = &debug_vars_list[i]; + if(debug_var->data.type == VT_NONE) continue; + nk_layout_row_dynamic(context, 20, 2); + nk_label(context, debug_var->name, NK_TEXT_ALIGN_LEFT); + struct Variant* var_data = &debug_var->data; + switch(debug_var->data.type) + { + case VT_INT: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", var_data->val_int); break; + case VT_FLOAT: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.4f", var_data->val_float); break; + case VT_DOUBLE: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", var_data->val_double); break; + case VT_VEC2: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "(%.2f, %.2f)", var_data->val_vec2.x, var_data->val_vec2.y); break; + case VT_VEC3: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "(%.2f, %.2f, %.2f)", var_data->val_vec3.x, var_data->val_vec3.y, var_data->val_vec3.z); break; + case VT_VEC4: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "(%.2f, %.2f, %.2f, %.2f)", var_data->val_vec4.x, var_data->val_vec4.y, var_data->val_vec4.z, var_data->val_vec4.w); break; + case VT_QUAT: nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "(%.2f, %.2f, %.2f, %.2f)", var_data->val_quat.x, var_data->val_quat.y, var_data->val_quat.z, var_data->val_quat.w); break; + default: nk_label(context, "Unsupported Value type", NK_TEXT_ALIGN_RIGHT); break; + }; + } + nk_group_end(context); + } + } + else + { + editor_state.debug_vars_window = 0; + } + nk_end(context); + } } void editor_toggle(void) @@ -194,3 +325,11 @@ void editor_color_combo(struct nk_context* context, vec4* color, int width, int nk_combo_end(context); } } + +void editor_cleanup(void) +{ + for(int i = 0; i < array_len(debug_vars_list); i++) + editor_debugvar_slot_remove(i); + array_free(debug_vars_list); + array_free(empty_indices); +} diff --git a/src/editor.h b/src/editor.h index 48a0952..7822878 100644 --- a/src/editor.h +++ b/src/editor.h @@ -1,8 +1,20 @@ #ifndef EDITOR_H #define EDITOR_H +#include "linmath.h" + void editor_init(void); void editor_update(float dt); void editor_toggle(void); +void editor_cleanup(void); +int editor_debugvar_slot_create(const char* name, int value_type); +void editor_debugvar_slot_remove(int index); +void editor_debugvar_slot_set_float(int index, float value); +void editor_debugvar_slot_set_int(int index, int value); +void editor_debugvar_slot_set_double(int index, double value); +void editor_debugvar_slot_set_vec2(int index, vec2* value); +void editor_debugvar_slot_set_vec3(int index, vec3* value); +void editor_debugvar_slot_set_vec4(int index, vec4* value); +void editor_debugvar_slot_set_quat(int index, quat* value); #endif diff --git a/src/game.c b/src/game.c index b316aaf..27c6831 100644 --- a/src/game.c +++ b/src/game.c @@ -62,10 +62,10 @@ void game_init(struct Window* window) light_init(); camera_init(); material_init(); + editor_init(); model_init(); entity_init(); scene_init(); - editor_init(); /* Debug scene setup */ scene_setup(); @@ -100,7 +100,7 @@ void scene_setup(void) struct Entity* player = scene_add_new("player", "None"); game_state->player_node = player->node; - vec3 viewer_pos = {10, 4, 100}; + vec3 viewer_pos = {10, 5, 100}; struct Transform* viewer_tran = entity_component_get(player, C_TRANSFORM); /* struct Model* player_model = entity_component_add(player, C_MODEL, "sphere.pamesh", NULL); */ /* model_set_material_param(player_model, "diffuse_color", &color); */ @@ -1573,6 +1573,7 @@ void render(void) void game_cleanup(void) { + editor_cleanup(); scene_cleanup(); entity_cleanup(); model_cleanup(); diff --git a/src/geometry.c b/src/geometry.c index f1579c7..5a44eaf 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -50,9 +50,9 @@ void geom_init(void) geometry_list = array_new(struct Geometry); empty_indices = array_new(int); draw_modes = array_new_cap(GLenum, GDM_NUM_DRAWMODES); - draw_modes[GDM_TRIANGLES] = GL_TRIANGLES; - draw_modes[GDM_LINES] = GL_LINES; - draw_modes[GDM_POINTS] = GL_POINTS; + draw_modes[GDM_TRIANGLES] = GL_TRIANGLES; + draw_modes[GDM_LINES] = GL_LINES; + draw_modes[GDM_POINTS] = GL_POINTS; } int geom_find(const char* filename) @@ -87,7 +87,7 @@ static void generate_bounding_volume(int geometry_index) if(vertex->z < box->min.z) box->min.z = vertex->z; } vec3_add(&sphere->center, &box->max, &box->min); - vec3_scale(&sphere->center, &sphere->center, (1.f / 2.f)); + vec3_scale(&sphere->center, &sphere->center, 0.5f); vec3 len_vec; vec3_sub(&len_vec, &box->max, &sphere->center); sphere->radius = fabs(vec3_len(&len_vec)); @@ -357,17 +357,22 @@ void geom_render(int index, enum Geometry_Draw_Mode draw_mode) } -void geom_render_in_frustum(int index, +int geom_render_in_frustum(int index, vec4* frustum, struct Transform* transform, enum Geometry_Draw_Mode draw_mode) { + int rendered = 0; struct Geometry* geometry = &geometry_list[index]; int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, transform); if(intersection == IT_INTERSECT || intersection == IT_INSIDE) { intersection = bv_intersect_frustum_box(frustum, &geometry->bounding_box, transform); if(intersection == IT_INTERSECT || intersection == IT_INSIDE) + { geom_render(index, draw_mode); + rendered = array_len(geometry->indices); + } } + return rendered; } diff --git a/src/geometry.h b/src/geometry.h index 20b8e79..70a9a4e 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -20,7 +20,7 @@ int geom_find(const char* filename); void geom_remove(int index); void geom_cleanup(void); void geom_render(int index, enum Geometry_Draw_Mode); -void geom_render_in_frustum(int index, +int geom_render_in_frustum(int index, vec4* frustum, struct Transform* transform, enum Geometry_Draw_Mode draw_mode); diff --git a/src/linmath.h b/src/linmath.h index fe2bfc0..432db1d 100644 --- a/src/linmath.h +++ b/src/linmath.h @@ -82,18 +82,18 @@ float vec3_len(vec3* val); float vec3_dot(vec3* v1, vec3* v2); /* vec4 */ -int vec4_equals(vec4* v1, vec4* v2); -void vec4_fill(vec4* res, float x, float y, float z, float w); -void vec4_fill_vec3(vec4* res, const vec3* v, float w); -void vec4_transform_norm(vec4* res, const vec4* val, const mat4* mat); -void vec4_scale(vec4* res, const vec4* val, float s); -void vec4_mul_mat4(vec4* res, vec4* val, mat4* mat); -void vec4_mul(vec4* res, vec4* v1, vec4* v4); -void vec4_norm(vec4* res, vec4* val); +int vec4_equals(vec4* v1, vec4* v2); +void vec4_fill(vec4* res, float x, float y, float z, float w); +void vec4_fill_vec3(vec4* res, const vec3* v, float w); +void vec4_transform_norm(vec4* res, const vec4* val, const mat4* mat); +void vec4_scale(vec4* res, const vec4* val, float s); +void vec4_mul_mat4(vec4* res, vec4* val, mat4* mat); +void vec4_mul(vec4* res, vec4* v1, vec4* v4); +void vec4_norm(vec4* res, vec4* val); float vec4_len(vec4* val); -void vec4_assign(vec4* res, vec4* val); -void vec4_sub(vec4* res, vec4* v1, vec4* v4); -void vec4_add(vec4* res, vec4* v1, vec4* v4); +void vec4_assign(vec4* res, vec4* val); +void vec4_sub(vec4* res, vec4* v1, vec4* v4); +void vec4_add(vec4* res, vec4* v1, vec4* v4); /* mat4 */ void mat4_assign(mat4* res, const mat4* m); diff --git a/src/model.c b/src/model.c index 574e60f..7f793af 100644 --- a/src/model.c +++ b/src/model.c @@ -9,6 +9,8 @@ #include "renderer.h" #include "material.h" #include "light.h" +#include "editor.h" +#include "variant.h" #include "gl_load.h" #include @@ -20,6 +22,8 @@ static struct Model* model_list; static int* empty_indices; +static int num_culled = 0, num_rendered = 0, num_indices = 0; +static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1; struct Model* model_get(int index) { @@ -33,8 +37,11 @@ struct Model* model_get(int index) void model_init(void) { - model_list = array_new(struct Model); - empty_indices = array_new(int); + model_list = array_new(struct Model); + empty_indices = array_new(int); + num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); + num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); + num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); } int model_create(int node, const char* geo_name, const char* material_name) @@ -267,7 +274,16 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) } /* Render the geometry */ - geom_render_in_frustum(model->geometry_index, &camera->frustum[0], transform, draw_mode); + int indices = geom_render_in_frustum(model->geometry_index, &camera->frustum[0], transform, draw_mode); + if(indices > 0) + { + num_rendered++; + num_indices += indices; + } + else + { + num_culled++; + } //geom_render(model->geometry_index, draw_mode); for(int k = 0; k < array_len(model->material_params); k++) @@ -284,6 +300,11 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) } 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); + + num_culled = num_rendered = num_indices = 0; } int model_set_material_param(struct Model* model, const char* name, void* value) diff --git a/src/renderer.c b/src/renderer.c index db69029..6ceb35f 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -41,7 +41,7 @@ void renderer_init(void) settings.fog.start_dist = 50.f; settings.fog.max_dist = 150.f; settings.debug_draw_enabled = 0; - settings.debug_draw_mode = GDM_LINES; + settings.debug_draw_mode = GDM_TRIANGLES; settings.max_gui_vertex_memory = MAX_GUI_VERTEX_MEMORY; settings.max_gui_element_memory = MAX_GUI_ELEMENT_MEMORY; vec3_fill(&settings.fog.color, 60.f/255.f, 60.f/255.f, 75.f/255.f); @@ -177,7 +177,12 @@ void renderer_draw(void) texture_unbind(final_render_tex); shader_unbind(); - if(settings.debug_draw_enabled) model_render_all_debug(active_camera, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color); + if(settings.debug_draw_enabled) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + model_render_all_debug(active_camera, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } gui_render(NK_ANTI_ALIASING_ON, settings.max_gui_vertex_memory, settings.max_gui_element_memory); } diff --git a/src/variant.c b/src/variant.c index 9149e45..eb10976 100644 --- a/src/variant.c +++ b/src/variant.c @@ -8,31 +8,91 @@ void variant_init_empty(struct Variant* variant) variant->val_voidptr = NULL; } -void variant_init_mat4(struct Variant* variant, const mat4* source) +void variant_assign_mat4(struct Variant* variant, const mat4* source) { - if(variant->type == VT_MAT4) + if(variant->type != VT_MAT4) variant_free(variant); + if(!variant->val_voidptr) { + variant->val_voidptr = malloc(sizeof(mat4)); if(!variant->val_voidptr) { - variant->val_voidptr = malloc(sizeof(mat4)); - if(!variant->val_voidptr) - { - log_error("variant_init_mat4", "Out of memory"); - return; - } + log_error("variant_init_mat4", "Out of memory"); + return; } - mat4_assign(variant->val_voidptr, source); } + mat4_assign(variant->val_voidptr, source); +} + +void variant_assign_float(struct Variant* variant, float value) +{ + if(variant->type != VT_FLOAT) variant_free(variant); + variant->type = VT_FLOAT; + variant->val_float = value; +} + +void variant_assign_int(struct Variant* variant, int value) +{ + if(variant->type != VT_INT) variant_free(variant); + variant->type = VT_INT; + variant->val_int = value; +} + +void variant_assign_double(struct Variant* variant, double value) +{ + if(variant->type != VT_DOUBLE) variant_free(variant); + variant->type = VT_DOUBLE; + variant->val_double = value; +} + +void variant_assign_vec2(struct Variant* variant, vec2* value) +{ + if(variant->type != VT_VEC2) variant_free(variant); + variant->type = VT_VEC2; + vec2_assign(&variant->val_vec2, value); +} + +void variant_assign_vec3(struct Variant* variant, vec3* value) +{ + if(variant->type != VT_VEC3) variant_free(variant); + variant->type = VT_VEC3; + vec3_assign(&variant->val_vec3, value); } +void variant_assign_vec4(struct Variant* variant, vec4* value) +{ + if(variant->type != VT_VEC4) variant_free(variant); + variant->type = VT_VEC4; + vec4_assign(&variant->val_vec4, value); +} + +void variant_assign_quat(struct Variant* variant, quat* value) +{ + if(variant->type != VT_QUAT) variant_free(variant); + variant->type = VT_QUAT; + quat_assign(&variant->val_quat, value); +} + + + + void variant_free_mat4(struct Variant* variant) { if(variant->type == VT_MAT4) { - if(variant->val_voidptr) free(variant->val_voidptr); + if(variant->val_voidptr) + { + free(variant->val_voidptr); + variant->val_voidptr = NULL; + } } else { log_error("variant:free_mat4", "Cannot free, variant is not of MAT4 type"); } } + +void variant_free(struct Variant* variant) +{ + if(variant->type == VT_MAT4) + variant_free_mat4(variant); +} diff --git a/src/variant.h b/src/variant.h index 27347fc..4215488 100644 --- a/src/variant.h +++ b/src/variant.h @@ -13,7 +13,6 @@ enum Variant_Type VT_VEC3, VT_VEC4, VT_QUAT, - VT_MAT3, VT_MAT4, VT_VOID_PTR, VT_NUM_TYPES @@ -36,8 +35,14 @@ struct Variant }; void variant_init_empty(struct Variant* variant); -void variant_init_mat4(struct Variant* out_new_variant, const mat4* source); +void variant_assign_mat4(struct Variant* variant, const mat4* source); +void variant_assign_float(struct Variant* variant, float value); +void variant_assign_int(struct Variant* variant, int value); +void variant_assign_double(struct Variant* variant, double value); +void variant_assign_vec2(struct Variant* variant, vec2* value); +void variant_assign_vec3(struct Variant* variant, vec3* value); +void variant_assign_vec4(struct Variant* variant, vec4* value); +void variant_assign_quat(struct Variant* variant, quat* value); void variant_free(struct Variant* variant); - #endif