Fixed a bug with rendering and added rpath in linux build

dev
Shariq Shah 7 years ago
parent c651847d43
commit e47b494d80
  1. 6
      README.md
  2. 1
      build/genie.lua
  3. 1
      src/common/log.h
  4. 286
      src/common/parser.c
  5. 232
      src/game/platform.c
  6. 2
      src/game/sound.c
  7. 98
      src/libsymmetry/console.c
  8. 2
      src/libsymmetry/console.h
  9. 106
      src/libsymmetry/editor.c
  10. 312
      src/libsymmetry/game.c
  11. 2
      src/libsymmetry/light.h
  12. 1
      src/libsymmetry/model.h
  13. 1
      src/libsymmetry/player.c
  14. 1
      src/libsymmetry/player.h
  15. 513
      src/libsymmetry/renderer.c
  16. 1
      src/libsymmetry/renderer.h
  17. 2
      src/libsymmetry/scene.h
  18. 0
      tools/genie

@ -155,6 +155,11 @@
- ## TODO - ## 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 - 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 - Improve bounding sphere calculation
- Screen mouse coordinates to world-coordinates for aiming - Screen mouse coordinates to world-coordinates for aiming
@ -164,7 +169,6 @@
- Console command history - Console command history
- Console command help - Console command help
- Space partitioning and scene handling - Space partitioning and scene handling
- NPR and cross-hatching
- Move Gui_State and Editor_State into game_state and modify usage as needed - Move Gui_State and Editor_State into game_state and modify usage as needed
- Remove model and replace all usages with static mesh - Remove model and replace all usages with static mesh
- Get editor camera speed and other settings from config file - Get editor camera speed and other settings from config file

@ -68,6 +68,7 @@ solution "Symmetry"
configuration "linux" configuration "linux"
includedirs {"../include/linux/sdl2/", "../include/common/soloud/", "../include/linux/"} includedirs {"../include/linux/sdl2/", "../include/common/soloud/", "../include/linux/"}
libdirs {"../lib/linux/sdl2/", "../lib/linux/soloud/", "../lib/linux/ode/"} libdirs {"../lib/linux/sdl2/", "../lib/linux/soloud/", "../lib/linux/ode/"}
linkoptions {"'-Wl,-rpath,$$ORIGIN'"}
links {"SDL2", "m", "ode", "pthread"} links {"SDL2", "m", "ode", "pthread"}
configuration {"windows", "vs2017"} configuration {"windows", "vs2017"}

@ -2,6 +2,7 @@
#define LOG_H #define LOG_H
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
typedef void (*Log_Message_CB)(const char* message, va_list args); typedef void (*Log_Message_CB)(const char* message, va_list args);
typedef void (*Log_Warning_CB)(const char* warning_message, va_list args); typedef void (*Log_Warning_CB)(const char* warning_message, va_list args);

