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. 3
      build/genie.lua
  3. 1
      src/common/log.h
  4. 276
      src/common/parser.c
  5. 232
      src/game/platform.c
  6. 2
      src/game/sound.c
  7. 94
      src/libsymmetry/console.c
  8. 4
      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. 3
      src/libsymmetry/player.h
  15. 501
      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"}
@ -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"); 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) printf("Output of blender addon build : \n%s\n", output)
end end
} }

@ -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++; current_line++;
memset(type_str, '\0', HASH_MAX_KEY_LEN); memset(type_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)
{ {
continue; 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 */ if(line_buffer[0] == '#')
char c = ' '; continue;
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 == '{') /* Object type */
{ if(sscanf(line_buffer, "%s", type_str) != 1)
obj_beginning = ftell(file); {
c = ' '; log_warning("Malformed line in config file %s, line %d", filename, current_line);
while(!feof(file)) 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); log_warning("Invalid object type '%s' on line %d", type_str, current_line);
if(c == '\n')
{
current_line++;
continue; 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, /* check if we found opening brace of next object,
if this is true then it means that this object is missing if this is true then it means that this object is missing
it's closing brace and we should stop */ it's closing brace and we should stop */
if(c == '{') if(c == '{')
{ {
found_next_before_current_ended = true; found_next_before_current_ended = true;
break; break;
} }
if(c == '}') if(c == '}')
{ {
obj_ending = ftell(file) - 1; 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;
} memset(obj_str, '\0', 1024);
} memset(line_buffer, '\0', MAX_LINE_LEN);
fseek(file, obj_beginning, SEEK_SET);
if(obj_beginning == -1) fread(obj_str, obj_ending - obj_beginning, 1, file);
{
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);
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,
@ -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); void console_on_log_error(struct Console* console, const char* context, const char* error, va_list args);
#endif #endif

@ -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,9 +2,10 @@
#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);
void player_update(struct Player* player, struct Scene* scene, float dt); void player_update(struct Player* player, struct Scene* scene, float dt);
#endif #endif

@ -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) 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); /* for each material, get all the registered models and render them */
shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); struct Material* material = &renderer->materials[i];
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); GL_CHECK(shader_bind(material->shader));
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count); if(material->lit) /* Set light information */
shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); {
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); 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); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->inner_angle); shader_set_uniform_float(material->shader, uniform_name, light->inner_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->falloff); shader_set_uniform_float(material->shader, uniform_name, light->falloff);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->radius); shader_set_uniform_int(material->shader, uniform_name, light->radius);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
} }
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light->color); shader_set_uniform_vec3(material->shader, uniform_name, &light->color);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->intensity); shader_set_uniform_float(material->shader, uniform_name, light->intensity);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->type); shader_set_uniform_int(material->shader, uniform_name, light->type);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); 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 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)); 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); vec3 camera_pos = {0, 0, 0};
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos)); transform_get_absolute_position(&camera->base, &camera_pos);
} GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos));
}
/* Set material pipeline uniforms */
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode)); /* Set material pipeline uniforms */
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_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode));
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_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density));
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_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_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color)); 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_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light)); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color));
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_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++) for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++)
{ {
if(!material->registered_static_meshes[j]) continue; if(!material->registered_static_meshes[j]) continue;
/* for each registered model, set up uniforms and render */ /* for each registered model, set up uniforms and render */
struct Static_Mesh* mesh = material->registered_static_meshes[j]; struct Static_Mesh* mesh = material->registered_static_meshes[j];
struct Geometry* geometry = geom_get(mesh->model.geometry_index); struct Geometry* geometry = geom_get(mesh->model.geometry_index);
/* Check if model is in frustum */ /* Check if model is in frustum */
vec3 abs_pos, abs_scale; vec3 abs_pos, abs_scale;
transform_get_absolute_position(&mesh->base, &abs_pos); transform_get_absolute_position(&mesh->base, &abs_pos);
transform_get_absolute_scale(&mesh->base, &abs_scale); transform_get_absolute_scale(&mesh->base, &abs_scale);
int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale); int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale);
if(intersection == IT_OUTSIDE) if(intersection == IT_OUTSIDE)
{ {
renderer->num_culled++; renderer->num_culled++;
continue; continue;
} }
else else
{ {
renderer->num_indices += array_len(geometry->indices); renderer->num_indices += array_len(geometry->indices);
renderer->num_rendered++; renderer->num_rendered++;
} }
/* set material params for the model */ /* set material params for the model */
for(int k = 0; k < MMP_MAX; k++) for(int k = 0; k < MMP_MAX; k++)
{ {
switch(mesh->model.material_params[k].type) 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_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_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_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; 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 */ /* Set pipeline uniforms that are derived per model */
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat); 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)); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MVP].type, material->pipeline_params[MPP_MVP].location, &mvp));
if(material->lit) 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_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)); 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 inv_mat;
mat4_identity(&inv_mat); mat4_identity(&inv_mat);
mat4_inverse(&inv_mat, &mesh->base.transform.trans_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)); 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 */ /* Render the geometry */
//int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode); //int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode);
//geom_render(model->geometry_index, draw_mode); //geom_render(model->geometry_index, draw_mode);
geom_render(mesh->model.geometry_index, GDM_TRIANGLES); geom_render(mesh->model.geometry_index, GDM_TRIANGLES);
for(int k = 0; k < MMP_MAX; k++) for(int k = 0; k < MMP_MAX; k++)
{ {
/* unbind textures, if any */ /* unbind textures, if any */
if(material->model_params[k].type == UT_TEX) if(material->model_params[k].type == UT_TEX)
GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int)); 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(); 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