diff --git a/README.md b/README.md index 7e3eeff..436b1b7 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,11 @@ - ## TODO + - String data-type that is based on array implementation + - Remove all malloc calls/free and move them into custom memory allocator/deallocator functions that only tag/track usage for now + - Rethink/remove the game executable and game library split. + - Remove all previous build system files and implement cross-compilation to windows in current build system or move to a build system that supports it as a first-class citizen + - Refactor all global application state into 'Application_Context' struct. A single global instance of which is available everywhere - Fix mouse button press/release behaviour by investigating how sdl handles mouse release or by explicitly caching mouse state by using event callbacks recieved when a mousebutton release event is reported by sdl - Improve bounding sphere calculation - Screen mouse coordinates to world-coordinates for aiming @@ -164,7 +169,6 @@ - Console command history - Console command help - Space partitioning and scene handling - - NPR and cross-hatching - Move Gui_State and Editor_State into game_state and modify usage as needed - Remove model and replace all usages with static mesh - Get editor camera speed and other settings from config file diff --git a/build/genie.lua b/build/genie.lua index 58ba83a..0b98f4d 100644 --- a/build/genie.lua +++ b/build/genie.lua @@ -68,6 +68,7 @@ solution "Symmetry" configuration "linux" includedirs {"../include/linux/sdl2/", "../include/common/soloud/", "../include/linux/"} libdirs {"../lib/linux/sdl2/", "../lib/linux/soloud/", "../lib/linux/ode/"} + linkoptions {"'-Wl,-rpath,$$ORIGIN'"} links {"SDL2", "m", "ode", "pthread"} configuration {"windows", "vs2017"} @@ -142,4 +143,4 @@ solution "Symmetry" local output = os.outputof("cd ../blender_addon && zip -r io_symmetry_exp.zip io_symmetry_exp/__init__.py io_symmetry_exp/exporter.py && mv io_symmetry_exp.zip ../build"); printf("Output of blender addon build : \n%s\n", output) end - } \ No newline at end of file + } diff --git a/src/common/log.h b/src/common/log.h index 3637eeb..4e9250f 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -2,6 +2,7 @@ #define LOG_H #include +#include typedef void (*Log_Message_CB)(const char* message, va_list args); typedef void (*Log_Warning_CB)(const char* warning_message, va_list args); diff --git a/src/common/parser.c b/src/common/parser.c index 384c312..8f2ffd0 100644 --- a/src/common/parser.c +++ b/src/common/parser.c @@ -17,14 +17,14 @@ bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_fun { if(!file) { - log_error("parser:load", "Invalid file handle for file %s", filename); - return false; + log_error("parser:load", "Invalid file handle for file %s", filename); + return false; } if(!assign_func) { - log_error("parser:load", "No assign function provided to load file %s", filename); - return false; + log_error("parser:load", "No assign function provided to load file %s", filename); + return false; } /* Read line by line, ignore comments */ @@ -39,28 +39,28 @@ bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_fun while(fgets(line_buffer, MAX_LINE_LEN - 1, file)) { - current_line++; - memset(key_str, '\0', HASH_MAX_KEY_LEN); - memset(value_str, '\0', HASH_MAX_KEY_LEN); - - if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) - { - if(return_on_emptyline) - return true; - else - continue; - } + current_line++; + memset(key_str, '\0', HASH_MAX_KEY_LEN); + memset(value_str, '\0', HASH_MAX_KEY_LEN); + + if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) + { + if(return_on_emptyline) + return true; + else + continue; + } - if(line_buffer[0] == '#') - continue; + if(line_buffer[0] == '#') + continue; - if(sscanf(line_buffer, format_str, key_str, value_str) != 2) - { - log_warning("Malformed value in config file %s, line %d", filename, current_line); - continue; - } + if(sscanf(line_buffer, format_str, key_str, value_str) != 2) + { + log_warning("Malformed value in config file %s, line %d", filename, current_line); + continue; + } - assign_func(key_str, value_str, filename, current_line); + assign_func(key_str, value_str, filename, current_line); } return true; } @@ -76,8 +76,8 @@ struct Parser* parser_load_objects(FILE* file, const char* filename) if(!file) { - log_error("parser:load_objects", "Invalid file handle for file %s", filename); - return false; + log_error("parser:load_objects", "Invalid file handle for file %s", filename); + return false; } struct Parser* parser = malloc(sizeof(*parser)); @@ -96,102 +96,102 @@ struct Parser* parser_load_objects(FILE* file, const char* filename) while(fgets(line_buffer, MAX_LINE_LEN - 1, file)) { - current_line++; - memset(type_str, '\0', HASH_MAX_KEY_LEN); + current_line++; + memset(type_str, '\0', HASH_MAX_KEY_LEN); - if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) - { - continue; - } - - if(line_buffer[0] == '#') - continue; - - /* Object type */ - if(sscanf(line_buffer, "%s", type_str) != 1) - { - log_warning("Malformed line in config file %s, line %d", filename, current_line); - continue; - } - - // Check if type string is valid - size_t type_str_len = strnlen(type_str, HASH_MAX_KEY_LEN); - if(type_str_len < 3 || strncmp(type_str, "{", HASH_MAX_KEY_LEN) == 0 || strncmp(type_str, "}", HASH_MAX_KEY_LEN) == 0) - { - log_warning("Invalid object type '%s' on line %d", type_str, current_line); - continue; - } - - long obj_beginning = -1; - long obj_ending = -1; - int obj_begin_expexted_at = current_line; - bool found_next_before_current_ended = false; + if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) + { + continue; + } - /* Opening brace and closing brace */ - char c = ' '; - size_t line_len = strnlen(line_buffer, MAX_LINE_LEN); - size_t seek_amount = line_len - type_str_len; - fseek(file, -seek_amount, SEEK_CUR); - while(!feof(file)) - { - c = fgetc(file); - if(c == '\n') - { - current_line++; - continue; - } + if(line_buffer[0] == '#') + continue; - if(c == '{') - { - obj_beginning = ftell(file); - c = ' '; - while(!feof(file)) + /* Object type */ + if(sscanf(line_buffer, "%s", type_str) != 1) + { + log_warning("Malformed line in config file %s, line %d", filename, current_line); + continue; + } + + // Check if type string is valid + size_t type_str_len = strnlen(type_str, HASH_MAX_KEY_LEN); + if(type_str_len < 3 || strncmp(type_str, "{", HASH_MAX_KEY_LEN) == 0 || strncmp(type_str, "}", HASH_MAX_KEY_LEN) == 0) { - c = fgetc(file); - if(c == '\n') - { - current_line++; + log_warning("Invalid object type '%s' on line %d", type_str, current_line); continue; - } + } + + long obj_beginning = -1; + long obj_ending = -1; + int obj_begin_expexted_at = current_line; + bool found_next_before_current_ended = false; + + /* Opening brace and closing brace */ + char c = ' '; + size_t line_len = strnlen(line_buffer, MAX_LINE_LEN); + size_t seek_amount = line_len - type_str_len; + fseek(file, -seek_amount, SEEK_CUR); + while(!feof(file)) + { + c = fgetc(file); + if(c == '\n') + { + current_line++; + continue; + } + + if(c == '{') + { + obj_beginning = ftell(file); + c = ' '; + while(!feof(file)) + { + c = fgetc(file); + if(c == '\n') + { + current_line++; + continue; + } - /* check if we found opening brace of next object, - if this is true then it means that this object is missing - it's closing brace and we should stop */ - if(c == '{') - { - found_next_before_current_ended = true; - break; - } - - if(c == '}') - { + /* check if we found opening brace of next object, + if this is true then it means that this object is missing + it's closing brace and we should stop */ + if(c == '{') + { + found_next_before_current_ended = true; + break; + } + + if(c == '}') + { obj_ending = ftell(file) - 1; - break; - } + break; + } + } + if(obj_ending != -1) break; + } + } + + if(obj_beginning == -1) + { + log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at); + return false; + } + + if(obj_ending == -1) + { + if(found_next_before_current_ended) + log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line); + else + log_error("parser:load_object", "Syntax error while loading %s, expected '}' at line %d", filename, current_line); + return false; } - if(obj_ending != -1) break; - } - } - - if(obj_beginning == -1) - { - log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at); - return false; - } - - if(obj_ending == -1) - { - if(found_next_before_current_ended) - log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line); - else - log_error("parser:load_object", "Syntax error while loading %s, expected '}' at line %d", filename, current_line); - return false; - } - - memset(obj_str, '\0', 1024); - memset(line_buffer, '\0', MAX_LINE_LEN); - fseek(file, obj_beginning, SEEK_SET); - fread(obj_str, obj_ending - obj_beginning, 1, file); + + memset(obj_str, '\0', 1024); + memset(line_buffer, '\0', MAX_LINE_LEN); + fseek(file, obj_beginning, SEEK_SET); + fread(obj_str, obj_ending - obj_beginning, 1, file); fseek(file, obj_ending + 1, SEEK_SET); // Position cursor after closing brace '}' // Read into intermediate parser object and add it to the objects list @@ -280,16 +280,16 @@ struct Parser* parser_new(void) parser = malloc(sizeof(*parser)); if(!parser) { - log_error("parser:new", "Out of memory"); - return NULL; + log_error("parser:new", "Out of memory"); + return NULL; } parser->objects = array_new(struct Parser_Object); if(!parser->objects) { - log_error("parser:new", "Could not create objects array for parser"); - free(parser); - return NULL; + log_error("parser:new", "Could not create objects array for parser"); + free(parser); + return NULL; } return parser; @@ -301,8 +301,8 @@ struct Parser_Object* parser_object_new(struct Parser* parser, int type) struct Parser_Object* object = array_grow(parser->objects, struct Parser_Object); if(!object) { - log_error("parser:object_new", "Failed to add new parser object"); - return NULL; + log_error("parser:object_new", "Failed to add new parser object"); + return NULL; } object->type = type; object->data = hashmap_new(); @@ -317,25 +317,25 @@ bool parser_write_objects(struct Parser* parser, FILE* file, const char* filenam int counter = 0; for(int i = 0; i < array_len(parser->objects); i++) { - struct Parser_Object* object = &parser->objects[i]; - if(object->type == PO_UNKNOWN) - { - log_warning("Unknown object type, cannot write to %s", filename); - continue; - } - - fprintf(file, "%s\n{\n", parser_object_type_to_str(object->type)); - - char* key = NULL; - struct Variant* value = NULL; - HASHMAP_FOREACH(object->data, key, value) - { - memset(value_str, '\0', MAX_VALUE_LEN); + struct Parser_Object* object = &parser->objects[i]; + if(object->type == PO_UNKNOWN) + { + log_warning("Unknown object type, cannot write to %s", filename); + continue; + } + + fprintf(file, "%s\n{\n", parser_object_type_to_str(object->type)); + + char* key = NULL; + struct Variant* value = NULL; + HASHMAP_FOREACH(object->data, key, value) + { + memset(value_str, '\0', MAX_VALUE_LEN); variant_to_str(value, &value_str[0], MAX_VALUE_LEN); - fprintf(file, "\t%s : %s\n", key, value_str); - } - fprintf(file, "}\n\n"); - counter++; + fprintf(file, "\t%s : %s\n", key, value_str); + } + fprintf(file, "}\n\n"); + counter++; } log_message("%d objects written to %s", counter, filename); diff --git a/src/game/platform.c b/src/game/platform.c index 2a68cef..e21ba55 100644 --- a/src/game/platform.c +++ b/src/game/platform.c @@ -36,15 +36,15 @@ struct Window* window_create(const char* title, int width, int height, int msaa, struct Window* new_window = NULL; if(!new_window) { - new_window = malloc(sizeof(*new_window)); - if(!new_window) - { - log_error("window_create", "Out of memory"); - return NULL; - } - new_window->sdl_window = NULL; - new_window->gl_context = NULL; - new_window->is_fullscreen = 0; + new_window = malloc(sizeof(*new_window)); + if(!new_window) + { + log_error("window_create", "Out of memory"); + return NULL; + } + new_window->sdl_window = NULL; + new_window->gl_context = NULL; + new_window->is_fullscreen = 0; } SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); @@ -54,8 +54,8 @@ struct Window* window_create(const char* title, int width, int height, int msaa, SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if(msaa) { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels); } SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); @@ -67,36 +67,36 @@ struct Window* window_create(const char* title, int width, int height, int msaa, SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); #endif SDL_Window* sdl_window = SDL_CreateWindow(title, - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - width, height, - SDL_WINDOW_OPENGL | - SDL_WINDOW_RESIZABLE | - SDL_WINDOW_INPUT_FOCUS | - SDL_WINDOW_MOUSE_FOCUS); + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + width, height, + SDL_WINDOW_OPENGL | + SDL_WINDOW_RESIZABLE | + SDL_WINDOW_INPUT_FOCUS | + SDL_WINDOW_MOUSE_FOCUS); if(!sdl_window) { - log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError()); - free(new_window); - new_window = NULL; - return new_window; + log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError()); + free(new_window); + new_window = NULL; + return new_window; } new_window->sdl_window = sdl_window; SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window); if(!gl_context) { - log_error("window_create:SDL_GL_CreateContext", "Failed to create GL context : %s", SDL_GetError()); + log_error("window_create:SDL_GL_CreateContext", "Failed to create GL context : %s", SDL_GetError()); window_destroy(new_window); - free(new_window); - new_window = NULL; - return new_window; + free(new_window); + new_window = NULL; + return new_window; } new_window->gl_context = gl_context; SDL_Window* current_window = SDL_GL_GetCurrentWindow(); SDL_GLContext current_context = SDL_GL_GetCurrentContext(); SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context); - SDL_GL_SetSwapInterval(1); /* 0: Vsync disabled, 1: Vsync enabled*/ + SDL_GL_SetSwapInterval(0); /* 0: Vsync disabled, 1: Vsync enabled*/ if(current_window && current_context) SDL_GL_MakeCurrent(current_window, current_context); int major = 0, minor = 0; @@ -112,18 +112,18 @@ int window_fullscreen_set(struct Window* window, int fullscreen) int rc = SDL_SetWindowFullscreen(window->sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); if(rc == 0) { - window->is_fullscreen = fullscreen ? 1 : 0; - success = 1; - log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed"); - int w, h; - window_get_size(window, &w, &h); - log_message("Window size : %dx%d", w, h); - window_get_drawable_size(window, &w, &h); - log_message("Drawable size : %dx%d", w, h); + window->is_fullscreen = fullscreen ? 1 : 0; + success = 1; + log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed"); + int w, h; + window_get_size(window, &w, &h); + log_message("Window size : %dx%d", w, h); + window_get_drawable_size(window, &w, &h); + log_message("Drawable size : %dx%d", w, h); } else { - log_error("platform:window_fullscreen", "window_fullscreen_set failed, %s", SDL_GetError()); + log_error("platform:window_fullscreen", "window_fullscreen_set failed, %s", SDL_GetError()); } return success; } @@ -180,27 +180,27 @@ bool platform_init(void) if(SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) { success = false; - if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0) - log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError()); + if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0) + log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError()); } else { - platform_state = malloc(sizeof(*platform_state)); - if(!platform_state) - { - if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0) - log_to_stdout("platform_init", "Could not create platform state, out of memory"); + platform_state = malloc(sizeof(*platform_state)); + if(!platform_state) + { + if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0) + log_to_stdout("platform_init", "Could not create platform state, out of memory"); success = false; - } - else - { - platform_state->on_keyboard_func = NULL; - platform_state->on_mousebutton_func = NULL; - platform_state->on_mousemotion_func = NULL; - platform_state->on_mousewheel_func = NULL; - platform_state->on_textinput_func = NULL; - platform_state->on_windowresize_func = NULL; - } + } + else + { + platform_state->on_keyboard_func = NULL; + platform_state->on_mousebutton_func = NULL; + platform_state->on_mousemotion_func = NULL; + platform_state->on_mousewheel_func = NULL; + platform_state->on_textinput_func = NULL; + platform_state->on_windowresize_func = NULL; + } } return success; } @@ -245,64 +245,64 @@ void platform_poll_events(bool* out_quit) static SDL_Event event; while(SDL_PollEvent(&event) != 0) { - switch(event.type) - { - case SDL_QUIT: - *out_quit = 1; - break; - case SDL_KEYDOWN: case SDL_KEYUP: - { - int scancode = event.key.keysym.scancode; - int key = event.key.keysym.sym; - int state = event.key.state; - int repeat = event.key.repeat; - int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0; - int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0; - int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0; - platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt); - //log_message("Key name : %s", SDL_GetKeyName(key)); - break; - } - case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - { - int button = event.button.button; - int state = event.button.state; - int num_clicks = event.button.clicks; - int x = event.button.x; - int y = event.button.y; - platform_state->on_mousebutton_func(button, state, x, y, num_clicks); - break; - } - case SDL_MOUSEMOTION: - { - int xrel = event.motion.xrel; - int yrel = event.motion.yrel; - int x = event.motion.x; - int y = event.motion.y; - platform_state->on_mousemotion_func(x, y, xrel, yrel); - break; - } - case SDL_MOUSEWHEEL: - { - int x = event.wheel.x; - int y = event.wheel.y; - platform_state->on_mousewheel_func(x, y); - break; - } - case SDL_TEXTINPUT: - { - platform_state->on_textinput_func(event.text.text); - break; - } - case SDL_WINDOWEVENT: - { - if(event.window.event == SDL_WINDOWEVENT_RESIZED) - { - platform_state->on_windowresize_func(event.window.data1, event.window.data2); - } - } - break; - } + switch(event.type) + { + case SDL_QUIT: + *out_quit = 1; + break; + case SDL_KEYDOWN: case SDL_KEYUP: + { + int scancode = event.key.keysym.scancode; + int key = event.key.keysym.sym; + int state = event.key.state; + int repeat = event.key.repeat; + int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0; + int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0; + int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0; + platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt); + //log_message("Key name : %s", SDL_GetKeyName(key)); + break; + } + case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: + { + int button = event.button.button; + int state = event.button.state; + int num_clicks = event.button.clicks; + int x = event.button.x; + int y = event.button.y; + platform_state->on_mousebutton_func(button, state, x, y, num_clicks); + break; + } + case SDL_MOUSEMOTION: + { + int xrel = event.motion.xrel; + int yrel = event.motion.yrel; + int x = event.motion.x; + int y = event.motion.y; + platform_state->on_mousemotion_func(x, y, xrel, yrel); + break; + } + case SDL_MOUSEWHEEL: + { + int x = event.wheel.x; + int y = event.wheel.y; + platform_state->on_mousewheel_func(x, y); + break; + } + case SDL_TEXTINPUT: + { + platform_state->on_textinput_func(event.text.text); + break; + } + case SDL_WINDOWEVENT: + { + if(event.window.event == SDL_WINDOWEVENT_RESIZED) + { + platform_state->on_windowresize_func(event.window.data1, event.window.data2); + } + } + break; + } } } @@ -392,8 +392,8 @@ char* platform_install_directory_get(void) char* path = NULL; if(returned_path) { - path = str_new(returned_path); - SDL_free(returned_path); + path = str_new(returned_path); + SDL_free(returned_path); } return path; } @@ -409,8 +409,8 @@ char* platform_clipboard_text_get(void) char* text = NULL; if(returned_text) { - text = str_new(returned_text); - SDL_free(returned_text); + text = str_new(returned_text); + SDL_free(returned_text); } return text; } @@ -448,8 +448,8 @@ char* platform_user_directory_get(const char* organization, const char* applicat char* temp_path = SDL_GetPrefPath(organization, application); if(temp_path) { - user_directory = str_new(temp_path); - SDL_free(temp_path); + user_directory = str_new(temp_path); + SDL_free(temp_path); } else { diff --git a/src/game/sound.c b/src/game/sound.c index 41c0009..7cebe34 100644 --- a/src/game/sound.c +++ b/src/game/sound.c @@ -207,7 +207,7 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) } long size = 0L; - char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); + unsigned char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); source = malloc(sizeof(*source)); if(!source) diff --git a/src/libsymmetry/console.c b/src/libsymmetry/console.c index 84b41bd..1edb51e 100644 --- a/src/libsymmetry/console.c +++ b/src/libsymmetry/console.c @@ -55,39 +55,39 @@ void console_update(struct Console* console, struct Gui_State* gui_state, float if(nk_begin_titled(context, "Console", "Console", nk_recti(0, 0, win_width, half_height), NK_WINDOW_SCROLL_AUTO_HIDE)) { - nk_layout_row_dynamic(context, nk_window_get_height(context) - console->text_region_height * 2, 1); - if(nk_group_begin(context, "Log", NK_WINDOW_BORDER)) - { - for(int i = 0; i <= console->current_message_index; i++) - { - nk_layout_row_dynamic(context, console->line_height, 1); - nk_labelf_colored(context, NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, console_message_color[console->console_messages[i].type], console->console_messages[i].message); - } - - if(console->scroll_to_bottom == true) // scroll console message area to the bottom if required - { - *context->current->layout->offset_y = (nk_uint)context->current->layout->at_y; - console->scroll_to_bottom = false; - } + nk_layout_row_dynamic(context, nk_window_get_height(context) - console->text_region_height * 2, 1); + if(nk_group_begin(context, "Log", NK_WINDOW_BORDER)) + { + for(int i = 0; i <= console->current_message_index; i++) + { + nk_layout_row_dynamic(context, console->line_height, 1); + nk_labelf_colored(context, NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, console_message_color[console->console_messages[i].type], console->console_messages[i].message); + } + + if(console->scroll_to_bottom == true) // scroll console message area to the bottom if required + { + *context->current->layout->offset_y = (nk_uint)context->current->layout->at_y; + console->scroll_to_bottom = false; + } - nk_group_end(context); - } - - //Edit-string/Textfield for command - nk_layout_row_dynamic(context, console->text_region_height, 1); - int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER; - nk_edit_focus(context, edit_flags); - int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter); - if(edit_state & NK_EDIT_COMMITED) - { - if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) - console->current_message_index = 0; + nk_group_end(context); + } + + //Edit-string/Textfield for command + nk_layout_row_dynamic(context, console->text_region_height, 1); + int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER; + nk_edit_focus(context, edit_flags); + int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter); + if(edit_state & NK_EDIT_COMMITED) + { + if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) + console->current_message_index = 0; - snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text); - console->console_messages[console->current_message_index].type = CMT_COMMAND; - memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN); - console->scroll_to_bottom = true; - } + snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text); + console->console_messages[console->current_message_index].type = CMT_COMMAND; + memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN); + console->scroll_to_bottom = true; + } } nk_end(context); } @@ -108,28 +108,28 @@ int console_filter(const struct nk_text_edit *box, nk_rune unicode) void console_on_log_message(struct Console* console, const char* message, va_list args) { - if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) - console->current_message_index = 0; - vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, message, args); - console->console_messages[console->current_message_index].type = CMT_MESSAGE; - console->scroll_to_bottom = true; + /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */ + /* console->current_message_index = 0; */ + /* vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, message, args); */ + /* console->console_messages[console->current_message_index].type = CMT_MESSAGE; */ + /* console->scroll_to_bottom = true; */ } void console_on_log_warning(struct Console* console, const char* warning_message, va_list args) { - if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) - console->current_message_index = 0; - vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, warning_message, args); - console->console_messages[console->current_message_index].type = CMT_WARNING; - console->scroll_to_bottom = true; + /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */ + /* console->current_message_index = 0; */ + /* vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, warning_message, args); */ + /* console->console_messages[console->current_message_index].type = CMT_WARNING; */ + /* console->scroll_to_bottom = true; */ } void console_on_log_error(struct Console* console, const char* context, const char* error, va_list args) { - if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) - console->current_message_index = 0; - int loc = snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "(%s)", context); - vsnprintf(console->console_messages[console->current_message_index].message + loc, MAX_CONSOLE_MESSAGE_LEN, error, args); - console->console_messages[console->current_message_index].type = CMT_ERROR; - console->scroll_to_bottom = true; + /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */ + /* console->current_message_index = 0; */ + /* int loc = snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "(%s)", context); */ + /* vsnprintf(console->console_messages[console->current_message_index].message + loc, MAX_CONSOLE_MESSAGE_LEN - loc, error, args); */ + /* console->console_messages[console->current_message_index].type = CMT_ERROR; */ + /* console->scroll_to_bottom = true; */ } diff --git a/src/libsymmetry/console.h b/src/libsymmetry/console.h index a8ae1f2..7799d51 100644 --- a/src/libsymmetry/console.h +++ b/src/libsymmetry/console.h @@ -7,6 +7,8 @@ #define MAX_CONSOLE_MESSAGE_LEN 256 #define MAX_CONSOLE_MESSAGES 1024 +struct Gui_State; + enum Console_Message_Type { CMT_NONE = 0, @@ -43,4 +45,4 @@ void console_on_log_warning(struct Console* console, const char* warning_message void console_on_log_error(struct Console* console, const char* context, const char* error, va_list args); -#endif \ No newline at end of file +#endif diff --git a/src/libsymmetry/editor.c b/src/libsymmetry/editor.c index d03b855..7bbf364 100644 --- a/src/libsymmetry/editor.c +++ b/src/libsymmetry/editor.c @@ -567,77 +567,77 @@ void editor_camera_update(float dt) if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED)) { - const float scale = 0.1f; - int cursor_lr, cursor_ud; - input_mouse_delta_get(&cursor_lr, &cursor_ud); - if(input_mouse_mode_get() != MM_RELATIVE) - { - input_mouse_mode_set(MM_RELATIVE); - cursor_lr = cursor_ud = 0; - } + const float scale = 0.1f; + int cursor_lr, cursor_ud; + input_mouse_delta_get(&cursor_lr, &cursor_ud); + if(input_mouse_mode_get() != MM_RELATIVE) + { + input_mouse_mode_set(MM_RELATIVE); + cursor_lr = cursor_ud = 0; + } - turn_up_down = -cursor_ud * turn_speed * dt * scale; - turn_left_right = cursor_lr * turn_speed * dt * scale; - //log_message("ud : %d, lr : %d", cursor_ud, cursor_lr); + turn_up_down = -cursor_ud * turn_speed * dt * scale; + turn_left_right = cursor_lr * turn_speed * dt * scale; + //log_message("ud : %d, lr : %d", cursor_ud, cursor_lr); } else { - input_mouse_mode_set(MM_NORMAL); - turn_up_down *= dt; - turn_left_right *= dt; - - //Picking - //If we're not looking around then allow picking - if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) - { - log_message("editor picking"); - int mouse_x = 0, mouse_y = 0; - platform->mouse_position_get(&mouse_x, &mouse_y); - struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y); - //log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z); - - struct Scene* scene = game_state_get()->scene; - struct Raycast_Result ray_result; - scene_ray_intersect(scene, &ray, &ray_result); - - if(ray_result.num_entities_intersected > 0) - { - //For now, just select the first entity that is intersected - struct Entity* intersected_entity = ray_result.entities_intersected[0]; - - if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) - { - editor_state.selected_entity->editor_selected = false; - editor_state.selected_entity = NULL; - } - - intersected_entity->editor_selected = true; - editor_state.selected_entity = intersected_entity; - } - } + input_mouse_mode_set(MM_NORMAL); + turn_up_down *= dt; + turn_left_right *= dt; + + //Picking + //If we're not looking around then allow picking + /* if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) */ + /* { */ + /* log_message("editor picking"); */ + /* int mouse_x = 0, mouse_y = 0; */ + /* platform->mouse_position_get(&mouse_x, &mouse_y); */ + /* struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y); */ + /* //log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z); */ + + /* struct Scene* scene = game_state_get()->scene; */ + /* struct Raycast_Result ray_result; */ + /* scene_ray_intersect(scene, &ray, &ray_result); */ + + /* if(ray_result.num_entities_intersected > 0) */ + /* { */ + /* //For now, just select the first entity that is intersected */ + /* struct Entity* intersected_entity = ray_result.entities_intersected[0]; */ + + /* if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) */ + /* { */ + /* editor_state.selected_entity->editor_selected = false; */ + /* editor_state.selected_entity = NULL; */ + /* } */ + + /* intersected_entity->editor_selected = true; */ + /* editor_state.selected_entity = intersected_entity; */ + /* } */ + /* } */ } total_up_down_rot += turn_up_down; if(total_up_down_rot >= max_up_down) { - total_up_down_rot = max_up_down; - turn_up_down = 0.f; + total_up_down_rot = max_up_down; + turn_up_down = 0.f; } else if(total_up_down_rot <= -max_up_down) { - total_up_down_rot = -max_up_down; - turn_up_down = 0.f; + total_up_down_rot = -max_up_down; + turn_up_down = 0.f; } if(turn_left_right != 0.f) { - transform_rotate(editor_camera, &rot_axis_left_right, -turn_left_right, TS_WORLD); + transform_rotate(editor_camera, &rot_axis_left_right, -turn_left_right, TS_WORLD); } if(turn_up_down != 0.f) { - //transform_rotate(editor_camera, &rot_axis_up_down, turn_up_down, TS_LOCAL); - transform_rotate(editor_camera, &rot_axis_up_down, turn_up_down, TS_LOCAL); + //transform_rotate(editor_camera, &rot_axis_up_down, turn_up_down, TS_LOCAL); + transform_rotate(editor_camera, &rot_axis_up_down, turn_up_down, TS_LOCAL); } /* Movement */ @@ -652,8 +652,8 @@ void editor_camera_update(float dt) vec3_scale(&offset, &offset, dt); if(offset.x != 0 || offset.y != 0 || offset.z != 0) { - transform_translate(editor_camera, &offset, TS_LOCAL); - //log_message("Position : %s", tostr_vec3(&transform->position)); + transform_translate(editor_camera, &offset, TS_LOCAL); + //log_message("Position : %s", tostr_vec3(&transform->position)); } } diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index c5904f1..f63f111 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -70,49 +70,49 @@ bool game_init(struct Window* window, struct Platform_Api* platform_api) game_state = malloc(sizeof(*game_state)); if(!game_state) { - log_error("game:init", "Out of memory, failed to allocate game_state"); - return 0; + log_error("game:init", "Out of memory, failed to allocate game_state"); + return 0; } else { - game_state->window = window; - game_state->is_initialized = false; - game_state->game_mode = GAME_MODE_GAME; - game_state->renderer = calloc(1, sizeof(*game_state->renderer)); - game_state->scene = calloc(1, sizeof(*game_state->scene)); - game_state->console = calloc(1, sizeof(*game_state->console)); - - log_file_handle_set(platform->log.file_handle_get()); - log_message_callback_set(game_on_log_message); - log_warning_callback_set(game_on_log_warning); - log_error_callback_set(game_on_log_error); - - 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(); - gui_init(); - console_init(game_state->console); - geom_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); - - editor_init(); - renderer_init(game_state->renderer); - scene_init(game_state->scene); + game_state->window = window; + game_state->is_initialized = false; + game_state->game_mode = GAME_MODE_GAME; + game_state->renderer = calloc(1, sizeof(*game_state->renderer)); + game_state->scene = calloc(1, sizeof(*game_state->scene)); + game_state->console = calloc(1, sizeof(*game_state->console)); + + log_file_handle_set(platform->log.file_handle_get()); + log_message_callback_set(game_on_log_message); + log_warning_callback_set(game_on_log_warning); + log_error_callback_set(game_on_log_error); + + 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(); + gui_init(); + console_init(game_state->console); + geom_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); + + editor_init(); + renderer_init(game_state->renderer); + scene_init(game_state->scene); } /* Debug scene setup */ @@ -297,18 +297,18 @@ void game_scene_setup(void) vec3 suz_pos = {0.f}; for(int i = 0; i < num_suz; i++) { - memset(&suz_name, '\0', MAX_ENTITY_NAME_LEN); - snprintf(&suz_name[0], MAX_ENTITY_NAME_LEN, "Suzanne_%d", i); - struct Static_Mesh* suzanne = scene_static_mesh_create(game_state->scene, suz_name, NULL, "sphere.symbres", MAT_BLINN); - suzanne->model.material_params[MMP_DIFFUSE_TEX].val_int = texture_create_from_file("white.tga", TU_DIFFUSE); - suzanne->model.material_params[MMP_DIFFUSE].val_float = 0.5f; - suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f; - suzanne->model.material_params[MMP_SPECULAR_STRENGTH].val_float = 1.f; - vec3_fill(&suzanne->model.material_params[MMP_DIFFUSE_COL].val_vec3, 1.f, 0.f, 1.f); - suz_pos.x = i + 10.f; - suz_pos.y = 5.f; - suz_pos.z = i + 5.f; - transform_set_position(suzanne, &suz_pos); + memset(&suz_name, '\0', MAX_ENTITY_NAME_LEN); + snprintf(&suz_name[0], MAX_ENTITY_NAME_LEN, "Suzanne_%d", i); + struct Static_Mesh* suzanne = scene_static_mesh_create(game_state->scene, suz_name, NULL, "sphere.symbres", MAT_BLINN); + suzanne->model.material_params[MMP_DIFFUSE_TEX].val_int = texture_create_from_file("white.tga", TU_DIFFUSE); + suzanne->model.material_params[MMP_DIFFUSE].val_float = 0.5f; + suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f; + suzanne->model.material_params[MMP_SPECULAR_STRENGTH].val_float = 1.f; + vec3_fill(&suzanne->model.material_params[MMP_DIFFUSE_COL].val_vec3, 1.f, 0.f, 1.f); + suz_pos.x = i + 10.f; + suz_pos.y = 5.f; + suz_pos.z = i + 5.f; + transform_set_position(suzanne, &suz_pos); } @@ -326,27 +326,27 @@ void game_debug(float dt) { if(input_is_key_pressed(KEY_SPACE)) { - 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); + 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(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}; - transform_translate(model, &amount, TS_LOCAL); + 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}; + transform_translate(model, &amount, TS_LOCAL); } if(input_is_key_pressed(KEY_N)) { - 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}; - transform_translate(model, &amount, TS_LOCAL); + 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}; + transform_translate(model, &amount, TS_LOCAL); } /*struct Entity* model = scene_find("Model_Entity"); @@ -388,22 +388,22 @@ void game_debug(float dt) //Raycast test if(input_is_key_pressed(KEY_R)) { - /*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); - transform_get_absolute_position(player_entity, &position); - struct Raycast_Hit hit; - if(platform->physics.cs_ray_cast(ray, &hit, position.x, position.y, position.z, direction.x, direction.y, direction.z)) - { - struct Entity* entity_hit = entity_get(hit.entity_id); - log_message("Ray hit %s", entity_hit->name); - } - else - { - log_message("Ray didn't hit anything!"); - } - platform->physics.cs_remove(ray);*/ + /*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); + transform_get_absolute_position(player_entity, &position); + struct Raycast_Hit hit; + if(platform->physics.cs_ray_cast(ray, &hit, position.x, position.y, position.z, direction.x, direction.y, direction.z)) + { + struct Entity* entity_hit = entity_get(hit.entity_id); + log_message("Ray hit %s", entity_hit->name); + } + else + { + log_message("Ray didn't hit anything!"); + } + platform->physics.cs_remove(ray);*/ } // Immediate geometry test @@ -483,8 +483,8 @@ void game_debug(float dt) for(int i = 0; i < 10; i++) { - im_position.x += i * 2.f; - im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES); + im_position.x += i * 2.f; + im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES); } } @@ -495,18 +495,18 @@ bool game_run(void) while(!should_window_close) { uint32 curr_time = platform->ticks_get(); - float delta_time = (float)(curr_time - last_time) / 1000.f; - last_time = curr_time; - if(delta_time > MAX_FRAME_TIME) delta_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */ + float delta_time = (float)(curr_time - last_time) / 1000.f; + last_time = curr_time; + if(delta_time > MAX_FRAME_TIME) delta_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */ - gui_input_begin(); + gui_input_begin(); platform->poll_events(&should_window_close); - gui_input_end(); + gui_input_end(); - game_update(delta_time, &should_window_close); - game_post_update(delta_time); - game_render(); - platform->window.swap_buffers(game_state->window); + game_update(delta_time, &should_window_close); + game_post_update(delta_time); + game_render(); + platform->window.swap_buffers(game_state->window); } return true; } @@ -519,24 +519,24 @@ void game_update(float dt, bool* window_should_close) if(input_map_state_get("Console_Toggle", KS_RELEASED)) console_toggle(game_state->console); if(input_map_state_get("Editor_Toggle", KS_RELEASED)) { - //editor_toggle(); - if(game_state->game_mode == GAME_MODE_EDITOR) - { - game_state->game_mode = GAME_MODE_GAME; - game_state->scene->active_camera_index = CAM_GAME; - } - else if(game_state->game_mode == GAME_MODE_GAME) - { - game_state->game_mode = GAME_MODE_EDITOR; - game_state->scene->active_camera_index = CAM_EDITOR; - } + //editor_toggle(); + if(game_state->game_mode == GAME_MODE_EDITOR) + { + game_state->game_mode = GAME_MODE_GAME; + game_state->scene->active_camera_index = CAM_GAME; + } + else if(game_state->game_mode == GAME_MODE_GAME) + { + game_state->game_mode = GAME_MODE_EDITOR; + game_state->scene->active_camera_index = CAM_EDITOR; + } } if(input_map_state_get("Reload_Game_Lib", KS_RELEASED)) { - *window_should_close = true; - platform->reload_game_lib(); - return; + *window_should_close = true; + platform->reload_game_lib(); + return; } //game_debug(dt); @@ -545,11 +545,11 @@ void game_update(float dt, bool* window_should_close) scene_update(game_state->scene, dt); if(game_state->game_mode == GAME_MODE_GAME) { - platform->physics.step(dt); + platform->physics.step(dt); } else if(game_state->game_mode == GAME_MODE_EDITOR) { - editor_update(dt); + editor_update(dt); } } @@ -1001,27 +1001,27 @@ void game_debug_gui(float dt) /* good old week day formula (double because precision) */ {int year_n = (sel_date.tm_mon < 2) ? year-1: year; - int y = year_n % 100; - int c = year_n / 100; - int y4 = (int)((float)y / 4); - int c4 = (int)((float)c / 4); - int m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2); - int week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7; - - /* weekdays */ - nk_layout_row_dynamic(ctx, 35, 7); - for (i = 0; i < (int)LEN(week_days); ++i) - nk_label(ctx, week_days[i], NK_TEXT_CENTERED); - - /* days */ - if (week_day > 0) nk_spacing(ctx, week_day); - for (i = 1; i <= days; ++i) { - sprintf(buffer, "%d", i); - if (nk_button_label(ctx, buffer)) { - sel_date.tm_mday = i; - nk_combo_close(ctx); - } - }} + int y = year_n % 100; + int c = year_n / 100; + int y4 = (int)((float)y / 4); + int c4 = (int)((float)c / 4); + int m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2); + int week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7; + + /* weekdays */ + nk_layout_row_dynamic(ctx, 35, 7); + for (i = 0; i < (int)LEN(week_days); ++i) + nk_label(ctx, week_days[i], NK_TEXT_CENTERED); + + /* days */ + if (week_day > 0) nk_spacing(ctx, week_day); + for (i = 1; i <= days; ++i) { + sprintf(buffer, "%d", i); + if (nk_button_label(ctx, buffer)) { + sel_date.tm_mday = i; + nk_combo_close(ctx); + } + }} nk_combo_end(ctx); } } @@ -1628,7 +1628,7 @@ void game_debug_gui(float dt) bounds = nk_widget_bounds(ctx); nk_spacing(ctx, 1); if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) { a = row_layout[0] + in->mouse.delta.x; @@ -1651,7 +1651,7 @@ void game_debug_gui(float dt) bounds = nk_widget_bounds(ctx); nk_spacing(ctx, 1); if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) { b = (row_layout[2] + in->mouse.delta.x); @@ -1707,7 +1707,7 @@ void game_debug_gui(float dt) bounds = nk_widget_bounds(ctx); nk_spacing(ctx, 1); if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) { a = a + in->mouse.delta.y; @@ -1732,7 +1732,7 @@ void game_debug_gui(float dt) nk_layout_row_dynamic(ctx, 8, 1); bounds = nk_widget_bounds(ctx); if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && + nk_input_is_mouse_prev_hovering_rect(in, bounds)) && nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) { b = b + in->mouse.delta.y; @@ -1773,31 +1773,31 @@ void game_cleanup(void) { if(game_state) { - if(game_state->is_initialized) - { - editor_cleanup(); - scene_destroy(game_state->scene); - input_cleanup(); - renderer_cleanup(game_state->renderer); - gui_cleanup(); - console_destroy(game_state->console); + if(game_state->is_initialized) + { + editor_cleanup(); + scene_destroy(game_state->scene); + input_cleanup(); + renderer_cleanup(game_state->renderer); + gui_cleanup(); + console_destroy(game_state->console); geom_cleanup(); - framebuffer_cleanup(); - texture_cleanup(); - shader_cleanup(); - - free(game_state->console); - free(game_state->scene); - free(game_state->renderer); - } - free(game_state); - game_state = NULL; + framebuffer_cleanup(); + texture_cleanup(); + shader_cleanup(); + + free(game_state->console); + free(game_state->scene); + free(game_state->renderer); + } + free(game_state); + game_state = NULL; } if(platform) { - platform->physics.cleanup(); - free(platform); + platform->physics.cleanup(); + free(platform); } } @@ -1811,9 +1811,9 @@ void on_collision_test(struct Entity* this_ent, struct Entity* other_ent, Rigidb float y = this_ent->transform.position.y; if(y < 10.f) { - //vec3 translation = {0.f, 50.f, 0.f}; - //transform_translate(this_ent, &translation, TS_WORLD); - //platform->physics.body_force_add(body, 0.f, -100.f, 0.f); + //vec3 translation = {0.f, 50.f, 0.f}; + //transform_translate(this_ent, &translation, TS_WORLD); + //platform->physics.body_force_add(body, 0.f, -100.f, 0.f); } //platform->physics.body_force_add(body, 0.f, 500.f, 0.f); } diff --git a/src/libsymmetry/light.h b/src/libsymmetry/light.h index 3e38638..9221e8c 100644 --- a/src/libsymmetry/light.h +++ b/src/libsymmetry/light.h @@ -3,6 +3,8 @@ #define MAX_SHADOWMAPS 4 +struct Light; + void light_init(struct Light* light, int light_type); void light_reset(struct Light* light); diff --git a/src/libsymmetry/model.h b/src/libsymmetry/model.h index dbea8cf..f452472 100644 --- a/src/libsymmetry/model.h +++ b/src/libsymmetry/model.h @@ -2,6 +2,7 @@ #define MODEL_H struct Model; +struct Static_Mesh; void model_init(struct Model* model, struct Static_Mesh* mesh, const char* geometry_name, int material_type); void model_reset(struct Model* model, struct Static_Mesh* mesh); diff --git a/src/libsymmetry/player.c b/src/libsymmetry/player.c index 50aaf96..c98702b 100644 --- a/src/libsymmetry/player.c +++ b/src/libsymmetry/player.c @@ -8,6 +8,7 @@ #include "bounding_volumes.h" #include "../common/hashmap.h" #include "../common/log.h" +#include "entity.h" void player_init(struct Player* player, struct Scene* scene) { diff --git a/src/libsymmetry/player.h b/src/libsymmetry/player.h index daf6068..e51746e 100644 --- a/src/libsymmetry/player.h +++ b/src/libsymmetry/player.h @@ -2,9 +2,10 @@ #define PLAYER_H struct Player; +struct Scene; void player_init(struct Player* player, struct Scene* scene); void player_destroy(struct Player* player); void player_update(struct Player* player, struct Scene* scene, float dt); -#endif \ No newline at end of file +#endif diff --git a/src/libsymmetry/renderer.c b/src/libsymmetry/renderer.c index 9cf1a26..273a7c8 100644 --- a/src/libsymmetry/renderer.c +++ b/src/libsymmetry/renderer.c @@ -87,24 +87,24 @@ void renderer_init(struct Renderer* renderer) struct Game_State* game_state = game_state_get(); platform->window.get_size(game_state->window, &width, &height); renderer->def_albedo_tex = texture_create("def_albedo_texture", - TU_DIFFUSE, - width, height, - GL_RGB, - GL_RGB16F, - GL_FLOAT, - NULL); + 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); + 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); @@ -125,11 +125,11 @@ void renderer_init(struct Renderer* renderer) renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch)); if(!renderer->sprite_batch) { - log_error("renderer:init", "Failed to allocated sprite batch"); + log_error("renderer:init", "Failed to allocated sprite batch"); } else { - sprite_batch_create(renderer->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(); @@ -137,7 +137,7 @@ void renderer_init(struct Renderer* renderer) // Initialize materials for(int i = 0; i < MAT_MAX; i++) { - material_init(&renderer->materials[i], i); + material_init(&renderer->materials[i], i); } } @@ -146,180 +146,181 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene) /* Render each camera output into it's framebuffer or to the default framebuffer */ for(int i = 0; i < MAX_CAMERAS; i++) { - struct Camera* camera = &scene->cameras[i]; - if(!camera->base.active) continue; - - int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; - framebuffer_bind(fbo); - { - glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glClearColor(camera->clear_color.x, - camera->clear_color.y, - camera->clear_color.z, - camera->clear_color.w); - glEnable(GL_CULL_FACE ); - glCullFace(GL_BACK); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - static mat4 mvp; - for(int i = 0; i < MAT_MAX; i++) - { - /* for each material, get all the registered models and render them */ - struct Material* material = &renderer->materials[i]; - GL_CHECK(shader_bind(material->shader)); - - if(material->lit) /* Set light information */ - { - char uniform_name[MAX_UNIFORM_NAME_LEN]; - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - int light_count = -1; - for(int i = 0; i < MAX_LIGHTS; i++) - { - struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */ - if(!light->base.active && light->valid) continue; - light_count++; - - vec3 light_pos = {0, 0, 0}; - transform_get_absolute_position(&light->base, &light_pos); - - if(light->type != LT_POINT) - { - 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->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); - } + struct Camera* camera = &scene->cameras[i]; + if(!camera->base.active) continue; - if(light->type != LT_DIR) + int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; + framebuffer_bind(fbo); + { + glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glClearColor(camera->clear_color.x, + camera->clear_color.y, + camera->clear_color.z, + camera->clear_color.w); + glEnable(GL_CULL_FACE ); + glCullFace(GL_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + static mat4 mvp; + for(int i = 0; i < MAT_MAX; 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", light_count); - shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + /* for each material, get all the registered models and render them */ + struct Material* material = &renderer->materials[i]; + GL_CHECK(shader_bind(material->shader)); + + if(material->lit) /* Set light information */ + { + char uniform_name[MAX_UNIFORM_NAME_LEN]; + memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); + int light_count = -1; + for(int i = 0; i < MAX_LIGHTS; i++) + { + struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */ + if(!light->base.active || !light->valid) continue; + light_count++; + + vec3 light_pos = {0, 0, 0}; + transform_get_absolute_position(&light->base, &light_pos); + + if(light->type != LT_POINT) + { + 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->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); + } + + if(light->type != LT_DIR) + { + 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", 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", 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].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", 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", 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].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", 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", 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].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", 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].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", light_count); - shader_set_uniform_int(material->shader, uniform_name, light->type); - memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); - } - - light_count++; // this variable is going to be used for looping an array so increase its length by one - 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(&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 */ - 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)); + 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); + } + + light_count++; // this variable is going to be sent as a uniform and be used for looping an array so increase its length by one + 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(&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 */ + 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 < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++) - { - if(!material->registered_static_meshes[j]) continue; - - /* for each registered model, set up uniforms and render */ - struct Static_Mesh* mesh = material->registered_static_meshes[j]; - struct Geometry* geometry = geom_get(mesh->model.geometry_index); - - /* Check if model is in frustum */ - 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[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); - if(intersection == IT_OUTSIDE) - { - renderer->num_culled++; - continue; - } - else - { - renderer->num_indices += array_len(geometry->indices); - renderer->num_rendered++; - } - - /* set material params for the model */ - for(int k = 0; k < MMP_MAX; k++) - { - switch(mesh->model.material_params[k].type) - { - case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_int)); break; - case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_float)); break; - case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec3)); break; - case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec4)); break; - } - } - - /* Set pipeline uniforms that are derived per model */ - 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) - { - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); - GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MODEL_MAT].type, material->pipeline_params[MPP_MODEL_MAT].location, &mesh->base.transform.trans_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)); - } + for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++) + { + if(!material->registered_static_meshes[j]) continue; + + /* for each registered model, set up uniforms and render */ + struct Static_Mesh* mesh = material->registered_static_meshes[j]; + struct Geometry* geometry = geom_get(mesh->model.geometry_index); + + /* Check if model is in frustum */ + 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[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); + if(intersection == IT_OUTSIDE) + { + renderer->num_culled++; + continue; + } + else + { + renderer->num_indices += array_len(geometry->indices); + renderer->num_rendered++; + } + + /* set material params for the model */ + for(int k = 0; k < MMP_MAX; k++) + { + switch(mesh->model.material_params[k].type) + { + case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_int)); break; + case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_float)); break; + case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec3)); break; + case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[k].type, material->model_params[k].location, &mesh->model.material_params[k].val_vec4)); break; + } + } + + /* Set pipeline uniforms that are derived per model */ + 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) + { + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat)); + GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MODEL_MAT].type, material->pipeline_params[MPP_MODEL_MAT].location, &mesh->base.transform.trans_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(mesh->model.geometry_index, GDM_TRIANGLES); - - for(int k = 0; k < MMP_MAX; k++) - { - /* unbind textures, if any */ - if(material->model_params[k].type == UT_TEX) - GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int)); - } + /* 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(mesh->model.geometry_index, GDM_TRIANGLES); + + for(int k = 0; k < MMP_MAX; k++) + { + /* unbind textures, if any */ + 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(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); + + renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; } - shader_unbind(); - } - 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); - - renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; - } - framebuffer_unbind(); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); + framebuffer_unbind(); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); } /* Final Render */ @@ -340,71 +341,71 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene) struct Hashmap* cvars = platform->config.get(); if(hashmap_bool_get(cvars, "debug_draw_enabled")) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); - shader_bind(renderer->debug_shader); - { - static mat4 mvp; - shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color); - for(int i = 0; i < MAX_STATIC_MESHES; i++) - { - 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_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")); - } - } - shader_unbind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); + shader_bind(renderer->debug_shader); + { + static mat4 mvp; + shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color); + for(int i = 0; i < MAX_STATIC_MESHES; i++) + { + 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_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")); + } + } + shader_unbind(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // Debug Physics render if(hashmap_bool_get(cvars, "debug_draw_physics")) { - static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; - for(int i = 0; i < MAX_STATIC_MESHES; 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(mesh->collision.rigidbody) - { - 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(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(mesh->collision.collision_shape); - switch(collision_shape_type) - { - case CST_SPHERE: - { - 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(mesh->collision.collision_shape, &x, &y, &z); - im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); - }; - break; - default: break; - } - } + static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; + for(int i = 0; i < MAX_STATIC_MESHES; 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(mesh->collision.rigidbody) + { + 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(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(mesh->collision.collision_shape); + switch(collision_shape_type) + { + case CST_SPHERE: + { + 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(mesh->collision.collision_shape, &x, &y, &z); + im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); + }; + break; + default: break; + } + } } //Immediate mode geometry render @@ -414,16 +415,16 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene) /* Render 2D stuff */ shader_bind(renderer->sprite_batch->shader); { - static mat4 ortho_mat; - mat4_identity(&ortho_mat); - int width, height; - struct Game_State* game_state = game_state_get(); - platform->window.get_size(game_state->window, &width, &height); + static mat4 ortho_mat; + mat4_identity(&ortho_mat); + int width, height; + struct Game_State* game_state = game_state_get(); + 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(renderer->sprite_batch->shader, "mvp", &ortho_mat); + mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f); + shader_set_uniform_mat4(renderer->sprite_batch->shader, "mvp", &ortho_mat); - sprite_batch_render(renderer->sprite_batch); + sprite_batch_render(renderer->sprite_batch); } shader_unbind(); @@ -435,7 +436,7 @@ void renderer_cleanup(struct Renderer* renderer) { for(int i = 0; i < MAT_MAX; i++) { - material_reset(&renderer->materials[i]); + material_reset(&renderer->materials[i]); } im_cleanup(); sprite_batch_remove(renderer->sprite_batch); @@ -452,9 +453,9 @@ void on_framebuffer_size_change(int width, int height) float aspect = (float)width / (float)height; for(int i = 0; i < MAX_CAMERAS; i++) { - struct Camera* viewer = &scene->cameras[i]; - viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; - camera_update_proj(viewer); + struct Camera* viewer = &scene->cameras[i]; + viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; + camera_update_proj(viewer); } framebuffer_resize_all(width, height); diff --git a/src/libsymmetry/renderer.h b/src/libsymmetry/renderer.h index e6f8232..8fbdd11 100644 --- a/src/libsymmetry/renderer.h +++ b/src/libsymmetry/renderer.h @@ -6,6 +6,7 @@ #include "material.h" struct Sprite_Batch; +struct Scene; enum Fog_Mode { diff --git a/src/libsymmetry/scene.h b/src/libsymmetry/scene.h index 5589237..9dd4abe 100644 --- a/src/libsymmetry/scene.h +++ b/src/libsymmetry/scene.h @@ -10,8 +10,8 @@ #define MAX_STATIC_MESHES 1024 #define MAX_SOUND_SOURCES 128 - struct Ray; +struct Raycast_Result; struct Scene { diff --git a/tools/genie b/tools/genie old mode 100644 new mode 100755