@ -17,14 +17,14 @@ bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_fun
{ {
if(!file) if(!file)
{ {
log_error("parser:load", "Invalid file handle for file %s", filename); log_error("parser:load", "Invalid file handle for file %s", filename);
return false; return false;
} }
if(!assign_func) if(!assign_func)
{ {
log_error("parser:load", "No assign function provided to load file %s", filename); log_error("parser:load", "No assign function provided to load file %s", filename);
return false; return false;
} }
/* Read line by line, ignore comments */ /* 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)) while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{ {
current_line++; current_line++;
memset(key_str, '\0', HASH_MAX_KEY_LEN); memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(value_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(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{ {
if(return_on_emptyline) if(return_on_emptyline)
return true; return true;
else else
continue; continue;
} }
if(line_buffer[0] == '#') if(line_buffer[0] == '#')
continue; continue;
if(sscanf(line_buffer, format_str, key_str, value_str) != 2) if(sscanf(line_buffer, format_str, key_str, value_str) != 2)
{ {
log_warning("Malformed value in config file %s, line %d", filename, current_line); log_warning("Malformed value in config file %s, line %d", filename, current_line);
continue; continue;
} }
assign_func(key_str, value_str, filename, current_line); assign_func(key_str, value_str, filename, current_line);
} }
return true; return true;
} }
@ -76,8 +76,8 @@ struct Parser* parser_load_objects(FILE* file, const char* filename)
if(!file) if(!file)
{ {
log_error("parser:load_objects", "Invalid file handle for file %s", filename); log_error("parser:load_objects", "Invalid file handle for file %s", filename);
return false; return false;
} }
struct Parser* parser = malloc(sizeof(*parser)); 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)) while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{ {
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;
/* 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++; current_line++;
continue; memset(type_str, '\0', HASH_MAX_KEY_LEN);
}
if(c == '{') if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{
obj_beginning = ftell(file);
c = ' ';
while(!feof(file))
{ {
c = fgetc(file);
if(c == '\n')
{
current_line++;
continue; continue;
} }
/* check if we found opening brace of next object, if(line_buffer[0] == '#')
if this is true then it means that this object is missing continue;
it's closing brace and we should stop */
if(c == '{') /* Object type */
{ if(sscanf(line_buffer, "%s", type_str) != 1)
found_next_before_current_ended = true; {
break; log_warning("Malformed line in config file %s, line %d", filename, current_line);
} continue;
}
if(c == '}')
{ // 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;
/* 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 == '}')
{
obj_ending = ftell(file) - 1; obj_ending = ftell(file) - 1;
break; break;
} }
}
if(obj_ending != -1) 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);
if(obj_beginning == -1) return false;
{ }
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)
if(obj_ending == -1) log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line);
{ else
if(found_next_before_current_ended) log_error("parser:load_object", "Syntax error while loading %s, expected '}' at line %d", filename, current_line);
log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line); return false;
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);
memset(obj_str, '\0', 1024); fread(obj_str, obj_ending - obj_beginning, 1, file);
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 '}' fseek(file, obj_ending + 1, SEEK_SET); // Position cursor after closing brace '}'
// Read into intermediate parser object and add it to the objects list // 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)); parser = malloc(sizeof(*parser));
if(!parser) if(!parser)
{ {
log_error("parser:new", "Out of memory"); log_error("parser:new", "Out of memory");
return NULL; return NULL;
} }
parser->objects = array_new(struct Parser_Object); parser->objects = array_new(struct Parser_Object);
if(!parser->objects) if(!parser->objects)
{ {
log_error("parser:new", "Could not create objects array for parser"); log_error("parser:new", "Could not create objects array for parser");
free(parser); free(parser);
return NULL; return NULL;
} }
return parser; 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); struct Parser_Object* object = array_grow(parser->objects, struct Parser_Object);
if(!object) if(!object)
{ {
log_error("parser:object_new", "Failed to add new parser object"); log_error("parser:object_new", "Failed to add new parser object");
return NULL; return NULL;
} }
object->type = type; object->type = type;
object->data = hashmap_new(); object->data = hashmap_new();
@ -317,25 +317,25 @@ bool parser_write_objects(struct Parser* parser, FILE* file, const char* filenam
int counter = 0; int counter = 0;
for(int i = 0; i < array_len(parser->objects); i++) for(int i = 0; i < array_len(parser->objects); i++)
{ {
struct Parser_Object* object = &parser->objects[i]; struct Parser_Object* object = &parser->objects[i];
if(object->type == PO_UNKNOWN) if(object->type == PO_UNKNOWN)
{ {
log_warning("Unknown object type, cannot write to %s", filename); log_warning("Unknown object type, cannot write to %s", filename);
continue; continue;
} }
fprintf(file, "%s\n{\n", parser_object_type_to_str(object->type)); fprintf(file, "%s\n{\n", parser_object_type_to_str(object->type));
char* key = NULL; char* key = NULL;
struct Variant* value = NULL; struct Variant* value = NULL;
HASHMAP_FOREACH(object->data, key, value) HASHMAP_FOREACH(object->data, key, value)
{ {
memset(value_str, '\0', MAX_VALUE_LEN); memset(value_str, '\0', MAX_VALUE_LEN);
variant_to_str(value, &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, "\t%s : %s\n", key, value_str);
} }
fprintf(file, "}\n\n"); fprintf(file, "}\n\n");
counter++; counter++;
} }
log_message("%d objects written to %s", counter, filename); log_message("%d objects written to %s", counter, filename);

@ -36,15 +36,15 @@ struct Window* window_create(const char* title, int width, int height, int msaa,
struct Window* new_window = NULL; struct Window* new_window = NULL;
if(!new_window) if(!new_window)
{ {
new_window = malloc(sizeof(*new_window)); new_window = malloc(sizeof(*new_window));
if(!new_window) if(!new_window)
{ {
log_error("window_create", "Out of memory"); log_error("window_create", "Out of memory");
return NULL; return NULL;
} }
new_window->sdl_window = NULL; new_window->sdl_window = NULL;
new_window->gl_context = NULL; new_window->gl_context = NULL;
new_window->is_fullscreen = 0; new_window->is_fullscreen = 0;
} }
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 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); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if(msaa) if(msaa)
{ {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels);
} }
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 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); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif #endif
SDL_Window* sdl_window = SDL_CreateWindow(title, SDL_Window* sdl_window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height, width, height,
SDL_WINDOW_OPENGL | SDL_WINDOW_OPENGL |
SDL_WINDOW_RESIZABLE | SDL_WINDOW_RESIZABLE |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_INPUT_FOCUS |
SDL_WINDOW_MOUSE_FOCUS); SDL_WINDOW_MOUSE_FOCUS);
if(!sdl_window) if(!sdl_window)
{ {
log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError()); log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError());
free(new_window); free(new_window);
new_window = NULL; new_window = NULL;
return new_window; return new_window;
} }
new_window->sdl_window = sdl_window; new_window->sdl_window = sdl_window;
SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window); SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window);
if(!gl_context) 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); window_destroy(new_window);
free(new_window); free(new_window);
new_window = NULL; new_window = NULL;
return new_window; return new_window;
} }
new_window->gl_context = gl_context; new_window->gl_context = gl_context;
SDL_Window* current_window = SDL_GL_GetCurrentWindow(); SDL_Window* current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext current_context = SDL_GL_GetCurrentContext(); SDL_GLContext current_context = SDL_GL_GetCurrentContext();
SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context); 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); if(current_window && current_context) SDL_GL_MakeCurrent(current_window, current_context);
int major = 0, minor = 0; 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); int rc = SDL_SetWindowFullscreen(window->sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if(rc == 0) if(rc == 0)
{ {
window->is_fullscreen = fullscreen ? 1 : 0; window->is_fullscreen = fullscreen ? 1 : 0;
success = 1; success = 1;
log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed"); log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed");
int w, h; int w, h;
window_get_size(window, &w, &h); window_get_size(window, &w, &h);
log_message("Window size : %dx%d", w, h); log_message("Window size : %dx%d", w, h);
window_get_drawable_size(window, &w, &h); window_get_drawable_size(window, &w, &h);
log_message("Drawable size : %dx%d", w, h); log_message("Drawable size : %dx%d", w, h);
} }
else 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; return success;
} }
@ -180,27 +180,27 @@ bool platform_init(void)
if(SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) if(SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0)
{ {
success = false; success = false;
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0) if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0)
log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError()); log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError());
} }
else else
{ {
platform_state = malloc(sizeof(*platform_state)); platform_state = malloc(sizeof(*platform_state));
if(!platform_state) if(!platform_state)
{ {
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0) 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"); log_to_stdout("platform_init", "Could not create platform state, out of memory");
success = false; success = false;
} }
else else
{ {
platform_state->on_keyboard_func = NULL; platform_state->on_keyboard_func = NULL;
platform_state->on_mousebutton_func = NULL; platform_state->on_mousebutton_func = NULL;
platform_state->on_mousemotion_func = NULL; platform_state->on_mousemotion_func = NULL;
platform_state->on_mousewheel_func = NULL; platform_state->on_mousewheel_func = NULL;
platform_state->on_textinput_func = NULL; platform_state->on_textinput_func = NULL;
platform_state->on_windowresize_func = NULL; platform_state->on_windowresize_func = NULL;
} }
} }
return success; return success;
} }
@ -245,64 +245,64 @@ void platform_poll_events(bool* out_quit)
static SDL_Event event; static SDL_Event event;
while(SDL_PollEvent(&event) != 0) while(SDL_PollEvent(&event) != 0)
{ {
switch(event.type) switch(event.type)
{ {
case SDL_QUIT: case SDL_QUIT:
*out_quit = 1; *out_quit = 1;
break; break;
case SDL_KEYDOWN: case SDL_KEYUP: case SDL_KEYDOWN: case SDL_KEYUP:
{ {
int scancode = event.key.keysym.scancode; int scancode = event.key.keysym.scancode;
int key = event.key.keysym.sym; int key = event.key.keysym.sym;
int state = event.key.state; int state = event.key.state;
int repeat = event.key.repeat; int repeat = event.key.repeat;
int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0; int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0;
int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0; int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0;
int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 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); platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt);
//log_message("Key name : %s", SDL_GetKeyName(key)); //log_message("Key name : %s", SDL_GetKeyName(key));
break; break;
} }
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
{ {
int button = event.button.button; int button = event.button.button;
int state = event.button.state; int state = event.button.state;
int num_clicks = event.button.clicks; int num_clicks = event.button.clicks;
int x = event.button.x; int x = event.button.x;
int y = event.button.y; int y = event.button.y;
platform_state->on_mousebutton_func(button, state, x, y, num_clicks); platform_state->on_mousebutton_func(button, state, x, y, num_clicks);
break; break;
} }
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
{ {
int xrel = event.motion.xrel; int xrel = event.motion.xrel;
int yrel = event.motion.yrel; int yrel = event.motion.yrel;
int x = event.motion.x; int x = event.motion.x;
int y = event.motion.y; int y = event.motion.y;
platform_state->on_mousemotion_func(x, y, xrel, yrel); platform_state->on_mousemotion_func(x, y, xrel, yrel);
break; break;
} }
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
int x = event.wheel.x; int x = event.wheel.x;
int y = event.wheel.y; int y = event.wheel.y;
platform_state->on_mousewheel_func(x, y); platform_state->on_mousewheel_func(x, y);
break; break;
} }
case SDL_TEXTINPUT: case SDL_TEXTINPUT:
{ {
platform_state->on_textinput_func(event.text.text); platform_state->on_textinput_func(event.text.text);
break; break;
} }
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
if(event.window.event == SDL_WINDOWEVENT_RESIZED) if(event.window.event == SDL_WINDOWEVENT_RESIZED)
{ {
platform_state->on_windowresize_func(event.window.data1, event.window.data2); platform_state->on_windowresize_func(event.window.data1, event.window.data2);
} }
} }
break; break;
} }
} }
} }
@ -392,8 +392,8 @@ char* platform_install_directory_get(void)
char* path = NULL; char* path = NULL;
if(returned_path) if(returned_path)
{ {
path = str_new(returned_path); path = str_new(returned_path);
SDL_free(returned_path); SDL_free(returned_path);
} }
return path; return path;
} }
@ -409,8 +409,8 @@ char* platform_clipboard_text_get(void)
char* text = NULL; char* text = NULL;
if(returned_text) if(returned_text)
{ {
text = str_new(returned_text); text = str_new(returned_text);
SDL_free(returned_text); SDL_free(returned_text);
} }
return 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); char* temp_path = SDL_GetPrefPath(organization, application);
if(temp_path) if(temp_path)
{ {
user_directory = str_new(temp_path); user_directory = str_new(temp_path);
SDL_free(temp_path); SDL_free(temp_path);
} }
else else
{ {

@ -207,7 +207,7 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type)
} }
long size = 0L; 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)); source = malloc(sizeof(*source));
if(!source) if(!source)

@ -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)) 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); 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)) if(nk_group_begin(context, "Log", NK_WINDOW_BORDER))
{ {
for(int i = 0; i <= console->current_message_index; i++) for(int i = 0; i <= console->current_message_index; i++)
{ {
nk_layout_row_dynamic(context, console->line_height, 1); 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); 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 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; *context->current->layout->offset_y = (nk_uint)context->current->layout->at_y;
console->scroll_to_bottom = false; console->scroll_to_bottom = false;
} }
nk_group_end(context); nk_group_end(context);
} }
//Edit-string/Textfield for command //Edit-string/Textfield for command
nk_layout_row_dynamic(context, console->text_region_height, 1); 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; int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER;
nk_edit_focus(context, edit_flags); 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); 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(edit_state & NK_EDIT_COMMITED)
{ {
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0; console->current_message_index = 0;
snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text); 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; console->console_messages[console->current_message_index].type = CMT_COMMAND;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN); memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->scroll_to_bottom = true; console->scroll_to_bottom = true;
} }
} }
nk_end(context); 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) void console_on_log_message(struct Console* console, const char* message, va_list args)
{ {
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */
console->current_message_index = 0; /* console->current_message_index = 0; */
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, message, args); /* 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->console_messages[console->current_message_index].type = CMT_MESSAGE; */
console->scroll_to_bottom = true; /* console->scroll_to_bottom = true; */
} }
void console_on_log_warning(struct Console* console, const char* warning_message, va_list args) void console_on_log_warning(struct Console* console, const char* warning_message, va_list args)
{ {
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */
console->current_message_index = 0; /* console->current_message_index = 0; */
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, warning_message, args); /* 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->console_messages[console->current_message_index].type = CMT_WARNING; */
console->scroll_to_bottom = true; /* console->scroll_to_bottom = true; */
} }
void console_on_log_error(struct Console* console, const char* context, const char* error, va_list args) 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) /* if(++console->current_message_index >= MAX_CONSOLE_MESSAGES) */
console->current_message_index = 0; /* console->current_message_index = 0; */
int loc = snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "(%s)", context); /* 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); /* 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->console_messages[console->current_message_index].type = CMT_ERROR; */
console->scroll_to_bottom = true; /* console->scroll_to_bottom = true; */
} }

@ -7,6 +7,8 @@
#define MAX_CONSOLE_MESSAGE_LEN 256 #define MAX_CONSOLE_MESSAGE_LEN 256
#define MAX_CONSOLE_MESSAGES 1024 #define MAX_CONSOLE_MESSAGES 1024
struct Gui_State;
enum Console_Message_Type enum Console_Message_Type
{ {
CMT_NONE = 0, CMT_NONE = 0,

@ -567,77 +567,77 @@ void editor_camera_update(float dt)
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED)) if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED))
{ {
const float scale = 0.1f; const float scale = 0.1f;
int cursor_lr, cursor_ud; int cursor_lr, cursor_ud;
input_mouse_delta_get(&cursor_lr, &cursor_ud); input_mouse_delta_get(&cursor_lr, &cursor_ud);
if(input_mouse_mode_get() != MM_RELATIVE) if(input_mouse_mode_get() != MM_RELATIVE)
{ {
input_mouse_mode_set(MM_RELATIVE); input_mouse_mode_set(MM_RELATIVE);
cursor_lr = cursor_ud = 0; cursor_lr = cursor_ud = 0;
} }
turn_up_down = -cursor_ud * turn_speed * dt * scale; turn_up_down = -cursor_ud * turn_speed * dt * scale;
turn_left_right = cursor_lr * turn_speed * dt * scale; turn_left_right = cursor_lr * turn_speed * dt * scale;
//log_message("ud : %d, lr : %d", cursor_ud, cursor_lr); //log_message("ud : %d, lr : %d", cursor_ud, cursor_lr);
} }
else else
{ {
input_mouse_mode_set(MM_NORMAL); input_mouse_mode_set(MM_NORMAL);
turn_up_down *= dt; turn_up_down *= dt;
turn_left_right *= dt; turn_left_right *= dt;
//Picking //Picking
//If we're not looking around then allow picking //If we're not looking around then allow picking
if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) /* if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) */
{ /* { */
log_message("editor picking"); /* log_message("editor picking"); */
int mouse_x = 0, mouse_y = 0; /* int mouse_x = 0, mouse_y = 0; */
platform->mouse_position_get(&mouse_x, &mouse_y); /* platform->mouse_position_get(&mouse_x, &mouse_y); */
struct Ray ray = camera_screen_coord_to_ray(editor_camera, 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); /* //log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z); */
struct Scene* scene = game_state_get()->scene; /* struct Scene* scene = game_state_get()->scene; */
struct Raycast_Result ray_result; /* struct Raycast_Result ray_result; */
scene_ray_intersect(scene, &ray, &ray_result); /* scene_ray_intersect(scene, &ray, &ray_result); */
if(ray_result.num_entities_intersected > 0) /* if(ray_result.num_entities_intersected > 0) */
{ /* { */
//For now, just select the first entity that is intersected /* //For now, just select the first entity that is intersected */
struct Entity* intersected_entity = ray_result.entities_intersected[0]; /* struct Entity* intersected_entity = ray_result.entities_intersected[0]; */
if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) /* if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) */
{ /* { */
editor_state.selected_entity->editor_selected = false; /* editor_state.selected_entity->editor_selected = false; */
editor_state.selected_entity = NULL; /* editor_state.selected_entity = NULL; */
} /* } */
intersected_entity->editor_selected = true; /* intersected_entity->editor_selected = true; */
editor_state.selected_entity = intersected_entity; /* editor_state.selected_entity = intersected_entity; */
} /* } */
} /* } */
} }
total_up_down_rot += turn_up_down; total_up_down_rot += turn_up_down;
if(total_up_down_rot >= max_up_down) if(total_up_down_rot >= max_up_down)
{ {
total_up_down_rot = max_up_down; total_up_down_rot = max_up_down;
turn_up_down = 0.f; turn_up_down = 0.f;
} }
else if(total_up_down_rot <= -max_up_down) else if(total_up_down_rot <= -max_up_down)
{ {
total_up_down_rot = -max_up_down; total_up_down_rot = -max_up_down;
turn_up_down = 0.f; turn_up_down = 0.f;
} }
if(turn_left_right != 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) 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 */ /* Movement */
@ -652,8 +652,8 @@ void editor_camera_update(float dt)
vec3_scale(&offset, &offset, dt); vec3_scale(&offset, &offset, dt);
if(offset.x != 0 || offset.y != 0 || offset.z != 0) if(offset.x != 0 || offset.y != 0 || offset.z != 0)
{ {
transform_translate(editor_camera, &offset, TS_LOCAL); transform_translate(editor_camera, &offset, TS_LOCAL);
//log_message("Position : %s", tostr_vec3(&transform->position)); //log_message("Position : %s", tostr_vec3(&transform->position));
} }
} }

@ -70,49 +70,49 @@ bool game_init(struct Window* window, struct Platform_Api* platform_api)
game_state = malloc(sizeof(*game_state)); game_state = malloc(sizeof(*game_state));
if(!game_state) if(!game_state)
{ {
log_error("game:init", "Out of memory, failed to allocate game_state"); log_error("game:init", "Out of memory, failed to allocate game_state");
return 0; return 0;
} }
else else
{ {
game_state->window = window; game_state->window = window;
game_state->is_initialized = false; game_state->is_initialized = false;
game_state->game_mode = GAME_MODE_GAME; game_state->game_mode = GAME_MODE_GAME;
game_state->renderer = calloc(1, sizeof(*game_state->renderer)); game_state->renderer = calloc(1, sizeof(*game_state->renderer));
game_state->scene = calloc(1, sizeof(*game_state->scene)); game_state->scene = calloc(1, sizeof(*game_state->scene));
game_state->console = calloc(1, sizeof(*game_state->console)); game_state->console = calloc(1, sizeof(*game_state->console));
log_file_handle_set(platform->log.file_handle_get()); log_file_handle_set(platform->log.file_handle_get());
log_message_callback_set(game_on_log_message); log_message_callback_set(game_on_log_message);
log_warning_callback_set(game_on_log_warning); log_warning_callback_set(game_on_log_warning);
log_error_callback_set(game_on_log_error); log_error_callback_set(game_on_log_error);
if(!gl_load_extentions()) if(!gl_load_extentions())
{ {
log_error("game:init", "Failed to load GL extentions"); log_error("game:init", "Failed to load GL extentions");
return false; return false;
} }
else else
{ {
log_message("Loaded GL extentions"); log_message("Loaded GL extentions");
} }
input_init(); input_init();
shader_init(); shader_init();
texture_init(); texture_init();
framebuffer_init(); framebuffer_init();
gui_init(); gui_init();
console_init(game_state->console); console_init(game_state->console);
geom_init(); geom_init();
platform->physics.init(); platform->physics.init();
platform->physics.gravity_set(0.f, -9.8f, 0.f); platform->physics.gravity_set(0.f, -9.8f, 0.f);
platform->physics.body_set_moved_callback(entity_rigidbody_on_move); platform->physics.body_set_moved_callback(entity_rigidbody_on_move);
platform->physics.body_set_collision_callback(entity_rigidbody_on_collision); platform->physics.body_set_collision_callback(entity_rigidbody_on_collision);
editor_init(); editor_init();
renderer_init(game_state->renderer); renderer_init(game_state->renderer);
scene_init(game_state->scene); scene_init(game_state->scene);
} }
/* Debug scene setup */ /* Debug scene setup */
@ -297,18 +297,18 @@ void game_scene_setup(void)
vec3 suz_pos = {0.f}; vec3 suz_pos = {0.f};
for(int i = 0; i < num_suz; i++) for(int i = 0; i < num_suz; i++)
{ {
memset(&suz_name, '\0', MAX_ENTITY_NAME_LEN); memset(&suz_name, '\0', MAX_ENTITY_NAME_LEN);
snprintf(&suz_name[0], MAX_ENTITY_NAME_LEN, "Suzanne_%d", i); 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); 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_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_DIFFUSE].val_float = 0.5f;
suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f; suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f;
suzanne->model.material_params[MMP_SPECULAR_STRENGTH].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); 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.x = i + 10.f;
suz_pos.y = 5.f; suz_pos.y = 5.f;
suz_pos.z = i + 5.f; suz_pos.z = i + 5.f;
transform_set_position(suzanne, &suz_pos); transform_set_position(suzanne, &suz_pos);
} }
@ -326,27 +326,27 @@ void game_debug(float dt)
{ {
if(input_is_key_pressed(KEY_SPACE)) if(input_is_key_pressed(KEY_SPACE))
{ {
struct Entity* model = scene_find(game_state->scene, "Light_Ent"); struct Entity* model = scene_find(game_state->scene, "Light_Ent");
vec3 x_axis = {0, 1, 0}; vec3 x_axis = {0, 1, 0};
transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD);
} }
if(input_is_key_pressed(KEY_M)) if(input_is_key_pressed(KEY_M))
{ {
struct Entity* model = scene_find(game_state->scene, "Model_Entity"); struct Entity* model = scene_find(game_state->scene, "Model_Entity");
//vec3 y_axis = {0, 0, 1}; //vec3 y_axis = {0, 0, 1};
//transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL); //transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL);
vec3 amount = {0, 0, -5 * dt}; vec3 amount = {0, 0, -5 * dt};
transform_translate(model, &amount, TS_LOCAL); transform_translate(model, &amount, TS_LOCAL);
} }
if(input_is_key_pressed(KEY_N)) if(input_is_key_pressed(KEY_N))
{ {
struct Entity* model = scene_find(game_state->scene, "Model_Entity"); struct Entity* model = scene_find(game_state->scene, "Model_Entity");
/* vec3 y_axis = {0, 0, 1}; */ /* vec3 y_axis = {0, 0, 1}; */
/* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */ /* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */
vec3 amount = {0, 0, 5 * dt}; vec3 amount = {0, 0, 5 * dt};
transform_translate(model, &amount, TS_LOCAL); transform_translate(model, &amount, TS_LOCAL);
} }
/*struct Entity* model = scene_find("Model_Entity"); /*struct Entity* model = scene_find("Model_Entity");
@ -388,22 +388,22 @@ void game_debug(float dt)
//Raycast test //Raycast test
if(input_is_key_pressed(KEY_R)) if(input_is_key_pressed(KEY_R))
{ {
/*Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true); /*Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true);
vec3 position = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f};
vec3 direction = {0.f, 0.f, 0.f}; vec3 direction = {0.f, 0.f, 0.f};
transform_get_absolute_forward(player_entity, &direction); transform_get_absolute_forward(player_entity, &direction);
transform_get_absolute_position(player_entity, &position); transform_get_absolute_position(player_entity, &position);
struct Raycast_Hit hit; struct Raycast_Hit hit;
if(platform->physics.cs_ray_cast(ray, &hit, position.x, position.y, position.z, direction.x, direction.y, direction.z)) 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); struct Entity* entity_hit = entity_get(hit.entity_id);
log_message("Ray hit %s", entity_hit->name); log_message("Ray hit %s", entity_hit->name);
} }
else else
{ {
log_message("Ray didn't hit anything!"); log_message("Ray didn't hit anything!");
} }
platform->physics.cs_remove(ray);*/ platform->physics.cs_remove(ray);*/
} }
// Immediate geometry test // Immediate geometry test
@ -483,8 +483,8 @@ void game_debug(float dt)
for(int i = 0; i < 10; i++) for(int i = 0; i < 10; i++)
{ {
im_position.x += i * 2.f; im_position.x += i * 2.f;
im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES); im_sphere(2.f, im_position, im_rot, prim_color, GDM_TRIANGLES);
} }
} }
@ -495,18 +495,18 @@ bool game_run(void)
while(!should_window_close) while(!should_window_close)
{ {
uint32 curr_time = platform->ticks_get(); uint32 curr_time = platform->ticks_get();
float delta_time = (float)(curr_time - last_time) / 1000.f; float delta_time = (float)(curr_time - last_time) / 1000.f;
last_time = curr_time; 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 */ 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); platform->poll_events(&should_window_close);
gui_input_end(); gui_input_end();
game_update(delta_time, &should_window_close); game_update(delta_time, &should_window_close);
game_post_update(delta_time); game_post_update(delta_time);
game_render(); game_render();
platform->window.swap_buffers(game_state->window); platform->window.swap_buffers(game_state->window);
} }
return true; 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("Console_Toggle", KS_RELEASED)) console_toggle(game_state->console);
if(input_map_state_get("Editor_Toggle", KS_RELEASED)) if(input_map_state_get("Editor_Toggle", KS_RELEASED))
{ {
//editor_toggle(); //editor_toggle();
if(game_state->game_mode == GAME_MODE_EDITOR) if(game_state->game_mode == GAME_MODE_EDITOR)
{ {
game_state->game_mode = GAME_MODE_GAME; game_state->game_mode = GAME_MODE_GAME;
game_state->scene->active_camera_index = CAM_GAME; game_state->scene->active_camera_index = CAM_GAME;
} }
else if(game_state->game_mode == GAME_MODE_GAME) else if(game_state->game_mode == GAME_MODE_GAME)
{ {
game_state->game_mode = GAME_MODE_EDITOR; game_state->game_mode = GAME_MODE_EDITOR;
game_state->scene->active_camera_index = CAM_EDITOR; game_state->scene->active_camera_index = CAM_EDITOR;
} }
} }
if(input_map_state_get("Reload_Game_Lib", KS_RELEASED)) if(input_map_state_get("Reload_Game_Lib", KS_RELEASED))
{ {
*window_should_close = true; *window_should_close = true;
platform->reload_game_lib(); platform->reload_game_lib();
return; return;
} }
//game_debug(dt); //game_debug(dt);
@ -545,11 +545,11 @@ void game_update(float dt, bool* window_should_close)
scene_update(game_state->scene, dt); scene_update(game_state->scene, dt);
if(game_state->game_mode == GAME_MODE_GAME) 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) 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) */ /* good old week day formula (double because precision) */
{int year_n = (sel_date.tm_mon < 2) ? year-1: year; {int year_n = (sel_date.tm_mon < 2) ? year-1: year;
int y = year_n % 100; int y = year_n % 100;
int c = year_n / 100; int c = year_n / 100;
int y4 = (int)((float)y / 4); int y4 = (int)((float)y / 4);
int c4 = (int)((float)c / 4); int c4 = (int)((float)c / 4);
int m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2); 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; int week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7;
/* weekdays */ /* weekdays */
nk_layout_row_dynamic(ctx, 35, 7); nk_layout_row_dynamic(ctx, 35, 7);
for (i = 0; i < (int)LEN(week_days); ++i) for (i = 0; i < (int)LEN(week_days); ++i)
nk_label(ctx, week_days[i], NK_TEXT_CENTERED); nk_label(ctx, week_days[i], NK_TEXT_CENTERED);
/* days */ /* days */
if (week_day > 0) nk_spacing(ctx, week_day); if (week_day > 0) nk_spacing(ctx, week_day);
for (i = 1; i <= days; ++i) { for (i = 1; i <= days; ++i) {
sprintf(buffer, "%d", i); sprintf(buffer, "%d", i);
if (nk_button_label(ctx, buffer)) { if (nk_button_label(ctx, buffer)) {
sel_date.tm_mday = i; sel_date.tm_mday = i;
nk_combo_close(ctx); nk_combo_close(ctx);
} }
}} }}
nk_combo_end(ctx); nk_combo_end(ctx);
} }
} }
@ -1628,7 +1628,7 @@ void game_debug_gui(float dt)
bounds = nk_widget_bounds(ctx); bounds = nk_widget_bounds(ctx);
nk_spacing(ctx, 1); nk_spacing(ctx, 1);
if ((nk_input_is_mouse_hovering_rect(in, bounds) || 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)) nk_input_is_mouse_down(in, NK_BUTTON_LEFT))
{ {
a = row_layout[0] + in->mouse.delta.x; a = row_layout[0] + in->mouse.delta.x;
@ -1651,7 +1651,7 @@ void game_debug_gui(float dt)
bounds = nk_widget_bounds(ctx); bounds = nk_widget_bounds(ctx);
nk_spacing(ctx, 1); nk_spacing(ctx, 1);
if ((nk_input_is_mouse_hovering_rect(in, bounds) || 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)) nk_input_is_mouse_down(in, NK_BUTTON_LEFT))
{ {
b = (row_layout[2] + in->mouse.delta.x); b = (row_layout[2] + in->mouse.delta.x);
@ -1707,7 +1707,7 @@ void game_debug_gui(float dt)
bounds = nk_widget_bounds(ctx); bounds = nk_widget_bounds(ctx);
nk_spacing(ctx, 1); nk_spacing(ctx, 1);
if ((nk_input_is_mouse_hovering_rect(in, bounds) || 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)) nk_input_is_mouse_down(in, NK_BUTTON_LEFT))
{ {
a = a + in->mouse.delta.y; a = a + in->mouse.delta.y;
@ -1732,7 +1732,7 @@ void game_debug_gui(float dt)
nk_layout_row_dynamic(ctx, 8, 1); nk_layout_row_dynamic(ctx, 8, 1);
bounds = nk_widget_bounds(ctx); bounds = nk_widget_bounds(ctx);
if ((nk_input_is_mouse_hovering_rect(in, bounds) || 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)) nk_input_is_mouse_down(in, NK_BUTTON_LEFT))
{ {
b = b + in->mouse.delta.y; b = b + in->mouse.delta.y;
@ -1773,31 +1773,31 @@ void game_cleanup(void)
{ {
if(game_state) if(game_state)
{ {
if(game_state->is_initialized) if(game_state->is_initialized)
{ {
editor_cleanup(); editor_cleanup();
scene_destroy(game_state->scene); scene_destroy(game_state->scene);
input_cleanup(); input_cleanup();
renderer_cleanup(game_state->renderer); renderer_cleanup(game_state->renderer);
gui_cleanup(); gui_cleanup();
console_destroy(game_state->console); console_destroy(game_state->console);
geom_cleanup(); geom_cleanup();
framebuffer_cleanup(); framebuffer_cleanup();
texture_cleanup(); texture_cleanup();
shader_cleanup(); shader_cleanup();
free(game_state->console); free(game_state->console);
free(game_state->scene); free(game_state->scene);
free(game_state->renderer); free(game_state->renderer);
} }
free(game_state); free(game_state);
game_state = NULL; game_state = NULL;
} }
if(platform) if(platform)
{ {
platform->physics.cleanup(); platform->physics.cleanup();
free(platform); 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; float y = this_ent->transform.position.y;
if(y < 10.f) if(y < 10.f)
{ {
//vec3 translation = {0.f, 50.f, 0.f}; //vec3 translation = {0.f, 50.f, 0.f};
//transform_translate(this_ent, &translation, TS_WORLD); //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, -100.f, 0.f);
} }
//platform->physics.body_force_add(body, 0.f, 500.f, 0.f); //platform->physics.body_force_add(body, 0.f, 500.f, 0.f);
} }

@ -3,6 +3,8 @@
#define MAX_SHADOWMAPS 4 #define MAX_SHADOWMAPS 4
struct Light;
void light_init(struct Light* light, int light_type); void light_init(struct Light* light, int light_type);
void light_reset(struct Light* light); void light_reset(struct Light* light);

@ -2,6 +2,7 @@
#define MODEL_H #define MODEL_H
struct Model; struct Model;
struct Static_Mesh;
void model_init(struct Model* model, struct Static_Mesh* mesh, const char* geometry_name, int material_type); 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); void model_reset(struct Model* model, struct Static_Mesh* mesh);

@ -8,6 +8,7 @@
#include "bounding_volumes.h" #include "bounding_volumes.h"
#include "../common/hashmap.h" #include "../common/hashmap.h"
#include "../common/log.h" #include "../common/log.h"
#include "entity.h"
void player_init(struct Player* player, struct Scene* scene) void player_init(struct Player* player, struct Scene* scene)
{ {

@ -2,6 +2,7 @@
#define PLAYER_H #define PLAYER_H
struct Player; struct Player;
struct Scene;
void player_init(struct Player* player, struct Scene* scene); void player_init(struct Player* player, struct Scene* scene);
void player_destroy(struct Player* player); void player_destroy(struct Player* player);

@ -87,24 +87,24 @@ void renderer_init(struct Renderer* renderer)
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height); platform->window.get_size(game_state->window, &width, &height);
renderer->def_albedo_tex = texture_create("def_albedo_texture", renderer->def_albedo_tex = texture_create("def_albedo_texture",
TU_DIFFUSE, TU_DIFFUSE,
width, height, width, height,
GL_RGB, GL_RGB,
GL_RGB16F, GL_RGB16F,
GL_FLOAT, GL_FLOAT,
NULL); 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_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_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_MIN_FILTER, GL_LINEAR);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MAG_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", renderer->def_depth_tex = texture_create("def_depth_texture",
TU_SHADOWMAP4, TU_SHADOWMAP4,
width, height, width, height,
GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F,
GL_FLOAT, GL_FLOAT,
NULL); 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_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_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -125,11 +125,11 @@ void renderer_init(struct Renderer* renderer)
renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch)); renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch));
if(!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 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(); im_init();
@ -137,7 +137,7 @@ void renderer_init(struct Renderer* renderer)
// Initialize materials // Initialize materials
for(int i = 0; i < MAT_MAX; i++) 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 */ /* Render each camera output into it's framebuffer or to the default framebuffer */
for(int i = 0; i < MAX_CAMERAS; i++) for(int i = 0; i < MAX_CAMERAS; i++)
{ {
struct Camera* camera = &scene->cameras[i]; struct Camera* camera = &scene->cameras[i];
if(!camera->base.active) continue; 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);
}
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].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); int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo;
shader_set_uniform_vec3(material->shader, uniform_name, &light->color); framebuffer_bind(fbo);
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));
for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++)
{ {
if(!material->registered_static_meshes[j]) continue; glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo));
glEnable(GL_DEPTH_TEST);
/* for each registered model, set up uniforms and render */ glDepthFunc(GL_LEQUAL);
struct Static_Mesh* mesh = material->registered_static_meshes[j]; glClearColor(camera->clear_color.x,
struct Geometry* geometry = geom_get(mesh->model.geometry_index); camera->clear_color.y,
camera->clear_color.z,
/* Check if model is in frustum */ camera->clear_color.w);
vec3 abs_pos, abs_scale; glEnable(GL_CULL_FACE );
transform_get_absolute_position(&mesh->base, &abs_pos); glCullFace(GL_BACK);
transform_get_absolute_scale(&mesh->base, &abs_scale); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); static mat4 mvp;
if(intersection == IT_OUTSIDE) for(int i = 0; i < MAT_MAX; i++)
{
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; /* for each material, get all the registered models and render them */
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; struct Material* material = &renderer->materials[i];
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; GL_CHECK(shader_bind(material->shader));
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;
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].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].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 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));
}
/* 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);
/* Set pipeline uniforms that are derived per model */ editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices);
mat4_identity(&mvp);
mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat); renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0;
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));
}
} }
shader_unbind(); framebuffer_unbind();
} glDisable(GL_DEPTH_TEST);
editor_debugvar_slot_set_int(renderer->num_rendered_slot, renderer->num_rendered); glDisable(GL_CULL_FACE);
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);
} }
/* Final Render */ /* Final Render */
@ -340,71 +341,71 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene)
struct Hashmap* cvars = platform->config.get(); struct Hashmap* cvars = platform->config.get();
if(hashmap_bool_get(cvars, "debug_draw_enabled")) if(hashmap_bool_get(cvars, "debug_draw_enabled"))
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color");
shader_bind(renderer->debug_shader); shader_bind(renderer->debug_shader);
{ {
static mat4 mvp; static mat4 mvp;
shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color); shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color);
for(int i = 0; i < MAX_STATIC_MESHES; i++) for(int i = 0; i < MAX_STATIC_MESHES; i++)
{ {
struct Static_Mesh* mesh = &scene->static_meshes[i]; struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active) continue; if(!mesh->base.active) continue;
struct Model* model = &mesh->model; struct Model* model = &mesh->model;
struct Transform* transform = &mesh->base.transform; struct Transform* transform = &mesh->base.transform;
int geometry = model->geometry_index; int geometry = model->geometry_index;
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp);
geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode")); geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode"));
} }
} }
shader_unbind(); shader_unbind();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
// Debug Physics render // Debug Physics render
if(hashmap_bool_get(cvars, "debug_draw_physics")) if(hashmap_bool_get(cvars, "debug_draw_physics"))
{ {
static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f };
for(int i = 0; i < MAX_STATIC_MESHES; i++) for(int i = 0; i < MAX_STATIC_MESHES; i++)
{ {
struct Static_Mesh* mesh = &scene->static_meshes[i]; struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue; if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue;
//Get collision mesh and it's props then render it //Get collision mesh and it's props then render it
vec3 pos = {0.f}; vec3 pos = {0.f};
quat rot = {0.f, 0.f, 0.f, 1.f }; quat rot = {0.f, 0.f, 0.f, 1.f };
if(mesh->collision.rigidbody) if(mesh->collision.rigidbody)
{ {
platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z); 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); platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w);
} }
else else
{ {
platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z); 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); 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); int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape);
switch(collision_shape_type) switch(collision_shape_type)
{ {
case CST_SPHERE: case CST_SPHERE:
{ {
float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape); float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape);
im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES); im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES);
} }
break; break;
case CST_BOX: case CST_BOX:
{ {
float x = 0.f, y = 0.f, z = 0.f; float x = 0.f, y = 0.f, z = 0.f;
platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z); platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z);
im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES);
}; };
break; break;
default: break; default: break;
} }
} }
} }
//Immediate mode geometry render //Immediate mode geometry render
@ -414,16 +415,16 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene)
/* Render 2D stuff */ /* Render 2D stuff */
shader_bind(renderer->sprite_batch->shader); shader_bind(renderer->sprite_batch->shader);
{ {
static mat4 ortho_mat; static mat4 ortho_mat;
mat4_identity(&ortho_mat); mat4_identity(&ortho_mat);
int width, height; int width, height;
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height); 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); 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); 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(); shader_unbind();
@ -435,7 +436,7 @@ void renderer_cleanup(struct Renderer* renderer)
{ {
for(int i = 0; i < MAT_MAX; i++) for(int i = 0; i < MAT_MAX; i++)
{ {
material_reset(&renderer->materials[i]); material_reset(&renderer->materials[i]);
} }
im_cleanup(); im_cleanup();
sprite_batch_remove(renderer->sprite_batch); 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; float aspect = (float)width / (float)height;
for(int i = 0; i < MAX_CAMERAS; i++) for(int i = 0; i < MAX_CAMERAS; i++)
{ {
struct Camera* viewer = &scene->cameras[i]; struct Camera* viewer = &scene->cameras[i];
viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(viewer); camera_update_proj(viewer);
} }
framebuffer_resize_all(width, height); framebuffer_resize_all(width, height);

@ -6,6 +6,7 @@
#include "material.h" #include "material.h"
struct Sprite_Batch; struct Sprite_Batch;
struct Scene;
enum Fog_Mode enum Fog_Mode
{ {

@ -10,8 +10,8 @@
#define MAX_STATIC_MESHES 1024 #define MAX_STATIC_MESHES 1024
#define MAX_SOUND_SOURCES 128 #define MAX_SOUND_SOURCES 128
struct Ray; struct Ray;
struct Raycast_Result;
struct Scene struct Scene
{ {

Loading…
Cancel
Save