Removed several warnings

dev
Shariq Shah 7 years ago
parent 785b762c7a
commit c651847d43
  1. 4
      .dir-locals.el
  2. 1
      README.md
  3. 350
      src/common/hashmap.c
  4. 78
      src/common/hashmap.h
  5. 897
      src/common/linmath.c
  6. 3
      src/common/linmath.h
  7. 402
      src/common/parser.c
  8. 118
      src/common/string_utils.c
  9. 163
      src/game/config_vars.c
  10. 616
      src/game/physics.c
  11. 492
      src/game/platform.c
  12. 358
      src/libsymmetry/camera.c
  13. 168
      src/libsymmetry/console.c
  14. 1189
      src/libsymmetry/editor.c
  15. 172
      src/libsymmetry/entity.h
  16. 966
      src/libsymmetry/game.c
  17. 60
      src/libsymmetry/material.h
  18. 106
      src/libsymmetry/player.c
  19. 841
      src/libsymmetry/renderer.c
  20. 52
      src/libsymmetry/renderer.h
  21. 1016
      src/libsymmetry/scene.c
  22. 20
      src/libsymmetry/scene.h

@ -2,8 +2,8 @@
((string-equal system-type "windows-nt") ; Microsoft Windows ((string-equal system-type "windows-nt") ; Microsoft Windows
(progn (progn
((c-mode . ((c-mode .
((company-clang-arguments . ("-IE:/Projects/symmerty/include" "-IE:\\Projects\\symmerty\\third_party\\windows\\SDL2-2.0.5\\include")) ((company-clang-arguments . ("-IW:/include"))
(flycheck-clang-include-path . ("E:/Projects/symmerty/include"))) (flycheck-clang-include-path . ("W:/include")))
) )
((c++-mode . ((mode . c)))) ((c++-mode . ((mode . c))))
) )

@ -163,6 +163,7 @@
- Console fix bug when enabled in editor mode - Console fix bug when enabled in editor mode
- Console command history - Console command history
- Console command help - Console command help
- Space partitioning and scene handling
- NPR and cross-hatching - 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

@ -9,14 +9,14 @@
struct Hashmap_Entry struct Hashmap_Entry
{ {
char* key; char* key;
struct Variant value; struct Variant value;
}; };
struct Hashmap struct Hashmap
{ {
struct Hashmap_Entry* buckets[HASH_MAP_NUM_BUCKETS]; struct Hashmap_Entry* buckets[HASH_MAP_NUM_BUCKETS];
int iter_bucket, iter_index; int iter_bucket, iter_index;
}; };
static unsigned int hashmap_generate_hash(const char* key); static unsigned int hashmap_generate_hash(const char* key);
@ -24,337 +24,337 @@ static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const ch
static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const char* key) static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const char* key)
{ {
unsigned int index = hashmap_generate_hash(key); unsigned int index = hashmap_generate_hash(key);
struct Hashmap_Entry* new_entry = NULL; struct Hashmap_Entry* new_entry = NULL;
for(int i = 0; i < array_len(hashmap->buckets[index]); i++) /* Look for duplicates and over-write if found */ for(int i = 0; i < array_len(hashmap->buckets[index]); i++) /* Look for duplicates and over-write if found */
{
if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0)
{ {
if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) new_entry = &hashmap->buckets[index][i];
{ if(new_entry->key) free(new_entry->key);
new_entry = &hashmap->buckets[index][i]; break;
if(new_entry->key) free(new_entry->key);
break;
}
} }
if(!new_entry) new_entry = array_grow(hashmap->buckets[index], struct Hashmap_Entry); }
new_entry->key = str_new(key); if(!new_entry) new_entry = array_grow(hashmap->buckets[index], struct Hashmap_Entry);
new_entry->value.type = VT_NONE; new_entry->key = str_new(key);
variant_free(&new_entry->value); new_entry->value.type = VT_NONE;
return new_entry; variant_free(&new_entry->value);
return new_entry;
} }
unsigned int hashmap_generate_hash(const char* key) unsigned int hashmap_generate_hash(const char* key)
{ {
unsigned int index = 0; unsigned int index = 0;
const int multiplier = 51; const int multiplier = 51;
for(int i = 0; i < (int)strlen(key); i++) for(int i = 0; i < (int)strlen(key); i++)
index = index * multiplier + key[i]; index = index * multiplier + key[i];
return index % HASH_MAP_NUM_BUCKETS; return index % HASH_MAP_NUM_BUCKETS;
} }
struct Hashmap* hashmap_new(void) struct Hashmap* hashmap_new(void)
{ {
struct Hashmap* hashmap = malloc(sizeof(*hashmap)); struct Hashmap* hashmap = malloc(sizeof(*hashmap));
if(!hashmap) if(!hashmap)
return NULL; return NULL;
for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++)
hashmap->buckets[i] = array_new(struct Hashmap_Entry); hashmap->buckets[i] = array_new(struct Hashmap_Entry);
hashmap->iter_bucket = 0; hashmap->iter_bucket = 0;
hashmap->iter_index = -1; hashmap->iter_index = -1;
return hashmap; return hashmap;
} }
void hashmap_free(struct Hashmap* hashmap) void hashmap_free(struct Hashmap* hashmap)
{ {
if(!hashmap) return; if(!hashmap) return;
for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++)
{
for(int j = 0; j < array_len(hashmap->buckets[i]); j++)
{ {
for(int j = 0; j < array_len(hashmap->buckets[i]); j++) struct Hashmap_Entry* entry = &hashmap->buckets[i][j];
{ if(entry->key)
struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; {
if(entry->key) free(entry->key);
{ entry->key = NULL;
free(entry->key); }
entry->key = NULL; variant_free(&entry->value);
}
variant_free(&entry->value);
}
array_free(hashmap->buckets[i]);
hashmap->buckets[i] = NULL;
} }
free(hashmap); array_free(hashmap->buckets[i]);
hashmap = NULL; hashmap->buckets[i] = NULL;
}
free(hashmap);
hashmap = NULL;
} }
void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value) void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value)
{ {
if(!hashmap || !key || !value) return; if(!hashmap || !key || !value) return;
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_copy(&new_entry->value, value); variant_copy(&new_entry->value, value);
} }
struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key) struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key)
{ {
if(!hashmap || !key) return NULL; if(!hashmap || !key) return NULL;
struct Variant* value = NULL; struct Variant* value = NULL;
unsigned int index = hashmap_generate_hash(key); unsigned int index = hashmap_generate_hash(key);
int key_len = strlen(key); int key_len = (int)strlen(key);
int compare_len = key_len < HASH_MAX_KEY_LEN ? key_len : HASH_MAX_KEY_LEN; int compare_len = key_len < HASH_MAX_KEY_LEN ? key_len : HASH_MAX_KEY_LEN;
for(int i = 0; i < array_len(hashmap->buckets[index]); i++) for(int i = 0; i < array_len(hashmap->buckets[index]); i++)
{
if(strncmp(key, hashmap->buckets[index][i].key, compare_len) == 0)
{ {
if(strncmp(key, hashmap->buckets[index][i].key, compare_len) == 0) value = &hashmap->buckets[index][i].value;
{ break;
value = &hashmap->buckets[index][i].value;
break;
}
} }
return value; }
return value;
} }
void hashmap_value_remove(struct Hashmap* hashmap, const char* key) void hashmap_value_remove(struct Hashmap* hashmap, const char* key)
{ {
if(!hashmap || !key) return; if(!hashmap || !key) return;
unsigned int index = hashmap_generate_hash(key); unsigned int index = hashmap_generate_hash(key);
int index_to_remove = -1; int index_to_remove = -1;
for(int i = 0; i < array_len(hashmap->buckets[index]); i++) for(int i = 0; i < array_len(hashmap->buckets[index]); i++)
{
if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0)
{ {
if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) index_to_remove = i;
{ break;
index_to_remove = i;
break;
}
} }
if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove); }
if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove);
} }
bool hashmap_value_exists(struct Hashmap * hashmap, const char * key) bool hashmap_value_exists(struct Hashmap * hashmap, const char * key)
{ {
return hashmap_value_get(hashmap, key); return hashmap_value_get(hashmap, key);
} }
void hashmap_float_set(struct Hashmap* hashmap, const char* key, const float value) void hashmap_float_set(struct Hashmap* hashmap, const char* key, const float value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_float(&new_entry->value, value); variant_assign_float(&new_entry->value, value);
} }
void hashmap_int_set(struct Hashmap* hashmap, const char* key, const int value) void hashmap_int_set(struct Hashmap* hashmap, const char* key, const int value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_int(&new_entry->value, value); variant_assign_int(&new_entry->value, value);
} }
void hashmap_double_set(struct Hashmap* hashmap, const char* key, const double value) void hashmap_double_set(struct Hashmap* hashmap, const char* key, const double value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_double(&new_entry->value, value); variant_assign_double(&new_entry->value, value);
} }
void hashmap_bool_set(struct Hashmap* hashmap, const char* key, const bool value) void hashmap_bool_set(struct Hashmap* hashmap, const char* key, const bool value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_bool(&new_entry->value, value); variant_assign_bool(&new_entry->value, value);
} }
void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value) void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec2(&new_entry->value, value); variant_assign_vec2(&new_entry->value, value);
} }
void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value) void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec3(&new_entry->value, value); variant_assign_vec3(&new_entry->value, value);
} }
void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value) void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec4(&new_entry->value, value); variant_assign_vec4(&new_entry->value, value);
} }
void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value) void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_quat(&new_entry->value, value); variant_assign_quat(&new_entry->value, value);
} }
void hashmap_vec2_setf(struct Hashmap* hashmap, const char* key, const float x, const float y) void hashmap_vec2_setf(struct Hashmap* hashmap, const char* key, const float x, const float y)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec2f(&new_entry->value, x, y); variant_assign_vec2f(&new_entry->value, x, y);
} }
void hashmap_vec3_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z) void hashmap_vec3_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec3f(&new_entry->value, x, y, z); variant_assign_vec3f(&new_entry->value, x, y, z);
} }
void hashmap_vec4_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w) void hashmap_vec4_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_vec4f(&new_entry->value, x, y, z, w); variant_assign_vec4f(&new_entry->value, x, y, z, w);
} }
void hashmap_quat_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w) void hashmap_quat_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_quatf(&new_entry->value, x, y, z, w); variant_assign_quatf(&new_entry->value, x, y, z, w);
} }
void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value) void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_mat4(&new_entry->value, value); variant_assign_mat4(&new_entry->value, value);
} }
void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value) void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_str(&new_entry->value, value); variant_assign_str(&new_entry->value, value);
} }
void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value) void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value)
{ {
struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key); struct Hashmap_Entry* new_entry = hashmap_entry_new(hashmap, key);
variant_assign_ptr(&new_entry->value, value); variant_assign_ptr(&new_entry->value, value);
} }
float hashmap_float_get(const struct Hashmap* hashmap, const char* key) float hashmap_float_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_FLOAT); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_FLOAT);
return variant->val_float; return variant->val_float;
} }
int hashmap_int_get(const struct Hashmap* hashmap, const char* key) int hashmap_int_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_INT); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_INT);
return variant->val_int; return variant->val_int;
} }
double hashmap_double_get(const struct Hashmap* hashmap, const char* key) double hashmap_double_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_DOUBLE); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_DOUBLE);
return variant->val_double; return variant->val_double;
} }
bool hashmap_bool_get(const struct Hashmap* hashmap, const char* key) bool hashmap_bool_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_BOOL); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_BOOL);
return variant->val_bool; return variant->val_bool;
} }
vec2 hashmap_vec2_get(const struct Hashmap* hashmap, const char* key) vec2 hashmap_vec2_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC2); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC2);
return variant->val_vec2; return variant->val_vec2;
} }
vec3 hashmap_vec3_get(const struct Hashmap* hashmap, const char* key) vec3 hashmap_vec3_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC3); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC3);
return variant->val_vec3; return variant->val_vec3;
} }
vec4 hashmap_vec4_get(const struct Hashmap* hashmap, const char* key) vec4 hashmap_vec4_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC4); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC4);
return variant->val_vec4; return variant->val_vec4;
} }
quat hashmap_quat_get(const struct Hashmap* hashmap, const char* key) quat hashmap_quat_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_QUAT); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_QUAT);
return variant->val_quat; return variant->val_quat;
} }
const mat4* hashmap_mat4_get(const struct Hashmap* hashmap, const char* key) const mat4* hashmap_mat4_get(const struct Hashmap* hashmap, const char* key)
{ {
struct Variant* variant = hashmap_value_get(hashmap, key); struct Variant* variant = hashmap_value_get(hashmap, key);
if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_MAT4); if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_MAT4);
return variant->val_mat4; return variant->val_mat4;
} }
const char* hashmap_str_get(const struct Hashmap* hashmap, const char* key) const char* hashmap_str_get(const struct Hashmap* hashmap, const char* key)
{ {
const struct Variant* variant = hashmap_value_get(hashmap, key); const struct Variant* variant = hashmap_value_get(hashmap, key);
return variant->val_str; return variant->val_str;
} }
void* hashmap_ptr_get(const struct Hashmap* hashmap, const char* key) void* hashmap_ptr_get(const struct Hashmap* hashmap, const char* key)
{ {
const struct Variant* variant = hashmap_value_get(hashmap, key); const struct Variant* variant = hashmap_value_get(hashmap, key);
return variant->val_voidptr; return variant->val_voidptr;
} }
void hashmap_debug_print(const struct Hashmap* hashmap) void hashmap_debug_print(const struct Hashmap* hashmap)
{ {
if(!hashmap) return; if(!hashmap) return;
static char str[128]; static char str[128];
memset(str, '\0', 128); memset(str, '\0', 128);
for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++)
{
log_message("Bucket : %d", i);
log_message("Bucket len : %d", array_len(hashmap->buckets[i]));
for(int j = 0; j < array_len(hashmap->buckets[i]); j++)
{ {
log_message("Bucket : %d", i); struct Hashmap_Entry* entry = &hashmap->buckets[i][j];
log_message("Bucket len : %d", array_len(hashmap->buckets[i])); const struct Variant* value = &entry->value;
for(int j = 0; j < array_len(hashmap->buckets[i]); j++) const char* key = entry->key;
{ log_message("Key : %s", key);
struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; variant_to_str(value, str, 128);
const struct Variant* value = &entry->value; log_message("Value : %s", str);
const char* key = entry->key; memset(str, '\0', 128);
log_message("Key : %s", key);
variant_to_str(value, str, 128);
log_message("Value : %s", str);
memset(str, '\0', 128);
}
} }
}
} }
void hashmap_iter_begin(struct Hashmap* hashmap) void hashmap_iter_begin(struct Hashmap* hashmap)
{ {
assert(hashmap); assert(hashmap);
hashmap->iter_bucket = 0; hashmap->iter_bucket = 0;
hashmap->iter_index = -1; hashmap->iter_index = -1;
} }
int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value) int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value)
{ {
assert(hashmap); assert(hashmap);
for(;hashmap->iter_bucket < HASH_MAP_NUM_BUCKETS; hashmap->iter_bucket++) for(;hashmap->iter_bucket < HASH_MAP_NUM_BUCKETS; hashmap->iter_bucket++)
{
if(hashmap->buckets[hashmap->iter_bucket])
{ {
if(hashmap->buckets[hashmap->iter_bucket]) if(++hashmap->iter_index < array_len(hashmap->buckets[hashmap->iter_bucket]))
{ {
if(++hashmap->iter_index < array_len(hashmap->buckets[hashmap->iter_bucket])) *key = hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].key;
{ *value = &hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].value;
*key = hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].key; return 1;
*value = &hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].value; }
return 1; else
} {
else hashmap->iter_index = -1;
{ }
hashmap->iter_index = -1;
}
}
} }
return 0; }
return 0;
} }
void hashmap_copy(struct Hashmap* from, struct Hashmap* to) void hashmap_copy(struct Hashmap* from, struct Hashmap* to)
{ {
struct Variant* from_val = NULL; struct Variant* from_val = NULL;
char* from_key = NULL; char* from_key = NULL;
HASHMAP_FOREACH(from, from_key, from_val) HASHMAP_FOREACH(from, from_key, from_val)
{ {
hashmap_value_set(to, from_key, from_val); hashmap_value_set(to, from_key, from_val);
} }
} }

@ -11,46 +11,46 @@
struct Hashmap; struct Hashmap;
struct Variant; struct Variant;
struct Hashmap* hashmap_new(void); struct Hashmap* hashmap_new(void);
void hashmap_free(struct Hashmap* hashmap); void hashmap_free(struct Hashmap* hashmap);
void hashmap_copy(struct Hashmap* from, struct Hashmap* to); void hashmap_copy(struct Hashmap* from, struct Hashmap* to);
void hashmap_value_remove(struct Hashmap* hashmap, const char* key); void hashmap_value_remove(struct Hashmap* hashmap, const char* key);
bool hashmap_value_exists(struct Hashmap* hashmap, const char* key); bool hashmap_value_exists(struct Hashmap* hashmap, const char* key);
void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value); void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value);
struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key); struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key);
void hashmap_float_set(struct Hashmap* hashmap, const char* key, const float value); void hashmap_float_set(struct Hashmap* hashmap, const char* key, const float value);
void hashmap_int_set(struct Hashmap* hashmap, const char* key, const int value); void hashmap_int_set(struct Hashmap* hashmap, const char* key, const int value);
void hashmap_double_set(struct Hashmap* hashmap, const char* key, const double value); void hashmap_double_set(struct Hashmap* hashmap, const char* key, const double value);
void hashmap_bool_set(struct Hashmap* hashmap, const char* key, const bool value); void hashmap_bool_set(struct Hashmap* hashmap, const char* key, const bool value);
void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value); void hashmap_vec2_set(struct Hashmap* hashmap, const char* key, const vec2* value);
void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value); void hashmap_vec3_set(struct Hashmap* hashmap, const char* key, const vec3* value);
void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value); void hashmap_vec4_set(struct Hashmap* hashmap, const char* key, const vec4* value);
void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value); void hashmap_quat_set(struct Hashmap* hashmap, const char* key, const quat* value);
void hashmap_vec2_setf(struct Hashmap* hashmap, const char* key, const float x, const float y); void hashmap_vec2_setf(struct Hashmap* hashmap, const char* key, const float x, const float y);
void hashmap_vec3_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z); void hashmap_vec3_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z);
void hashmap_vec4_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w); void hashmap_vec4_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w);
void hashmap_quat_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w); void hashmap_quat_setf(struct Hashmap* hashmap, const char* key, const float x, const float y, const float z, const float w);
void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value); void hashmap_mat4_set(struct Hashmap* hashmap, const char* key, const mat4* value);
void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value); void hashmap_str_set(struct Hashmap* hashmap, const char* key, const char* value);
void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value); void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value);
float hashmap_float_get(const struct Hashmap* hashmap, const char* key); float hashmap_float_get(const struct Hashmap* hashmap, const char* key);
int hashmap_int_get(const struct Hashmap* hashmap, const char* key); int hashmap_int_get(const struct Hashmap* hashmap, const char* key);
double hashmap_double_get(const struct Hashmap* hashmap, const char* key); double hashmap_double_get(const struct Hashmap* hashmap, const char* key);
bool hashmap_bool_get(const struct Hashmap* hashmap, const char* key); bool hashmap_bool_get(const struct Hashmap* hashmap, const char* key);
vec2 hashmap_vec2_get(const struct Hashmap* hashmap, const char* key); vec2 hashmap_vec2_get(const struct Hashmap* hashmap, const char* key);
vec3 hashmap_vec3_get(const struct Hashmap* hashmap, const char* key); vec3 hashmap_vec3_get(const struct Hashmap* hashmap, const char* key);
vec4 hashmap_vec4_get(const struct Hashmap* hashmap, const char* key); vec4 hashmap_vec4_get(const struct Hashmap* hashmap, const char* key);
quat hashmap_quat_get(const struct Hashmap* hashmap, const char* key); quat hashmap_quat_get(const struct Hashmap* hashmap, const char* key);
const mat4* hashmap_mat4_get(const struct Hashmap* hashmap, const char* key); const mat4* hashmap_mat4_get(const struct Hashmap* hashmap, const char* key);
const char* hashmap_str_get(const struct Hashmap* hashmap, const char* key); const char* hashmap_str_get(const struct Hashmap* hashmap, const char* key);
void* hashmap_ptr_get(const struct Hashmap* hashmap, const char* key); void* hashmap_ptr_get(const struct Hashmap* hashmap, const char* key);
void hashmap_debug_print(const struct Hashmap* hashmap); void hashmap_debug_print(const struct Hashmap* hashmap);
/* Only used during iteration */ /* Only used during iteration */
void hashmap_iter_begin(struct Hashmap* hashmap); void hashmap_iter_begin(struct Hashmap* hashmap);
int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value); int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value);
#define HASHMAP_FOREACH(hashmap, key, value) \ #define HASHMAP_FOREACH(hashmap, key, value) \
hashmap_iter_begin(hashmap); \ hashmap_iter_begin(hashmap); \

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@ i'll make my own additions like SIMD etc later on.
/* conversions */ /* conversions */
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846f
#endif #endif
#define EPSILON 0.0001 #define EPSILON 0.0001
#define TO_RADIANS(degrees) ((degrees * M_PI) / 180.0) #define TO_RADIANS(degrees) ((degrees * M_PI) / 180.0)
@ -132,5 +132,6 @@ void quat_mul_vec3(vec3* res, const quat* q, const vec3* v);
void quat_assign(quat* res, const quat* val); void quat_assign(quat* res, const quat* val);
void quat_identity(quat* res); void quat_identity(quat* res);
void quat_fill(quat* res, float x, float y, float z, float w); void quat_fill(quat* res, float x, float y, float z, float w);
void quat_mul_mat4(quat* res, quat* val, mat4* mat);
#endif #endif

@ -15,70 +15,70 @@
bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line) bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line)
{ {
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 */
char format_str[64]; char format_str[64];
char key_str[HASH_MAX_KEY_LEN]; char key_str[HASH_MAX_KEY_LEN];
char value_str[MAX_VALUE_LEN]; char value_str[MAX_VALUE_LEN];
char line_buffer[MAX_LINE_LEN]; char line_buffer[MAX_LINE_LEN];
memset(key_str, '\0', HASH_MAX_KEY_LEN); memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(line_buffer, '\0', MAX_LINE_LEN); memset(line_buffer, '\0', MAX_LINE_LEN);
memset(format_str, '\0', 64); memset(format_str, '\0', 64);
snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN); snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN);
while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{
current_line++;
memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(value_str, '\0', HASH_MAX_KEY_LEN);
if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{ {
if(return_on_emptyline) current_line++;
return true; memset(key_str, '\0', HASH_MAX_KEY_LEN);
else memset(value_str, '\0', HASH_MAX_KEY_LEN);
continue;
}
if(line_buffer[0] == '#') if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
continue; {
if(return_on_emptyline)
return true;
else
continue;
}
if(sscanf(line_buffer, format_str, key_str, value_str) != 2) if(line_buffer[0] == '#')
{ continue;
log_warning("Malformed value in config file %s, line %d", filename, current_line);
continue;
}
assign_func(key_str, value_str, filename, current_line); if(sscanf(line_buffer, format_str, key_str, value_str) != 2)
{
log_warning("Malformed value in config file %s, line %d", filename, current_line);
continue;
} }
return true;
assign_func(key_str, value_str, filename, current_line);
}
return true;
} }
struct Parser* parser_load_objects(FILE* file, const char* filename) struct Parser* parser_load_objects(FILE* file, const char* filename)
{ {
/* Note, this is isn't really a proper parser and might have lurking bugs, it just has to be /* Note, this is isn't really a proper parser and might have lurking bugs, it just has to be
good enough for my needs. For example, multiple opening and closing braces on them good enough for my needs. For example, multiple opening and closing braces on them
same line are fine but opening brace on the same line as type is NOT fine. There same line are fine but opening brace on the same line as type is NOT fine. There
are probably several others that i don't know of yet. This is just a temporary solution, are probably several others that i don't know of yet. This is just a temporary solution,
i may completely change the format in the future or switch to binary or use something like i may completely change the format in the future or switch to binary or use something like
JSON or TOML etc. */ JSON or TOML etc. */
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));
if(!parser) if(!parser)
@ -89,109 +89,109 @@ struct Parser* parser_load_objects(FILE* file, const char* filename)
parser->objects = array_new(struct Parser_Object); parser->objects = array_new(struct Parser_Object);
int current_line = 0; int current_line = 0;
char line_buffer[MAX_LINE_LEN]; char line_buffer[MAX_LINE_LEN];
char type_str[HASH_MAX_KEY_LEN]; char type_str[HASH_MAX_KEY_LEN];
char obj_str[1024]; char obj_str[1024];
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] == '#') if(line_buffer[0] == '#')
continue; continue;
/* Object type */ /* Object type */
if(sscanf(line_buffer, "%s", type_str) != 1) if(sscanf(line_buffer, "%s", type_str) != 1)
{ {
log_warning("Malformed line in config file %s, line %d", filename, current_line); log_warning("Malformed line in config file %s, line %d", filename, current_line);
continue; continue;
} }
// Check if type string is valid // Check if type string is valid
int type_str_len = strnlen(type_str, HASH_MAX_KEY_LEN); 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) 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); log_warning("Invalid object type '%s' on line %d", type_str, current_line);
continue; continue;
} }
long obj_beginning = -1; long obj_beginning = -1;
long obj_ending = -1; long obj_ending = -1;
int obj_begin_expexted_at = current_line; int obj_begin_expexted_at = current_line;
bool found_next_before_current_ended = false; 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;
}
/* Opening brace and closing brace */ if(c == '{')
char c = ' '; {
int line_len = strnlen(line_buffer, MAX_LINE_LEN); obj_beginning = ftell(file);
int seek_amount = line_len - type_str_len; c = ' ';
fseek(file, -seek_amount, SEEK_CUR);
while(!feof(file)) while(!feof(file))
{ {
c = fgetc(file); c = fgetc(file);
if(c == '\n') if(c == '\n')
{ {
current_line++; current_line++;
continue; continue;
} }
if(c == '{') /* check if we found opening brace of next object,
{ if this is true then it means that this object is missing
obj_beginning = ftell(file); it's closing brace and we should stop */
c = ' '; if(c == '{')
while(!feof(file)) {
{ found_next_before_current_ended = true;
c = fgetc(file); break;
if(c == '\n') }
{
current_line++; if(c == '}')
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) if(obj_beginning == -1)
{ {
log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at); log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at);
return false; return false;
} }
if(obj_ending == -1) if(obj_ending == -1)
{ {
if(found_next_before_current_ended) 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); log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line);
else else
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 '}' at line %d", filename, current_line);
return false; return false;
} }
memset(obj_str, '\0', 1024); memset(obj_str, '\0', 1024);
memset(line_buffer, '\0', MAX_LINE_LEN); memset(line_buffer, '\0', MAX_LINE_LEN);
fseek(file, obj_beginning, SEEK_SET); fseek(file, obj_beginning, SEEK_SET);
fread(obj_str, obj_ending - obj_beginning, 1, file); 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
@ -229,7 +229,7 @@ struct Parser* parser_load_objects(FILE* file, const char* filename)
while((line = strtok(NULL, "\r\n")) != NULL); while((line = strtok(NULL, "\r\n")) != NULL);
//log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str); //log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str);
} }
return parser; return parser;
} }
@ -240,25 +240,25 @@ int parser_object_type_from_str(const char* str)
if(strncmp(str, "Entity", HASH_MAX_KEY_LEN) == 0) object_type = PO_ENTITY; if(strncmp(str, "Entity", HASH_MAX_KEY_LEN) == 0) object_type = PO_ENTITY;
else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL; else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL;
else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL; else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL;
else if(strncmp(str, "Config", HASH_MAX_KEY_LEN) == 0) object_type = PO_CONFIG; else if(strncmp(str, "Config", HASH_MAX_KEY_LEN) == 0) object_type = PO_CONFIG;
else if(strncmp(str, "Key", HASH_MAX_KEY_LEN) == 0) object_type = PO_KEY; else if(strncmp(str, "Key", HASH_MAX_KEY_LEN) == 0) object_type = PO_KEY;
return object_type; return object_type;
} }
const char* parser_object_type_to_str(int type) const char* parser_object_type_to_str(int type)
{ {
switch(type) switch(type)
{ {
case PO_ENTITY: return "Entity"; case PO_ENTITY: return "Entity";
case PO_MODEL: return "Model"; case PO_MODEL: return "Model";
case PO_MATERIAL: return "Material"; case PO_MATERIAL: return "Material";
case PO_CONFIG: return "Config"; case PO_CONFIG: return "Config";
case PO_KEY: return "Key"; case PO_KEY: return "Key";
case PO_UNKNOWN: return "Unknown"; case PO_UNKNOWN: return "Unknown";
default: return "Unknown"; default: return "Unknown";
} }
} }
void parser_free(struct Parser *parser) void parser_free(struct Parser *parser)
@ -276,68 +276,68 @@ void parser_free(struct Parser *parser)
struct Parser* parser_new(void) struct Parser* parser_new(void)
{ {
struct Parser* parser = NULL; struct Parser* parser = NULL;
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;
} }
struct Parser_Object* parser_object_new(struct Parser* parser, int type) struct Parser_Object* parser_object_new(struct Parser* parser, int type)
{ {
assert(parser); assert(parser);
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();
return object; return object;
} }
bool parser_write_objects(struct Parser* parser, FILE* file, const char* filename) bool parser_write_objects(struct Parser* parser, FILE* file, const char* filename)
{ {
assert(parser); assert(parser);
char value_str[MAX_VALUE_LEN]; char value_str[MAX_VALUE_LEN];
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];
if(object->type == PO_UNKNOWN)
{ {
struct Parser_Object* object = &parser->objects[i]; log_warning("Unknown object type, cannot write to %s", filename);
if(object->type == PO_UNKNOWN) continue;
{ }
log_warning("Unknown object type, cannot write to %s", filename);
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");
counter++;
} }
fprintf(file, "}\n\n");
counter++;
}
log_message("%d objects written to %s", counter, filename); log_message("%d objects written to %s", counter, filename);
return true; return true;
} }

@ -61,73 +61,73 @@ char* str_concat(char* string, const char* str_to_concat)
char* str_replace(char* string, const char* pattern, const char* replacement) char* str_replace(char* string, const char* pattern, const char* replacement)
{ {
int* indices = array_new(int); int* indices = array_new(int);
size_t string_len = strlen(string); size_t string_len = strlen(string);
/* Calculate size of new string and allocate new memory */
size_t pattern_len = strlen(pattern);
size_t replacement_len = strlen(replacement);
int done = 0;
char* remaining_string = string;
while(!done)
{
char* location = strstr(remaining_string, pattern);
if(location)
{
int index = (int)(location - string);
array_push(indices, index, int);
remaining_string = location + pattern_len; /* Find the next occurance in the remaining string */
}
else
{
done = 1;
}
}
/* Calculate size of new string and allocate new memory */ int num_indices = array_len(indices);
size_t pattern_len = strlen(pattern); if(num_indices > 0)
size_t replacement_len = strlen(replacement); {
size_t string_len_without_pattern = string_len - (pattern_len * num_indices);
size_t new_string_len = string_len_without_pattern + (replacement_len * num_indices);
char* new_string = malloc(new_string_len);
int done = 0; if(new_string)
char* remaining_string = string;
while(!done)
{ {
char* location = strstr(remaining_string, pattern); done = 0;
if(location) int count = 0;
int index = indices[count];
int prev_index = 0;
while(!done)
{
char* source_beg = string + prev_index;
char* source_end = string + index;
strncat(new_string, source_beg, (source_end - source_beg));
strcat(new_string, replacement);
count++;
prev_index = index + pattern_len;
if(count == array_len(indices))
{ {
int index = location - string; done = 1;
array_push(indices, index, int); source_beg = string + prev_index;
remaining_string = location + pattern_len; /* Find the next occurance in the remaining string */ strcat(new_string, source_beg);
} }
else else
{ {
done = 1; index = indices[count];
} }
}
free(string);
} }
int num_indices = array_len(indices); array_free(indices);
if(num_indices > 0) return new_string;
{ }
size_t string_len_without_pattern = string_len - (pattern_len * num_indices); else
size_t new_string_len = string_len_without_pattern + (replacement_len * num_indices); {
char* new_string = malloc(new_string_len); return NULL;
}
if(new_string)
{
done = 0;
int count = 0;
int index = indices[count];
unsigned int prev_index = 0;
while(!done)
{
char* source_beg = string + prev_index;
char* source_end = string + index;
strncat(new_string, source_beg, (source_end - source_beg));
strcat(new_string, replacement);
count++;
prev_index = index + pattern_len;
if(count == array_len(indices))
{
done = 1;
source_beg = string + prev_index;
strcat(new_string, source_beg);
}
else
{
index = indices[count];
}
}
free(string);
}
array_free(indices);
return new_string;
}
else
{
return NULL;
}
} }

@ -16,46 +16,46 @@ static struct Hashmap* cvars = NULL;
void config_vars_init(void) void config_vars_init(void)
{ {
cvars = hashmap_new(); cvars = hashmap_new();
/* Initialize with default values incase there is no config file */ /* Initialize with default values incase there is no config file */
hashmap_int_set(cvars, "render_width", 1024); hashmap_int_set(cvars, "render_width", 1024);
hashmap_int_set(cvars, "render_height", 768); hashmap_int_set(cvars, "render_height", 768);
hashmap_int_set(cvars, "fog_mode", 0); hashmap_int_set(cvars, "fog_mode", 0);
hashmap_vec3_setf(cvars, "fog_color", 0.9f, 0.2f, 0.2f); hashmap_vec3_setf(cvars, "fog_color", 0.9f, 0.2f, 0.2f);
hashmap_float_set(cvars, "fog_density", 0.1); hashmap_float_set(cvars, "fog_density", 0.1f);
hashmap_float_set(cvars, "fog_start_dist", 10.f); hashmap_float_set(cvars, "fog_start_dist", 10.f);
hashmap_float_set(cvars, "fog_max_dist", 50.f); hashmap_float_set(cvars, "fog_max_dist", 50.f);
hashmap_vec3_setf(cvars, "ambient_light", 0.1f, 0.1f, 0.1f); hashmap_vec3_setf(cvars, "ambient_light", 0.1f, 0.1f, 0.1f);
hashmap_bool_set(cvars, "msaa_enabled", 1); hashmap_bool_set(cvars, "msaa_enabled", 1);
hashmap_int_set(cvars, "msaa_levels", 4); hashmap_int_set(cvars, "msaa_levels", 4);
hashmap_bool_set(cvars, "debug_draw_enabled", true); hashmap_bool_set(cvars, "debug_draw_enabled", true);
hashmap_bool_set(cvars, "debug_draw_physics", true); hashmap_bool_set(cvars, "debug_draw_physics", true);
hashmap_int_set(cvars, "video_driver_linux", VD_WAYLAND); hashmap_int_set(cvars, "video_driver_linux", VD_WAYLAND);
hashmap_int_set(cvars, "debug_draw_mode", 0); hashmap_int_set(cvars, "debug_draw_mode", 0);
hashmap_vec4_setf(cvars, "debug_draw_color", 1.f, 0.f, 0.f, 1.f); hashmap_vec4_setf(cvars, "debug_draw_color", 1.f, 0.f, 0.f, 1.f);
hashmap_float_set(cvars, "player_move_speed", 10.f); hashmap_float_set(cvars, "player_move_speed", 10.f);
hashmap_float_set(cvars, "player_move_speed_multiplier", 2.f); hashmap_float_set(cvars, "player_move_speed_multiplier", 2.f);
hashmap_float_set(cvars, "player_turn_speed", 5.f); hashmap_float_set(cvars, "player_turn_speed", 5.f);
} }
void config_vars_cleanup(void) void config_vars_cleanup(void)
{ {
hashmap_free(cvars); hashmap_free(cvars);
} }
struct Hashmap* config_vars_get(void) struct Hashmap* config_vars_get(void)
{ {
return cvars; return cvars;
} }
bool config_vars_load(const char* filename, int directory_type) bool config_vars_load(const char* filename, int directory_type)
{ {
FILE* config_file = io_file_open(directory_type, filename, "rb"); FILE* config_file = io_file_open(directory_type, filename, "rb");
if(!config_file) if(!config_file)
{ {
log_error("config:vars_load", "Could not open %s", filename); log_error("config:vars_load", "Could not open %s", filename);
return false; return false;
} }
struct Parser* parser = parser_load_objects(config_file, filename); struct Parser* parser = parser_load_objects(config_file, filename);
if(!parser) if(!parser)
@ -65,74 +65,73 @@ bool config_vars_load(const char* filename, int directory_type)
return false; return false;
} }
bool config_loaded = false; bool config_loaded = false;
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_CONFIG) if(object->type != PO_CONFIG)
{
log_warning("Unexpected config object type %s in %s", parser_object_type_to_str(object->type), filename);
continue;
}
config_loaded = true;
char* key = NULL;
struct Variant* value = NULL;
char variant_str[MAX_VARIANT_STR_LEN];
HASHMAP_FOREACH(object->data, key, value)
{
struct Variant* existing_val = hashmap_value_get(cvars, key);
if(!existing_val)
{
log_warning("Unkown key '%s' in config file %s", key, filename);
continue;
}
variant_copy(existing_val, value);
}
}
if(config_loaded) log_message("Loaded config from %s", filename);
fclose(config_file);
return config_loaded;
}
bool config_vars_save(const char* filename, int directory_type)
{
bool success = false;
FILE* config_file = io_file_open(directory_type, filename, "w");
if(!config_file)
{ {
log_error("config:vars_save", "Failed to open config file %s for writing"); log_warning("Unexpected config object type %s in %s", parser_object_type_to_str(object->type), filename);
return success; continue;
} }
struct Parser* parser = parser_new(); config_loaded = true;
if(!parser) char* key = NULL;
struct Variant* value = NULL;
HASHMAP_FOREACH(object->data, key, value)
{ {
log_error("config_vars:save", "Could not create Parser for %s", filename); struct Variant* existing_val = hashmap_value_get(cvars, key);
fclose(config_file); if(!existing_val)
return false; {
log_warning("Unkown key '%s' in config file %s", key, filename);
continue;
}
variant_copy(existing_val, value);
} }
}
struct Parser_Object* object = parser_object_new(parser, PO_CONFIG); if(config_loaded) log_message("Loaded config from %s", filename);
if(!object) fclose(config_file);
{ return config_loaded;
log_error("config_vars:save", "Could not create Parser_Object for %s", filename); }
parser_free(parser);
fclose(config_file);
return false;
}
hashmap_copy(cvars, object->data); bool config_vars_save(const char* filename, int directory_type)
{
bool success = false;
FILE* config_file = io_file_open(directory_type, filename, "w");
if(!config_file)
{
log_error("config:vars_save", "Failed to open config file %s for writing");
return success;
}
if(!parser_write_objects(parser, config_file, filename)) struct Parser* parser = parser_new();
{ if(!parser)
log_error("config_vars:save", "Failed to write config to '%s'", filename); {
success = false; log_error("config_vars:save", "Could not create Parser for %s", filename);
} fclose(config_file);
return false;
}
struct Parser_Object* object = parser_object_new(parser, PO_CONFIG);
if(!object)
{
log_error("config_vars:save", "Could not create Parser_Object for %s", filename);
parser_free(parser); parser_free(parser);
fclose(config_file); fclose(config_file);
return success; return false;
}
hashmap_copy(cvars, object->data);
if(!parser_write_objects(parser, config_file, filename))
{
log_error("config_vars:save", "Failed to write config to '%s'", filename);
success = false;
}
parser_free(parser);
fclose(config_file);
return success;
} }

@ -6,533 +6,533 @@
static struct static struct
{ {
dWorldID world; dWorldID world;
dSpaceID space; dSpaceID space;
dJointGroupID contact_group; dJointGroupID contact_group;
double step_size; double step_size;
RigidbodyColCB on_collision; RigidbodyColCB on_collision;
RigidbodyMoveCB on_move; RigidbodyMoveCB on_move;
} }
Physics; Physics;
static void physics_near_callback(void* data, dGeomID body1, dGeomID body2); static void physics_near_callback(void* data, dGeomID body1, dGeomID body2);
static void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2); static void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2);
void physics_init(void) void physics_init(void)
{ {
if(dInitODE2(0) == 0) if(dInitODE2(0) == 0)
{ {
log_error("physics:init", "Failed to initialize ode"); log_error("physics:init", "Failed to initialize ode");
return; return;
} }
dAllocateODEDataForThread(dAllocateMaskAll); dAllocateODEDataForThread(dAllocateMaskAll);
Physics.world = dWorldCreate(); Physics.world = dWorldCreate();
if(!Physics.world) if(!Physics.world)
{ {
log_error("physics:init", "Physics world created!"); log_error("physics:init", "Physics world created!");
} }
else else
{ {
log_message("Physics world created"); log_message("Physics world created");
Physics.space = dHashSpaceCreate(0); Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0); Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.016; Physics.step_size = 0.016;
dWorldSetCFM(Physics.world,1e-5); dWorldSetCFM(Physics.world,1e-5);
dWorldSetAutoDisableFlag(Physics.world, 1); dWorldSetAutoDisableFlag(Physics.world, 1);
dWorldSetLinearDamping(Physics.world, 0.00001); dWorldSetLinearDamping(Physics.world, 0.00001);
dWorldSetAngularDamping(Physics.world, 0.005); dWorldSetAngularDamping(Physics.world, 0.005);
dWorldSetMaxAngularSpeed(Physics.world, 200); dWorldSetMaxAngularSpeed(Physics.world, 200);
dWorldSetContactMaxCorrectingVel(Physics.world,0.1); dWorldSetContactMaxCorrectingVel(Physics.world,0.1);
dWorldSetContactSurfaceLayer(Physics.world,0.001); dWorldSetContactSurfaceLayer(Physics.world,0.001);
} }
} }
void physics_cleanup(void) void physics_cleanup(void)
{ {
dJointGroupDestroy(Physics.contact_group); dJointGroupDestroy(Physics.contact_group);
dSpaceDestroy(Physics.space); dSpaceDestroy(Physics.space);
if(Physics.world) if(Physics.world)
{ {
dWorldDestroy(Physics.world); dWorldDestroy(Physics.world);
} }
dCleanupODEAllDataForThread(); dCleanupODEAllDataForThread();
dCloseODE(); dCloseODE();
} }
void physics_step(float delta_time) void physics_step(float delta_time)
{ {
int steps = (int)ceilf(delta_time / Physics.step_size); int steps = (int)ceilf(delta_time / (float)Physics.step_size);
for(int i = 0; i < steps; i++) for(int i = 0; i < steps; i++)
{ {
dSpaceCollide(Physics.space, NULL, physics_near_callback); dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size); dWorldQuickStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group); dJointGroupEmpty(Physics.contact_group);
} }
} }
void physics_gravity_set(float x, float y, float z) void physics_gravity_set(float x, float y, float z)
{ {
dWorldSetGravity(Physics.world, x, y, z); dWorldSetGravity(Physics.world, x, y, z);
} }
void physics_gravity_get(float * x, float * y, float * z) void physics_gravity_get(float * x, float * y, float * z)
{ {
assert(x && y && z); assert(x && y && z);
dVector3 gravity; dVector3 gravity;
dWorldGetGravity(Physics.world, gravity); dWorldGetGravity(Physics.world, gravity);
*x = gravity[0]; *x = (float)gravity[0];
*y = gravity[1]; *y = (float)gravity[1];
*z = gravity[2]; *z = (float)gravity[2];
} }
void physics_body_position_get(Rigidbody body, float * x, float * y, float * z) void physics_body_position_get(Rigidbody body, float * x, float * y, float * z)
{ {
assert(x && y && z); assert(x && y && z);
const dReal* position = dBodyGetPosition(body); const dReal* position = dBodyGetPosition(body);
*x = position[0]; *x = (float)position[0];
*y = position[1]; *y = (float)position[1];
*z = position[2]; *z = (float)position[2];
} }
void physics_body_position_set(Rigidbody body, float x, float y, float z) void physics_body_position_set(Rigidbody body, float x, float y, float z)
{ {
dBodySetPosition(body, x, y, z); dBodySetPosition(body, x, y, z);
dBodyEnable(body); dBodyEnable(body);
} }
void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, float * w) void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, float * w)
{ {
assert(x && y && z && w); assert(x && y && z && w);
const dReal* rotation = dBodyGetQuaternion(body); const dReal* rotation = dBodyGetQuaternion(body);
*x = rotation[1]; *x = (float)rotation[1];
*y = rotation[2]; *y = (float)rotation[2];
*z = rotation[3]; *z = (float)rotation[3];
*w = rotation[0]; *w = (float)rotation[0];
} }
void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w) void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w)
{ {
dReal rotation[4] = { 0.f }; dReal rotation[4] = { 0.f };
rotation[1] = x; rotation[1] = x;
rotation[2] = y; rotation[2] = y;
rotation[3] = z; rotation[3] = z;
rotation[0] = w; rotation[0] = w;
dBodySetQuaternion(body, &rotation[0]); dBodySetQuaternion(body, &rotation[0]);
dBodyEnable(body); dBodyEnable(body);
} }
void physics_near_callback(void* data, dGeomID o1, dGeomID o2) void physics_near_callback(void* data, dGeomID o1, dGeomID o2)
{ {
assert(o1); assert(o1);
assert(o2); assert(o2);
//if(dGeomIsSpace(o1) || dGeomIsSpace(o2)) //if(dGeomIsSpace(o1) || dGeomIsSpace(o2))
//{ //{
// fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2); // fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2);
// // colliding a space with something // // colliding a space with something
// dSpaceCollide2(o1, o2, data, &physics_near_callback); // dSpaceCollide2(o1, o2, data, &physics_near_callback);
// // Note we do not want to test intersections within a space, // // Note we do not want to test intersections within a space,
// // only between spaces. // // only between spaces.
// return; // return;
//} //}
// fprintf(stderr,"testing geoms %p %p\n", o1, o2); // fprintf(stderr,"testing geoms %p %p\n", o1, o2);
// exit without doing anything if the two bodies are connected by a joint // exit without doing anything if the two bodies are connected by a joint
dBodyID b1 = dGeomGetBody(o1); dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2); dBodyID b2 = dGeomGetBody(o2);
if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))
return; return;
if(o1 == o2) if(o1 == o2)
log_message("same body!"); log_message("same body!");
#define MAX_CONTACTS 8 #define MAX_CONTACTS 8
dContact contact[MAX_CONTACTS]; dContact contact[MAX_CONTACTS];
for (int i = 0; i < MAX_CONTACTS; i++) for (int i = 0; i < MAX_CONTACTS; i++)
{ {
//contact[i].surface.mode = dContactBounce | dContactSoftCFM; //contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mode = dContactBounce | dContactSoftCFM; contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity; contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0; contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.1; contact[i].surface.bounce = 0.1;
contact[i].surface.bounce_vel = 0.1; contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 0.01; contact[i].surface.soft_cfm = 0.01;
} }
int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact)); int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact));
if(n > 0) if(n > 0)
{
Physics.on_collision(b1, b2);
for(int i = 0; i < n; i++)
{ {
Physics.on_collision(b1, b2); //contact[i].surface.slip1 = 0.7;
for(int i = 0; i < n; i++) //contact[i].surface.slip2 = 0.7;
{ //contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
//contact[i].surface.slip1 = 0.7; //contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.slip2 = 0.7; //contact[i].surface.soft_erp = 0.96;
//contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2; //contact[i].surface.soft_cfm = 0.04;
//contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.soft_erp = 0.96; dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]);
//contact[i].surface.soft_cfm = 0.04; dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]); dGeomGetBody(contact[i].geom.g2));*/
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
} }
}
} }
Collision_Shape physics_body_cs_get(Rigidbody body) Collision_Shape physics_body_cs_get(Rigidbody body)
{ {
return dBodyGetFirstGeom(body); return dBodyGetFirstGeom(body);
} }
void physics_body_cs_set(Rigidbody body, Collision_Shape shape) void physics_body_cs_set(Rigidbody body, Collision_Shape shape)
{ {
dGeomSetBody(shape, body); dGeomSetBody(shape, body);
} }
Collision_Shape physics_cs_plane_create(float a, float b, float c, float d) Collision_Shape physics_cs_plane_create(float a, float b, float c, float d)
{ {
dGeomID plane = dCreatePlane(Physics.space, a, b, c, d); dGeomID plane = dCreatePlane(Physics.space, a, b, c, d);
return plane; return plane;
} }
void physics_cs_plane_params_set(Collision_Shape shape, float a, float b, float c, float d) void physics_cs_plane_params_set(Collision_Shape shape, float a, float b, float c, float d)
{ {
dGeomPlaneSetParams(shape, a, b, c, d); dGeomPlaneSetParams(shape, a, b, c, d);
} }
void physics_cs_plane_params_get(Collision_Shape shape, float* a, float* b, float* c, float* d) void physics_cs_plane_params_get(Collision_Shape shape, float* a, float* b, float* c, float* d)
{ {
assert(a && b && c && d); assert(a && b && c && d);
*a = *b = *c = *d = 0.f; *a = *b = *c = *d = 0.f;
float result[4] = { 0.f }; float result[4] = { 0.f };
dGeomPlaneGetParams(shape, result); dGeomPlaneGetParams(shape, result);
*a = result[0]; *a = result[0];
*b = result[1]; *b = result[1];
*c = result[2]; *c = result[2];
*d = result[3]; *d = result[3];
} }
Collision_Shape physics_cs_box_create(float x, float y, float z) Collision_Shape physics_cs_box_create(float x, float y, float z)
{ {
dGeomID box = dCreateBox(Physics.space, x, y, z); dGeomID box = dCreateBox(Physics.space, x, y, z);
if(!box) if(!box)
{ {
log_error("physics:cs_box_create", "Failed to create box collision shape"); log_error("physics:cs_box_create", "Failed to create box collision shape");
} }
return box; return box;
} }
int physics_cs_type_get(Collision_Shape shape) int physics_cs_type_get(Collision_Shape shape)
{ {
int geom_class = dGeomGetClass(shape); int geom_class = dGeomGetClass(shape);
switch(geom_class) switch(geom_class)
{ {
case dBoxClass: return CST_BOX; case dBoxClass: return CST_BOX;
case dSphereClass: return CST_SPHERE; case dSphereClass: return CST_SPHERE;
case dCylinderClass: return CST_CYLINDER; case dCylinderClass: return CST_CYLINDER;
case dTriMeshClass: return CST_TRIMESH; case dTriMeshClass: return CST_TRIMESH;
case dPlaneClass: return CST_PLANE; case dPlaneClass: return CST_PLANE;
default: return CST_UNKNOWN; default: return CST_UNKNOWN;
} }
} }
void physics_cs_box_params_get(Collision_Shape shape, float* x, float* y, float* z) void physics_cs_box_params_get(Collision_Shape shape, float* x, float* y, float* z)
{ {
assert(x && y && z); assert(x && y && z);
*x = *y = *z = 0.f; *x = *y = *z = 0.f;
dReal lengths[3] = { 0 }; dReal lengths[3] = { 0 };
dGeomBoxGetLengths(shape, &lengths[0]); dGeomBoxGetLengths(shape, &lengths[0]);
*x = lengths[0]; *x = lengths[0];
*y = lengths[1]; *y = lengths[1];
*z = lengths[2]; *z = lengths[2];
} }
void physics_cs_box_params_set(Collision_Shape shape, float x, float y, float z) void physics_cs_box_params_set(Collision_Shape shape, float x, float y, float z)
{ {
dGeomBoxSetLengths(shape, x, y, z); dGeomBoxSetLengths(shape, x, y, z);
} }
Collision_Shape physics_cs_sphere_create(float radius) Collision_Shape physics_cs_sphere_create(float radius)
{ {
dGeomID sphere = dCreateSphere(Physics.space, radius); dGeomID sphere = dCreateSphere(Physics.space, radius);
if(!sphere) if(!sphere)
{ {
log_error("physics:cs_sphere_create", "Failed to create sphere collision shape"); log_error("physics:cs_sphere_create", "Failed to create sphere collision shape");
} }
return sphere; return sphere;
} }
float physics_cs_sphere_radius_get(Collision_Shape shape) float physics_cs_sphere_radius_get(Collision_Shape shape)
{ {
return dGeomSphereGetRadius(shape); return dGeomSphereGetRadius(shape);
} }
void physics_cs_sphere_radius_set(Collision_Shape shape, float radius) void physics_cs_sphere_radius_set(Collision_Shape shape, float radius)
{ {
dGeomSphereSetRadius(shape, radius); dGeomSphereSetRadius(shape, radius);
} }
Collision_Shape physics_cs_capsule_create(float radius, float length) Collision_Shape physics_cs_capsule_create(float radius, float length)
{ {
dGeomID capsule = dCreateCapsule(Physics.space, radius, length); dGeomID capsule = dCreateCapsule(Physics.space, radius, length);
if(!capsule) if(!capsule)
{ {
log_error("physics:cs_capsule_create", "Failed to create capsule collision shape"); log_error("physics:cs_capsule_create", "Failed to create capsule collision shape");
} }
return capsule; return capsule;
} }
void physics_cs_capsule_params_get(Collision_Shape shape, float* radius, float* length) void physics_cs_capsule_params_get(Collision_Shape shape, float* radius, float* length)
{ {
assert(radius && length); assert(radius && length);
*radius = *length = 0.f; *radius = *length = 0.f;
dGeomCapsuleGetParams(shape, radius, length); dGeomCapsuleGetParams(shape, radius, length);
} }
void physics_cs_capsule_params_set(Collision_Shape shape, float radius, float length) void physics_cs_capsule_params_set(Collision_Shape shape, float radius, float length)
{ {
dGeomCapsuleSetParams(shape, radius, length); dGeomCapsuleSetParams(shape, radius, length);
} }
void physics_box_params_get(Rigidbody body, float* x, float* y, float* z) void physics_box_params_get(Rigidbody body, float* x, float* y, float* z)
{ {
assert(x && y && z); assert(x && y && z);
*x = *y = *z = 0.f; *x = *y = *z = 0.f;
dGeomID box = dBodyGetFirstGeom(body); dGeomID box = dBodyGetFirstGeom(body);
if(box == 0) if(box == 0)
{ {
log_error("physics:box_get_params", "Body has invalid geometry"); log_error("physics:box_get_params", "Body has invalid geometry");
return; return;
} }
float lengths[3] = { 0.f }; float lengths[3] = { 0.f };
dGeomBoxGetLengths(box, lengths); dGeomBoxGetLengths(box, lengths);
*x = lengths[0]; *x = lengths[0];
*y = lengths[1]; *y = lengths[1];
*z = lengths[2]; *z = lengths[2];
} }
void physics_box_params_set(Rigidbody body, float x, float y, float z) void physics_box_params_set(Rigidbody body, float x, float y, float z)
{ {
assert(x && y && z); assert(x && y && z);
dGeomID box = dBodyGetFirstGeom(body); dGeomID box = dBodyGetFirstGeom(body);
if(box == 0) if(box == 0)
{ {
log_error("physics:box_get_params", "Body has invalid geometry"); log_error("physics:box_get_params", "Body has invalid geometry");
return; return;
} }
dGeomBoxSetLengths(box, x, y, z); dGeomBoxSetLengths(box, x, y, z);
} }
Rigidbody physics_body_box_create(float x, float y, float z) Rigidbody physics_body_box_create(float x, float y, float z)
{ {
Rigidbody body = NULL; Rigidbody body = NULL;
Collision_Shape box = physics_cs_box_create(x, y, z); Collision_Shape box = physics_cs_box_create(x, y, z);
if(box) if(box)
{ {
body = dBodyCreate(Physics.world); body = dBodyCreate(Physics.world);
physics_body_cs_set(body, box); physics_body_cs_set(body, box);
dBodySetMovedCallback(body, Physics.on_move); dBodySetMovedCallback(body, Physics.on_move);
} }
return body; return body;
} }
Rigidbody physics_body_sphere_create(float radius) Rigidbody physics_body_sphere_create(float radius)
{ {
Rigidbody body = NULL; Rigidbody body = NULL;
Collision_Shape sphere = physics_cs_sphere_create(radius); Collision_Shape sphere = physics_cs_sphere_create(radius);
if(sphere) if(sphere)
{ {
body = dBodyCreate(Physics.world); body = dBodyCreate(Physics.world);
physics_body_cs_set(body, sphere); physics_body_cs_set(body, sphere);
dBodySetMovedCallback(body, Physics.on_move); dBodySetMovedCallback(body, Physics.on_move);
} }
return body; return body;
} }
Rigidbody physics_body_capsule_create(float radius, float length) Rigidbody physics_body_capsule_create(float radius, float length)
{ {
Rigidbody body = NULL; Rigidbody body = NULL;
Collision_Shape capsule = physics_cs_capsule_create(radius, length); Collision_Shape capsule = physics_cs_capsule_create(radius, length);
if(capsule) if(capsule)
{ {
body = dBodyCreate(Physics.world); body = dBodyCreate(Physics.world);
physics_body_cs_set(body, capsule); physics_body_cs_set(body, capsule);
dBodySetMovedCallback(body, Physics.on_move); dBodySetMovedCallback(body, Physics.on_move);
} }
return body; return body;
} }
void physics_body_force_add(Rigidbody body, float fx, float fy, float fz) void physics_body_force_add(Rigidbody body, float fx, float fy, float fz)
{ {
dBodyAddForce(body, fx, fy, fz); dBodyAddForce(body, fx, fy, fz);
} }
void physics_body_set_moved_callback(RigidbodyMoveCB callback) void physics_body_set_moved_callback(RigidbodyMoveCB callback)
{ {
Physics.on_move = callback; Physics.on_move = callback;
} }
void physics_body_set_collision_callback(RigidbodyColCB callback) void physics_body_set_collision_callback(RigidbodyColCB callback)
{ {
Physics.on_collision = callback; Physics.on_collision = callback;
} }
float physics_body_mass_get(Rigidbody body) float physics_body_mass_get(Rigidbody body)
{ {
return 0.0f; return 0.0f;
} }
void physics_body_mass_set(Rigidbody body, float mass) void physics_body_mass_set(Rigidbody body, float mass)
{ {
/*dMass dmass; /*dMass dmass;
dMassAdjust(&dmass, mass); dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/ dBodySetMass(body, &dmass);*/
} }
void physics_body_data_set(Rigidbody body, void * data) void physics_body_data_set(Rigidbody body, void * data)
{ {
dBodySetData(body, data); dBodySetData(body, data);
} }
void * physics_body_data_get(Rigidbody body) void * physics_body_data_get(Rigidbody body)
{ {
return dBodyGetData(body); return dBodyGetData(body);
} }
void physics_body_kinematic_set(Rigidbody body) void physics_body_kinematic_set(Rigidbody body)
{ {
dBodySetKinematic(body); dBodySetKinematic(body);
} }
void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2) void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2)
{ {
dContact contact; dContact contact;
if(dCollide(geom1, geom2, 1, &contact.geom, sizeof(contact)) == 1) if(dCollide(geom1, geom2, 1, &contact.geom, sizeof(contact)) == 1)
{
struct Raycast_Hit* rayhit = (struct Raycast_Hit*)data;
Rigidbody body = dGeomGetBody(geom2);
if(body)
{
int entity_id = (int)dBodyGetData(body);
if(entity_id != 0) rayhit->entity_id = entity_id;
}
else
{ {
struct Raycast_Hit* rayhit = (struct Raycast_Hit*)data; int entity_id = (int)dGeomGetData(geom2);
Rigidbody body = dGeomGetBody(geom2); if(entity_id != 0) rayhit->entity_id = entity_id;
if(body)
{
int entity_id = (int)dBodyGetData(body);
if(entity_id != 0) rayhit->entity_id = entity_id;
}
else
{
int entity_id = (int)dGeomGetData(geom2);
if(entity_id != 0) rayhit->entity_id = entity_id;
}
} }
}
} }
bool physics_cs_ray_cast(Collision_Shape ray, bool physics_cs_ray_cast(Collision_Shape ray,
struct Raycast_Hit* out_rayhit, struct Raycast_Hit* out_rayhit,
float pos_x, float pos_y, float pos_z, float pos_x, float pos_y, float pos_z,
float dir_x, float dir_y, float dir_z) float dir_x, float dir_y, float dir_z)
{ {
assert(out_rayhit); assert(out_rayhit);
out_rayhit->entity_id = -1; out_rayhit->entity_id = -1;
dGeomRaySet(ray, pos_x, pos_y, pos_z, dir_x, dir_y, dir_z); dGeomRaySet(ray, pos_x, pos_y, pos_z, dir_x, dir_y, dir_z);
dSpaceCollide2(ray, Physics.space, (void*)out_rayhit, &physics_cs_ray_hit_callback); dSpaceCollide2(ray, Physics.space, (void*)out_rayhit, &physics_cs_ray_hit_callback);
return out_rayhit->entity_id == -1 ? false : true; return out_rayhit->entity_id == -1 ? false : true;
} }
void physics_cs_position_get(Collision_Shape shape, float * x, float * y, float * z) void physics_cs_position_get(Collision_Shape shape, float * x, float * y, float * z)
{ {
assert(x && y && z); assert(x && y && z);
if(dGeomGetClass(shape) == dPlaneClass) if(dGeomGetClass(shape) == dPlaneClass)
{ {
*x = 0.f; *x = 0.f;
*y = 0.f; *y = 0.f;
*z = 0.f; *z = 0.f;
return; return;
} }
const dReal* pos = dGeomGetPosition(shape); const dReal* pos = dGeomGetPosition(shape);
*x = pos[0]; *x = pos[0];
*y = pos[1]; *y = pos[1];
*z = pos[2]; *z = pos[2];
} }
void physics_cs_position_set(Collision_Shape shape, float x, float y, float z) void physics_cs_position_set(Collision_Shape shape, float x, float y, float z)
{ {
if(dGeomGetClass(shape) == dPlaneClass) if(dGeomGetClass(shape) == dPlaneClass)
return; return;
dGeomSetPosition(shape, x, y, z); dGeomSetPosition(shape, x, y, z);
} }
void physics_cs_rotation_get(Collision_Shape shape, float* x, float* y, float* z, float* w) void physics_cs_rotation_get(Collision_Shape shape, float* x, float* y, float* z, float* w)
{ {
assert(x && y && z && w); assert(x && y && z && w);
if(dGeomGetClass(shape) == dPlaneClass) if(dGeomGetClass(shape) == dPlaneClass)
{ {
*x = 0.f; *x = 0.f;
*y = 0.f; *y = 0.f;
*z = 0.f; *z = 0.f;
*w = 1.f; *w = 1.f;
return; return;
} }
dReal rotation[4] = { 1, 0, 0, 0 }; dReal rotation[4] = { 1, 0, 0, 0 };
dGeomGetQuaternion(shape, &rotation[0]); dGeomGetQuaternion(shape, &rotation[0]);
*x = rotation[1]; *x = rotation[1];
*y = rotation[2]; *y = rotation[2];
*z = rotation[3]; *z = rotation[3];
*w = rotation[0]; *w = rotation[0];
} }
void physics_cs_rotation_set(Collision_Shape shape, float x, float y, float z, float w) void physics_cs_rotation_set(Collision_Shape shape, float x, float y, float z, float w)
{ {
if(dGeomGetClass(shape) == dPlaneClass) if(dGeomGetClass(shape) == dPlaneClass)
return; return;
dReal rotation[4] = { 0.f }; dReal rotation[4] = { 0.f };
rotation[1] = x; rotation[1] = x;
rotation[2] = y; rotation[2] = y;
rotation[3] = z; rotation[3] = z;
rotation[0] = w; rotation[0] = w;
dGeomSetQuaternion(shape, &rotation[0]); dGeomSetQuaternion(shape, &rotation[0]);
} }
Collision_Shape physics_cs_ray_create(float length, bool first_contact, bool backface_cull) Collision_Shape physics_cs_ray_create(float length, bool first_contact, bool backface_cull)
{ {
dGeomID ray = dCreateRay(Physics.space, length); dGeomID ray = dCreateRay(Physics.space, length);
dGeomRaySetParams(ray, first_contact, backface_cull); dGeomRaySetParams(ray, first_contact, backface_cull);
return ray; return ray;
} }
void physics_body_remove(Rigidbody body) void physics_body_remove(Rigidbody body)
{ {
dGeomID shape = dBodyGetFirstGeom(body); dGeomID shape = dBodyGetFirstGeom(body);
if(shape) if(shape)
physics_cs_remove(shape); physics_cs_remove(shape);
dBodyDestroy(body); dBodyDestroy(body);
} }
void physics_cs_remove(Collision_Shape shape) void physics_cs_remove(Collision_Shape shape)
{ {
dGeomDestroy(shape); dGeomDestroy(shape);
} }
void physics_cs_data_set(Collision_Shape shape, void* data) void physics_cs_data_set(Collision_Shape shape, void* data)
{ {
assert(shape); assert(shape);
dGeomSetData(shape, data); dGeomSetData(shape, data);
} }
void* physics_cs_data_get(Collision_Shape shape) void* physics_cs_data_get(Collision_Shape shape)
{ {
assert(shape); assert(shape);
return dGeomGetData(shape); return dGeomGetData(shape);
} }

@ -13,19 +13,19 @@
struct Window struct Window
{ {
void* sdl_window; void* sdl_window;
SDL_GLContext gl_context; SDL_GLContext gl_context;
int is_fullscreen; int is_fullscreen;
}; };
struct Platform_State struct Platform_State
{ {
Keyboard_Event_Func on_keyboard_func; Keyboard_Event_Func on_keyboard_func;
Mousebutton_Event_Func on_mousebutton_func; Mousebutton_Event_Func on_mousebutton_func;
Mousemotion_Event_Func on_mousemotion_func; Mousemotion_Event_Func on_mousemotion_func;
Mousewheel_Event_Func on_mousewheel_func; Mousewheel_Event_Func on_mousewheel_func;
Windowresize_Event_Func on_windowresize_func; Windowresize_Event_Func on_windowresize_func;
Textinput_Event_Func on_textinput_func; Textinput_Event_Func on_textinput_func;
}; };
/* TODO: Find a better way to handle internal state */ /* TODO: Find a better way to handle internal state */
@ -33,176 +33,176 @@ static struct Platform_State* platform_state = NULL;
struct Window* window_create(const char* title, int width, int height, int msaa, int msaa_levels) struct Window* window_create(const char* title, int width, int height, int msaa, int msaa_levels)
{ {
struct Window* new_window = NULL; struct Window* new_window = NULL;
if(!new_window)
{
new_window = malloc(sizeof(*new_window));
if(!new_window) if(!new_window)
{ {
new_window = malloc(sizeof(*new_window)); log_error("window_create", "Out of memory");
if(!new_window) return NULL;
{
log_error("window_create", "Out of memory");
return NULL;
}
new_window->sdl_window = NULL;
new_window->gl_context = NULL;
new_window->is_fullscreen = 0;
} }
new_window->sdl_window = NULL;
new_window->gl_context = NULL;
new_window->is_fullscreen = 0;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
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);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
#ifdef GL_DEBUG_CONTEXT #ifdef GL_DEBUG_CONTEXT
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;
}
new_window->gl_context = gl_context;
SDL_Window* current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext current_context = SDL_GL_GetCurrentContext();
SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context);
SDL_GL_SetSwapInterval(1); /* 0: Vsync disabled, 1: Vsync enabled*/
if(current_window && current_context) SDL_GL_MakeCurrent(current_window, current_context);
int major = 0, minor = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
log_message("Window created and initialized with opengl core context %d.%d", major, minor);
return new_window; return new_window;
}
new_window->gl_context = gl_context;
SDL_Window* current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext current_context = SDL_GL_GetCurrentContext();
SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context);
SDL_GL_SetSwapInterval(1); /* 0: Vsync disabled, 1: Vsync enabled*/
if(current_window && current_context) SDL_GL_MakeCurrent(current_window, current_context);
int major = 0, minor = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
log_message("Window created and initialized with opengl core context %d.%d", major, minor);
return new_window;
} }
int window_fullscreen_set(struct Window* window, int fullscreen) int window_fullscreen_set(struct Window* window, int fullscreen)
{ {
int success = 0; int success = 0;
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;
} }
void window_make_context_current(struct Window* window) void window_make_context_current(struct Window* window)
{ {
SDL_GL_MakeCurrent((SDL_Window*)window->sdl_window, window->gl_context); SDL_GL_MakeCurrent((SDL_Window*)window->sdl_window, window->gl_context);
} }
void window_show(struct Window* window) void window_show(struct Window* window)
{ {
SDL_ShowWindow((SDL_Window*)window->sdl_window); SDL_ShowWindow((SDL_Window*)window->sdl_window);
} }
void window_hide(struct Window* window) void window_hide(struct Window* window)
{ {
SDL_HideWindow((SDL_Window*)window->sdl_window); SDL_HideWindow((SDL_Window*)window->sdl_window);
} }
void window_raise(struct Window* window) void window_raise(struct Window* window)
{ {
SDL_RaiseWindow((SDL_Window*)window->sdl_window); SDL_RaiseWindow((SDL_Window*)window->sdl_window);
} }
void window_destroy(struct Window* window) void window_destroy(struct Window* window)
{ {
if(window->gl_context) SDL_GL_DeleteContext(window->gl_context); if(window->gl_context) SDL_GL_DeleteContext(window->gl_context);
SDL_DestroyWindow((SDL_Window*)window->sdl_window); SDL_DestroyWindow((SDL_Window*)window->sdl_window);
} }
void window_set_size(struct Window* window, int width, int height) void window_set_size(struct Window* window, int width, int height)
{ {
SDL_SetWindowSize((SDL_Window*)window->sdl_window, width, height); SDL_SetWindowSize((SDL_Window*)window->sdl_window, width, height);
} }
void window_get_size(struct Window* window, int* out_width, int* out_height) void window_get_size(struct Window* window, int* out_width, int* out_height)
{ {
SDL_GetWindowSize((SDL_Window*)window->sdl_window, out_width, out_height); SDL_GetWindowSize((SDL_Window*)window->sdl_window, out_width, out_height);
} }
void window_get_drawable_size(struct Window* window, int* out_width, int* out_height) void window_get_drawable_size(struct Window* window, int* out_width, int* out_height)
{ {
SDL_GL_GetDrawableSize((SDL_Window*)window->sdl_window, out_width, out_height); SDL_GL_GetDrawableSize((SDL_Window*)window->sdl_window, out_width, out_height);
} }
void window_swap_buffers(struct Window* window) void window_swap_buffers(struct Window* window)
{ {
SDL_GL_SwapWindow(window->sdl_window); SDL_GL_SwapWindow(window->sdl_window);
} }
bool platform_init(void) bool platform_init(void)
{ {
bool success = true; bool success = true;
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
{
platform_state = malloc(sizeof(*platform_state));
if(!platform_state)
{
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0)
log_to_stdout("platform_init", "Could not create platform state, out of memory");
success = false;
} }
else else
{ {
platform_state = malloc(sizeof(*platform_state)); platform_state->on_keyboard_func = NULL;
if(!platform_state) platform_state->on_mousebutton_func = NULL;
{ platform_state->on_mousemotion_func = NULL;
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0) platform_state->on_mousewheel_func = NULL;
log_to_stdout("platform_init", "Could not create platform state, out of memory"); platform_state->on_textinput_func = NULL;
success = false; platform_state->on_windowresize_func = NULL;
}
else
{
platform_state->on_keyboard_func = NULL;
platform_state->on_mousebutton_func = NULL;
platform_state->on_mousemotion_func = NULL;
platform_state->on_mousewheel_func = NULL;
platform_state->on_textinput_func = NULL;
platform_state->on_windowresize_func = NULL;
}
} }
return success; }
return success;
} }
bool platform_init_video() bool platform_init_video()
@ -234,228 +234,228 @@ bool platform_init_video()
void platform_cleanup(void) void platform_cleanup(void)
{ {
if(platform_state) free(platform_state); if(platform_state) free(platform_state);
platform_state = NULL; platform_state = NULL;
SDL_VideoQuit(); SDL_VideoQuit();
SDL_Quit(); SDL_Quit();
} }
void platform_poll_events(bool* out_quit) 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)
{
case SDL_QUIT:
*out_quit = 1;
break;
case SDL_KEYDOWN: case SDL_KEYUP:
{
int scancode = event.key.keysym.scancode;
int key = event.key.keysym.sym;
int state = event.key.state;
int repeat = event.key.repeat;
int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0;
int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0;
int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0;
platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt);
//log_message("Key name : %s", SDL_GetKeyName(key));
break;
}
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
{
int button = event.button.button;
int state = event.button.state;
int num_clicks = event.button.clicks;
int x = event.button.x;
int y = event.button.y;
platform_state->on_mousebutton_func(button, state, x, y, num_clicks);
break;
}
case SDL_MOUSEMOTION:
{ {
switch(event.type) int xrel = event.motion.xrel;
{ int yrel = event.motion.yrel;
case SDL_QUIT: int x = event.motion.x;
*out_quit = 1; int y = event.motion.y;
break; platform_state->on_mousemotion_func(x, y, xrel, yrel);
case SDL_KEYDOWN: case SDL_KEYUP: break;
{
int scancode = event.key.keysym.scancode;
int key = event.key.keysym.sym;
int state = event.key.state;
int repeat = event.key.repeat;
int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0;
int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0;
int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0;
platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt);
//log_message("Key name : %s", SDL_GetKeyName(key));
break;
}
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
{
int button = event.button.button;
int state = event.button.state;
int num_clicks = event.button.clicks;
int x = event.button.x;
int y = event.button.y;
platform_state->on_mousebutton_func(button, state, x, y, num_clicks);
break;
}
case SDL_MOUSEMOTION:
{
int xrel = event.motion.xrel;
int yrel = event.motion.yrel;
int x = event.motion.x;
int y = event.motion.y;
platform_state->on_mousemotion_func(x, y, xrel, yrel);
break;
}
case SDL_MOUSEWHEEL:
{
int x = event.wheel.x;
int y = event.wheel.y;
platform_state->on_mousewheel_func(x, y);
break;
}
case SDL_TEXTINPUT:
{
platform_state->on_textinput_func(event.text.text);
break;
}
case SDL_WINDOWEVENT:
{
if(event.window.event == SDL_WINDOWEVENT_RESIZED)
{
platform_state->on_windowresize_func(event.window.data1, event.window.data2);
}
}
break;
}
} }
case SDL_MOUSEWHEEL:
{
int x = event.wheel.x;
int y = event.wheel.y;
platform_state->on_mousewheel_func(x, y);
break;
}
case SDL_TEXTINPUT:
{
platform_state->on_textinput_func(event.text.text);
break;
}
case SDL_WINDOWEVENT:
{
if(event.window.event == SDL_WINDOWEVENT_RESIZED)
{
platform_state->on_windowresize_func(event.window.data1, event.window.data2);
}
}
break;
}
}
} }
void platform_keyboard_callback_set(Keyboard_Event_Func func) void platform_keyboard_callback_set(Keyboard_Event_Func func)
{ {
platform_state->on_keyboard_func = func; platform_state->on_keyboard_func = func;
} }
void platform_mousebutton_callback_set(Mousebutton_Event_Func func) void platform_mousebutton_callback_set(Mousebutton_Event_Func func)
{ {
platform_state->on_mousebutton_func = func; platform_state->on_mousebutton_func = func;
} }
void platform_mousemotion_callback_set(Mousemotion_Event_Func func) void platform_mousemotion_callback_set(Mousemotion_Event_Func func)
{ {
platform_state->on_mousemotion_func = func; platform_state->on_mousemotion_func = func;
} }
void platform_mousewheel_callback_set(Mousewheel_Event_Func func) void platform_mousewheel_callback_set(Mousewheel_Event_Func func)
{ {
platform_state->on_mousewheel_func = func; platform_state->on_mousewheel_func = func;
} }
void platform_textinput_callback_set(Textinput_Event_Func func) void platform_textinput_callback_set(Textinput_Event_Func func)
{ {
platform_state->on_textinput_func = func; platform_state->on_textinput_func = func;
} }
void platform_windowresize_callback_set(Windowresize_Event_Func func) void platform_windowresize_callback_set(Windowresize_Event_Func func)
{ {
platform_state->on_windowresize_func = func; platform_state->on_windowresize_func = func;
} }
int platform_is_key_pressed(int key) int platform_is_key_pressed(int key)
{ {
/* Returns 1 if key is pressed, 0 otherwise */ /* Returns 1 if key is pressed, 0 otherwise */
const Uint8* keyboard_state = SDL_GetKeyboardState(NULL); const Uint8* keyboard_state = SDL_GetKeyboardState(NULL);
return keyboard_state[SDL_GetScancodeFromKey(key)]; return keyboard_state[SDL_GetScancodeFromKey(key)];
} }
int platform_mousebutton_state_get(uint button) int platform_mousebutton_state_get(uint button)
{ {
int pressed = 0; int pressed = 0;
uint32 current_button_state = SDL_GetMouseState(NULL, NULL); uint32 current_button_state = SDL_GetMouseState(NULL, NULL);
if((current_button_state & SDL_BUTTON(button))) pressed = 1; if((current_button_state & SDL_BUTTON(button))) pressed = 1;
return pressed; return pressed;
} }
void platform_mouse_position_get(int* x, int* y) void platform_mouse_position_get(int* x, int* y)
{ {
SDL_GetMouseState(x, y); SDL_GetMouseState(x, y);
} }
void platform_mouse_position_set(struct Window* window, int x, int y) void platform_mouse_position_set(struct Window* window, int x, int y)
{ {
SDL_WarpMouseInWindow(window->sdl_window, x, y); SDL_WarpMouseInWindow(window->sdl_window, x, y);
} }
void platform_mouse_global_position_set(int x, int y) void platform_mouse_global_position_set(int x, int y)
{ {
SDL_WarpMouseGlobal(x, y); SDL_WarpMouseGlobal(x, y);
} }
void platform_mouse_relative_mode_set(int relative_mode) void platform_mouse_relative_mode_set(int relative_mode)
{ {
SDL_SetRelativeMouseMode(relative_mode ? SDL_TRUE : SDL_FALSE); SDL_SetRelativeMouseMode(relative_mode ? SDL_TRUE : SDL_FALSE);
} }
int platform_mouse_relative_mode_get(void) int platform_mouse_relative_mode_get(void)
{ {
return SDL_GetRelativeMouseMode() == SDL_TRUE ? 1 : 0; return SDL_GetRelativeMouseMode() == SDL_TRUE ? 1 : 0;
} }
uint32 platform_ticks_get(void) uint32 platform_ticks_get(void)
{ {
return SDL_GetTicks(); return SDL_GetTicks();
} }
void platform_mouse_delta_get(int* x, int* y) void platform_mouse_delta_get(int* x, int* y)
{ {
SDL_GetRelativeMouseState(x, y); SDL_GetRelativeMouseState(x, y);
} }
char* platform_install_directory_get(void) char* platform_install_directory_get(void)
{ {
char* returned_path = SDL_GetBasePath(); char* returned_path = SDL_GetBasePath();
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;
} }
void platform_clipboard_text_set(const char* text) void platform_clipboard_text_set(const char* text)
{ {
SDL_SetClipboardText(text); SDL_SetClipboardText(text);
} }
char* platform_clipboard_text_get(void) char* platform_clipboard_text_get(void)
{ {
char* returned_text = SDL_GetClipboardText(); char* returned_text = SDL_GetClipboardText();
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;
} }
int platform_key_from_name(const char* key_name) int platform_key_from_name(const char* key_name)
{ {
if(!key_name || strlen(key_name) == 0) return SDLK_UNKNOWN; if(!key_name || strlen(key_name) == 0) return SDLK_UNKNOWN;
/* Remove leading/trailing spaces, preserve spaces in-between */ /* Remove leading/trailing spaces, preserve spaces in-between */
#define max_name_len 30 #define max_name_len 30
char trimmed_key_name[max_name_len] = {'\0'}; char trimmed_key_name[max_name_len] = {'\0'};
int start = 0; int start = 0;
while(isspace(key_name[start]) != 0) start++; while(isspace(key_name[start]) != 0) start++;
int end = strlen(key_name) - 1; size_t end = strlen(key_name) - 1;
while(isspace(key_name[end]) != 0) end--; while(isspace(key_name[end]) != 0) end--;
strncpy(trimmed_key_name, &key_name[start], (end - start) + 1); strncpy(trimmed_key_name, &key_name[start], (end - start) + 1);
int key = SDL_GetKeyFromName(trimmed_key_name); int key = SDL_GetKeyFromName(trimmed_key_name);
/*if(key == SDLK_UNKNOWN) /*if(key == SDLK_UNKNOWN)
log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError());*/ log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError());*/
return key; return key;
} }
const char* platform_key_name_get(int key) const char* platform_key_name_get(int key)
{ {
if(key < 0) return "SDLK_UNKNOWN"; if(key < 0) return "SDLK_UNKNOWN";
return SDL_GetKeyName(key); return SDL_GetKeyName(key);
} }
char* platform_user_directory_get(const char* organization, const char* application) char* platform_user_directory_get(const char* organization, const char* application)
{ {
char* user_directory = NULL; char* user_directory = NULL;
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
{ {
log_to_stdout("ERR(platform:user_directory_get) Error getting user directory, %s", SDL_GetError()); log_to_stdout("ERR(platform:user_directory_get) Error getting user directory, %s", SDL_GetError());
} }
return user_directory; return user_directory;
} }
void* platform_load_library(const char *name) void* platform_load_library(const char *name)
@ -469,7 +469,7 @@ void* platform_load_library(const char *name)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
snprintf(lib_name, MAX_LIB_NAME_LEN, "%s.dll", name); snprintf(lib_name, MAX_LIB_NAME_LEN, "%s.dll", name);
#elif defined(__MING32__) || defined(__MINGW64__) #elif defined(__MING32__) || defined(__MINGW64__)
snprintf(lib_name, MAX_LIB_NAME_LEN, "./%s.dll", name); snprintf(lib_name, MAX_LIB_NAME_LEN, "./%s.dll", name);
#endif #endif
void* lib_handle = SDL_LoadObject(lib_name); void* lib_handle = SDL_LoadObject(lib_name);
if(!lib_handle) log_error("platform:load_library", "Failed to load library '%s', SDL : (%s)", lib_name, SDL_GetError()); if(!lib_handle) log_error("platform:load_library", "Failed to load library '%s', SDL : (%s)", lib_name, SDL_GetError());

@ -21,224 +21,224 @@ static void update_frustum(struct Camera* camera);
void camera_reset(struct Camera* camera) void camera_reset(struct Camera* camera)
{ {
if(camera->fbo != -1) framebuffer_remove(camera->fbo); if(camera->fbo != -1) framebuffer_remove(camera->fbo);
if(camera->render_tex != -1) texture_remove(camera->render_tex); if(camera->render_tex != -1) texture_remove(camera->render_tex);
if(camera->depth_tex != -1) texture_remove(camera->depth_tex); if(camera->depth_tex != -1) texture_remove(camera->depth_tex);
camera->fbo = camera->render_tex = camera->depth_tex = -1; camera->fbo = camera->render_tex = camera->depth_tex = -1;
camera->ortho = camera->resizeable = false; camera->ortho = camera->resizeable = false;
camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f; camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f;
mat4_identity(&camera->view_mat); mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat); mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++) for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0); vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0);
} }
void camera_init(struct Camera* camera, int width, int height) void camera_init(struct Camera* camera, int width, int height)
{ {
camera->base.type = ET_CAMERA; camera->base.type = ET_CAMERA;
camera->fbo = -1; camera->fbo = -1;
camera->render_tex = -1; camera->render_tex = -1;
camera->depth_tex = -1; camera->depth_tex = -1;
camera->farz = 1000.f; camera->farz = 1000.f;
camera->nearz = 0.1f; camera->nearz = 0.1f;
camera->fov = 60.f; camera->fov = 60.f;
camera->ortho = false; camera->ortho = false;
camera->resizeable = true; camera->resizeable = true;
camera->zoom = 1.f; camera->zoom = 1.f;
float aspect_ratio = (float)width / (float)height; float aspect_ratio = (float)width / (float)height;
camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio;
mat4_identity(&camera->view_mat); mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat); mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++) for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(camera); camera_update_view(camera);
camera_update_proj(camera); camera_update_proj(camera);
vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f); vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f);
} }
void camera_update_view_proj(struct Camera* camera) void camera_update_view_proj(struct Camera* camera)
{ {
mat4_identity(&camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat); mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat);
update_frustum(camera); update_frustum(camera);
} }
void camera_update_view(struct Camera* camera) void camera_update_view(struct Camera* camera)
{ {
vec3 lookat = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f};
vec3 up = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f};
vec3 position = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(&camera->base, &lookat); transform_get_absolute_lookat(&camera->base, &lookat);
transform_get_absolute_up(&camera->base, &up); transform_get_absolute_up(&camera->base, &up);
transform_get_absolute_position(&camera->base, &position); transform_get_absolute_position(&camera->base, &position);
mat4_lookat(&camera->view_mat, &position, &lookat, &up); mat4_lookat(&camera->view_mat, &position, &lookat, &up);
camera_update_view_proj(&camera->base); camera_update_view_proj(camera);
} }
void camera_update_proj(struct Camera* camera) void camera_update_proj(struct Camera* camera)
{ {
if(!camera->ortho) if(!camera->ortho)
{ {
mat4_perspective(&camera->proj_mat, mat4_perspective(&camera->proj_mat,
camera->fov / camera->zoom, camera->fov / camera->zoom,
camera->aspect_ratio, camera->aspect_ratio,
camera->nearz, camera->nearz,
camera->farz); camera->farz);
} }
else else
{ {
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(&camera->proj_mat, mat4_ortho(&camera->proj_mat,
-width / camera->zoom, -width / camera->zoom,
width / camera->zoom, width / camera->zoom,
height / camera->zoom, height / camera->zoom,
-height / camera->zoom, -height / camera->zoom,
camera->nearz, camera->nearz,
camera->farz); camera->farz);
} }
camera_update_view_proj(camera); camera_update_view_proj(camera);
} }
void camera_attach_fbo(struct Camera* camera, void camera_attach_fbo(struct Camera* camera,
int width, int width,
int height, int height,
bool has_depth, bool has_depth,
bool has_color, bool has_color,
bool resizeable) bool resizeable)
{ {
assert(width > 0 && height > 0); assert(width > 0 && height > 0);
if(camera->fbo != -1) if(camera->fbo != -1)
{
log_error("camera:attach_fbo", "Camera already has fbo attached!");
return;
}
camera->fbo = framebuffer_create(width, height, has_depth, 0, resizeable);
if(camera->fbo > -1)
{
if(has_color)
{ {
log_error("camera:attach_fbo", "Camera already has fbo attached!"); camera->render_tex = texture_create(NULL,
return; TU_DIFFUSE,
width, height,
GL_RGBA,
GL_RGBA8,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(camera->render_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(camera->render_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
framebuffer_texture_set(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0);
} }
camera->fbo = framebuffer_create(width, height, has_depth, 0, resizeable);
if(camera->fbo > -1) if(has_depth)
{
if(has_color)
{
camera->render_tex = texture_create(NULL,
TU_DIFFUSE,
width, height,
GL_RGBA,
GL_RGBA8,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(camera->render_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(camera->render_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(camera->render_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
framebuffer_texture_set(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0);
}
if(has_depth)
{
camera->depth_tex = texture_create(NULL,
TU_SHADOWMAP1,
width, height,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(camera->depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(camera->depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
framebuffer_texture_set(camera->fbo, camera->depth_tex, FA_DEPTH_ATTACHMENT);
}
}
else
{ {
log_error("camera:attach_fbo", "Framebuffer not attached to camera!"); camera->depth_tex = texture_create(NULL,
TU_SHADOWMAP1,
width, height,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT,
GL_UNSIGNED_BYTE,
NULL);
texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(camera->depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(camera->depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(camera->depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
texture_set_param(camera->depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
framebuffer_texture_set(camera->fbo, camera->depth_tex, FA_DEPTH_ATTACHMENT);
} }
}
else
{
log_error("camera:attach_fbo", "Framebuffer not attached to camera!");
}
} }
static void update_frustum(struct Camera* camera) static void update_frustum(struct Camera* camera)
{ {
assert(camera); assert(camera);
float* mvp = &camera->view_proj_mat.mat[0]; float* mvp = &camera->view_proj_mat.mat[0];
camera->frustum[FP_LEFT].x = mvp[3] + mvp[0]; camera->frustum[FP_LEFT].x = mvp[3] + mvp[0];
camera->frustum[FP_LEFT].y = mvp[7] + mvp[4]; camera->frustum[FP_LEFT].y = mvp[7] + mvp[4];
camera->frustum[FP_LEFT].z = mvp[11] + mvp[2]; camera->frustum[FP_LEFT].z = mvp[11] + mvp[2];
camera->frustum[FP_LEFT].w = mvp[15] + mvp[12]; camera->frustum[FP_LEFT].w = mvp[15] + mvp[12];
camera->frustum[FP_RIGHT].x = mvp[3] - mvp[0]; camera->frustum[FP_RIGHT].x = mvp[3] - mvp[0];
camera->frustum[FP_RIGHT].y = mvp[7] - mvp[4]; camera->frustum[FP_RIGHT].y = mvp[7] - mvp[4];
camera->frustum[FP_RIGHT].z = mvp[11] - mvp[8]; camera->frustum[FP_RIGHT].z = mvp[11] - mvp[8];
camera->frustum[FP_RIGHT].w = mvp[15] - mvp[12]; camera->frustum[FP_RIGHT].w = mvp[15] - mvp[12];
camera->frustum[FP_BOTTOM].x = mvp[3] + mvp[1]; camera->frustum[FP_BOTTOM].x = mvp[3] + mvp[1];
camera->frustum[FP_BOTTOM].y = mvp[11] + mvp[5]; camera->frustum[FP_BOTTOM].y = mvp[11] + mvp[5];
camera->frustum[FP_BOTTOM].z = mvp[11] + mvp[9]; camera->frustum[FP_BOTTOM].z = mvp[11] + mvp[9];
camera->frustum[FP_BOTTOM].w = mvp[15] + mvp[13]; camera->frustum[FP_BOTTOM].w = mvp[15] + mvp[13];
camera->frustum[FP_TOP].x = mvp[3] - mvp[1]; camera->frustum[FP_TOP].x = mvp[3] - mvp[1];
camera->frustum[FP_TOP].y = mvp[7] - mvp[5]; camera->frustum[FP_TOP].y = mvp[7] - mvp[5];
camera->frustum[FP_TOP].z = mvp[11] - mvp[9]; camera->frustum[FP_TOP].z = mvp[11] - mvp[9];
camera->frustum[FP_TOP].w = mvp[15] - mvp[13]; camera->frustum[FP_TOP].w = mvp[15] - mvp[13];
camera->frustum[FP_NEAR].x = mvp[3] + mvp[2]; camera->frustum[FP_NEAR].x = mvp[3] + mvp[2];
camera->frustum[FP_NEAR].y = mvp[7] + mvp[6]; camera->frustum[FP_NEAR].y = mvp[7] + mvp[6];
camera->frustum[FP_NEAR].z = mvp[11] + mvp[10]; camera->frustum[FP_NEAR].z = mvp[11] + mvp[10];
camera->frustum[FP_NEAR].w = mvp[15] + mvp[14]; camera->frustum[FP_NEAR].w = mvp[15] + mvp[14];
camera->frustum[FP_FAR].x = mvp[3] - mvp[2]; camera->frustum[FP_FAR].x = mvp[3] - mvp[2];
camera->frustum[FP_FAR].y = mvp[7] - mvp[6]; camera->frustum[FP_FAR].y = mvp[7] - mvp[6];
camera->frustum[FP_FAR].z = mvp[11] - mvp[10]; camera->frustum[FP_FAR].z = mvp[11] - mvp[10];
camera->frustum[FP_FAR].w = mvp[15] - mvp[14]; camera->frustum[FP_FAR].w = mvp[15] - mvp[14];
for(int i = 0; i < FP_NUM_PLANES; i++) for(int i = 0; i < FP_NUM_PLANES; i++)
{ {
vec3 plane_xyz = {camera->frustum[i].x, camera->frustum[i].y, camera->frustum[i].z}; vec3 plane_xyz = {camera->frustum[i].x, camera->frustum[i].y, camera->frustum[i].z};
float length = fabsf(vec3_len(&plane_xyz)); float length = fabsf(vec3_len(&plane_xyz));
vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length)); vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length));
} }
} }
struct Ray camera_screen_coord_to_ray(struct Camera* camera, int mouse_x, int mouse_y) struct Ray camera_screen_coord_to_ray(struct Camera* camera, int mouse_x, int mouse_y)
{ {
struct Ray ray; struct Ray ray;
int win_width = 0, win_height = 0; int win_width = 0, win_height = 0;
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &win_width, &win_height); platform->window.get_size(game_state->window, &win_width, &win_height);
float normalized_x = (2.f * (float)mouse_x) / (float)win_width - 1.f; float normalized_x = (2.f * (float)mouse_x) / (float)win_width - 1.f;
float normalized_y = 1.f - (2.f * (float)mouse_y) / (float)win_height; float normalized_y = 1.f - (2.f * (float)mouse_y) / (float)win_height;
vec3 near_point = {0.f}; vec3 near_point = {0.f};
vec3 far_point = {0.f}; vec3 far_point = {0.f};
mat4 inverse_view_proj_mat; mat4 inverse_view_proj_mat;
mat4_identity(&inverse_view_proj_mat); mat4_identity(&inverse_view_proj_mat);
mat4_inverse(&inverse_view_proj_mat, &camera->view_proj_mat); mat4_inverse(&inverse_view_proj_mat, &camera->view_proj_mat);
//Project the near point //Project the near point
quat rot_near = {normalized_x, normalized_y, 0.f, 1.f}; quat rot_near = {normalized_x, normalized_y, 0.f, 1.f};
vec4_mul_mat4(&rot_near, &rot_near, &inverse_view_proj_mat); quat_mul_mat4(&rot_near, &rot_near, &inverse_view_proj_mat);
near_point.x = rot_near.x / rot_near.w; near_point.x = rot_near.x / rot_near.w;
near_point.y = rot_near.y / rot_near.w; near_point.y = rot_near.y / rot_near.w;
near_point.z = rot_near.z / rot_near.w; near_point.z = rot_near.z / rot_near.w;
//Project far point //Project far point
quat rot_far = {normalized_x, normalized_y, 1.f, 1.f}; quat rot_far = {normalized_x, normalized_y, 1.f, 1.f};
vec4_mul_mat4(&rot_far, &rot_far, &inverse_view_proj_mat); quat_mul_mat4(&rot_far, &rot_far, &inverse_view_proj_mat);
far_point.x = rot_far.x / rot_far.w; far_point.x = rot_far.x / rot_far.w;
far_point.y = rot_far.y / rot_far.w; far_point.y = rot_far.y / rot_far.w;
far_point.z = rot_far.z / rot_far.w; far_point.z = rot_far.z / rot_far.w;
vec3_sub(&ray.direction, &far_point, &near_point); vec3_sub(&ray.direction, &far_point, &near_point);
vec3_norm(&ray.direction, &ray.direction); vec3_norm(&ray.direction, &ray.direction);
transform_get_absolute_position(&camera->base, &ray.origin); transform_get_absolute_position(&camera->base, &ray.origin);
return ray; return ray;
} }

@ -14,82 +14,82 @@ static int console_filter(const struct nk_text_edit *box, nk_rune unicode);
void console_init(struct Console* console) void console_init(struct Console* console)
{ {
assert(console); assert(console);
console_message_color[CMT_MESSAGE] = nk_rgb(255, 255, 255); console_message_color[CMT_MESSAGE] = nk_rgb(255, 255, 255);
console_message_color[CMT_WARNING] = nk_rgb(255, 255, 0); console_message_color[CMT_WARNING] = nk_rgb(255, 255, 0);
console_message_color[CMT_ERROR] = nk_rgb(255, 0, 0); console_message_color[CMT_ERROR] = nk_rgb(255, 0, 0);
console_message_color[CMT_COMMAND] = nk_rgb(114, 173, 224); console_message_color[CMT_COMMAND] = nk_rgb(114, 173, 224);
console_message_color[CMT_NONE] = nk_rgb(255, 0, 255); console_message_color[CMT_NONE] = nk_rgb(255, 0, 255);
console->visible = false; console->visible = false;
console->scroll_to_bottom = true; console->scroll_to_bottom = true;
console->text_region_height = 22.f; console->text_region_height = 22.f;
console->line_height = 20.f; console->line_height = 20.f;
console->current_message_index = -1; console->current_message_index = -1;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN); memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
for(int i = 0; i < MAX_CONSOLE_MESSAGES; i++) for(int i = 0; i < MAX_CONSOLE_MESSAGES; i++)
{ {
memset(console->console_messages[i].message, '\0', MAX_CONSOLE_MESSAGE_LEN); memset(console->console_messages[i].message, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->console_messages[i].type = CMT_NONE; console->console_messages[i].type = CMT_NONE;
} }
} }
void console_toggle(struct Console* console) void console_toggle(struct Console* console)
{ {
if(!console->visible) console->scroll_to_bottom = true; console->visible = !console->visible;
console->visible = !console->visible; if(console->visible) console->scroll_to_bottom = true;
} }
void console_update(struct Console* console, struct Gui_State* gui_state, float dt) void console_update(struct Console* console, struct Gui_State* gui_state, float dt)
{ {
if(!console->visible) return; if(!console->visible) return;
struct nk_context* context = &gui_state->context;
struct Game_State* game_state = game_state_get();
struct nk_context* context = &gui_state->context; int win_width = 0, win_height = 0;
struct Game_State* game_state = game_state_get(); platform->window.get_drawable_size(game_state->window, &win_width, &win_height);
int half_height = win_height / 2;
int win_width = 0, win_height = 0; if(nk_begin_titled(context, "Console", "Console", nk_recti(0, 0, win_width, half_height), NK_WINDOW_SCROLL_AUTO_HIDE))
platform->window.get_drawable_size(game_state->window, &win_width, &win_height); {
int half_height = win_height / 2; nk_layout_row_dynamic(context, nk_window_get_height(context) - console->text_region_height * 2, 1);
if(nk_group_begin(context, "Log", NK_WINDOW_BORDER))
{
for(int i = 0; i <= console->current_message_index; i++)
{
nk_layout_row_dynamic(context, console->line_height, 1);
nk_labelf_colored(context, NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, console_message_color[console->console_messages[i].type], console->console_messages[i].message);
}
if(console->scroll_to_bottom == true) // scroll console message area to the bottom if required
{
*context->current->layout->offset_y = (nk_uint)context->current->layout->at_y;
console->scroll_to_bottom = false;
}
nk_group_end(context);
}
if(nk_begin_titled(context, "Console", "Console", nk_recti(0, 0, win_width, half_height), NK_WINDOW_SCROLL_AUTO_HIDE)) //Edit-string/Textfield for command
nk_layout_row_dynamic(context, console->text_region_height, 1);
int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER;
nk_edit_focus(context, edit_flags);
int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter);
if(edit_state & NK_EDIT_COMMITED)
{ {
nk_layout_row_dynamic(context, nk_window_get_height(context) - console->text_region_height * 2, 1); if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
if(nk_group_begin(context, "Log", NK_WINDOW_BORDER)) console->current_message_index = 0;
{
for(int i = 0; i <= console->current_message_index; i++) 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;
nk_layout_row_dynamic(context, console->line_height, 1); memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
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); console->scroll_to_bottom = true;
}
if(console->scroll_to_bottom == true) // scroll console message area to the bottom if required
{
*context->current->layout->offset_y = context->current->layout->at_y;
console->scroll_to_bottom = false;
}
nk_group_end(context);
}
//Edit-string/Textfield for command
nk_layout_row_dynamic(context, console->text_region_height, 1);
int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER;
nk_edit_focus(context, edit_flags);
int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter);
if(edit_state & NK_EDIT_COMMITED)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text);
console->console_messages[console->current_message_index].type = CMT_COMMAND;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->scroll_to_bottom = true;
}
} }
nk_end(context); }
nk_end(context);
} }
void console_destroy(struct Console* console) void console_destroy(struct Console* console)
@ -99,37 +99,37 @@ void console_destroy(struct Console* console)
int console_filter(const struct nk_text_edit *box, nk_rune unicode) int console_filter(const struct nk_text_edit *box, nk_rune unicode)
{ {
NK_UNUSED(box); NK_UNUSED(box);
if(unicode > 128 || unicode == 96) // Ignore tilde or anything other than ascii if(unicode > 128 || unicode == 96) // Ignore tilde or anything other than ascii
return nk_false; return nk_false;
else else
return nk_true; return nk_true;
} }
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, 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;
} }

File diff suppressed because it is too large Load Diff

@ -18,137 +18,137 @@ typedef void (*Collision_CB)(struct Entity* this_entity, struct Entity* other_en
enum Entity_Type enum Entity_Type
{ {
ET_NONE, ET_NONE,
ET_DEFAULT, ET_DEFAULT,
ET_PLAYER, ET_PLAYER,
ET_ROOT, ET_ROOT,
ET_CAMERA, ET_CAMERA,
ET_LIGHT, ET_LIGHT,
ET_STATIC_MESH, ET_STATIC_MESH,
ET_SOUND_SOURCE, ET_SOUND_SOURCE,
ET_MAX ET_MAX
}; };
enum LightType enum LightType
{ {
LT_SPOT = 0, LT_SPOT = 0,
LT_DIR, LT_DIR,
LT_POINT, LT_POINT,
LT_INVALID, LT_INVALID,
LT_MAX LT_MAX
}; };
enum Camera_Type enum Camera_Type
{ {
CAM_EDITOR = 0, CAM_EDITOR = 0,
CAM_GAME, CAM_GAME,
CAM_MAX CAM_MAX
}; };
struct Transform struct Transform
{ {
vec3 position; vec3 position;
vec3 scale; vec3 scale;
quat rotation; quat rotation;
mat4 trans_mat; mat4 trans_mat;
bool is_modified; bool is_modified;
bool sync_physics; bool sync_physics;
struct Entity* parent; struct Entity* parent;
struct Entity** children; struct Entity** children;
}; };
struct Entity struct Entity
{ {
int id; int id;
int type; int type;
char name[MAX_ENTITY_NAME_LEN]; char name[MAX_ENTITY_NAME_LEN];
bool marked_for_deletion; bool marked_for_deletion;
bool active; bool active;
bool editor_selected; bool editor_selected;
struct Transform transform; struct Transform transform;
}; };
struct Model struct Model
{ {
int geometry_index; int geometry_index;
struct Material* material; struct Material* material;
struct Variant material_params[MMP_MAX]; struct Variant material_params[MMP_MAX];
}; };
struct Sound_Source struct Sound_Source
{ {
struct Entity base; struct Entity base;
int type; int type;
bool playing; bool playing;
bool loop; bool loop;
uint source_instance; uint source_instance;
float min_distance; float min_distance;
float max_distance; float max_distance;
float rolloff_factor; float rolloff_factor;
float volume; float volume;
int attenuation_type; int attenuation_type;
struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played
}; };
struct Camera struct Camera
{ {
struct Entity base; struct Entity base;
mat4 proj_mat; mat4 proj_mat;
mat4 view_mat; mat4 view_mat;
mat4 view_proj_mat; mat4 view_proj_mat;
float fov; float fov;
float aspect_ratio; float aspect_ratio;
float nearz; float nearz;
float farz; float farz;
float zoom; float zoom;
bool ortho; bool ortho;
int fbo; int fbo;
int render_tex; int render_tex;
int depth_tex; int depth_tex;
vec4 clear_color; vec4 clear_color;
vec4 frustum[6]; vec4 frustum[6];
bool resizeable; bool resizeable;
}; };
struct Light struct Light
{ {
struct Entity base; struct Entity base;
float outer_angle; float outer_angle;
float inner_angle; float inner_angle;
float falloff; float falloff;
float intensity; float intensity;
vec3 color; vec3 color;
bool cast_shadow; bool cast_shadow;
bool pcf_enabled; bool pcf_enabled;
bool valid; bool valid;
int type; int type;
int radius; int radius;
int shadow_map[4]; int shadow_map[4];
float depth_bias; float depth_bias;
}; };
struct Collision struct Collision
{ {
Rigidbody rigidbody; Rigidbody rigidbody;
Collision_Shape collision_shape; Collision_Shape collision_shape;
Collision_CB on_collision; Collision_CB on_collision;
}; };
struct Static_Mesh struct Static_Mesh
{ {
struct Entity base; struct Entity base;
struct Model model; struct Model model;
struct Collision collision; struct Collision collision;
}; };
struct Player struct Player
{ {
struct Entity base; struct Entity base;
struct Static_Mesh* mesh; struct Static_Mesh* mesh;
struct Camera* camera_node; struct Camera* camera_node;
float move_speed; float move_speed;
float move_speed_multiplier; float move_speed_multiplier;
float turn_speed; float turn_speed;
}; };
void entity_init(struct Entity* entity, const char* name, struct Entity* parent); void entity_init(struct Entity* entity, const char* name, struct Entity* parent);

File diff suppressed because it is too large Load Diff

@ -12,52 +12,52 @@ struct Static_Mesh;
struct Uniform struct Uniform
{ {
int location; int location;
int type; int type;
}; };
enum Mat_Type enum Mat_Type
{ {
MAT_BLINN = 0, MAT_BLINN = 0,
MAT_UNSHADED, MAT_UNSHADED,
MAT_MAX MAT_MAX
}; };
enum Mat_Model_Param enum Mat_Model_Param
{ {
MMP_DIFFUSE_TEX = 0, MMP_DIFFUSE_TEX = 0,
MMP_DIFFUSE_COL, MMP_DIFFUSE_COL,
MMP_DIFFUSE, MMP_DIFFUSE,
MMP_SPECULAR_STRENGTH, MMP_SPECULAR_STRENGTH,
MMP_SPECULAR, MMP_SPECULAR,
MMP_MAX MMP_MAX
}; };
enum Mat_Pipeline_Param enum Mat_Pipeline_Param
{ {
MPP_MODEL_MAT = 0, MPP_MODEL_MAT = 0,
MPP_INV_MODEL_MAT, MPP_INV_MODEL_MAT,
MPP_VIEW_MAT, MPP_VIEW_MAT,
MPP_MVP, MPP_MVP,
MPP_FOG_MODE, MPP_FOG_MODE,
MPP_FOG_DENSITY, MPP_FOG_DENSITY,
MPP_FOG_START_DIST, MPP_FOG_START_DIST,
MPP_FOG_MAX_DIST, MPP_FOG_MAX_DIST,
MPP_FOG_COLOR, MPP_FOG_COLOR,
MPP_CAM_POS, MPP_CAM_POS,
MPP_TOTAL_LIGHTS, MPP_TOTAL_LIGHTS,
MPP_AMBIENT_LIGHT, MPP_AMBIENT_LIGHT,
MPP_MAX MPP_MAX
}; };
struct Material struct Material
{ {
int type; int type;
int shader; int shader;
struct Static_Mesh* registered_static_meshes[MAX_MATERIAL_REGISTERED_STATIC_MESHES]; struct Static_Mesh* registered_static_meshes[MAX_MATERIAL_REGISTERED_STATIC_MESHES];
bool lit; bool lit;
struct Uniform model_params[MMP_MAX]; struct Uniform model_params[MMP_MAX];
struct Uniform pipeline_params[MPP_MAX]; struct Uniform pipeline_params[MPP_MAX];
}; };
bool material_init(struct Material* material, int material_type); bool material_init(struct Material* material, int material_type);

@ -6,77 +6,79 @@
#include "../common/common.h" #include "../common/common.h"
#include "camera.h" #include "camera.h"
#include "bounding_volumes.h" #include "bounding_volumes.h"
#include "../common/hashmap.h"
#include "../common/log.h"
void player_init(struct Player* player, struct Scene* scene) void player_init(struct Player* player, struct Scene* scene)
{ {
entity_init(player, "Player", &scene->root_entity); entity_init(player, "Player", &scene->root_entity);
player->base.active = true; player->base.active = true;
player->base.id = 1; player->base.id = 1;
player->base.type = ET_PLAYER; player->base.type = ET_PLAYER;
struct Hashmap* config = platform->config.get(); struct Hashmap* config = platform->config.get();
player->move_speed = hashmap_int_get(config, "player_move_speed"); player->move_speed = hashmap_int_get(config, "player_move_speed");
player->move_speed_multiplier = hashmap_int_get(config, "player_move_speed_multiplier"); player->move_speed_multiplier = hashmap_int_get(config, "player_move_speed_multiplier");
player->turn_speed = hashmap_int_get(config, "player_turn_speed"); player->turn_speed = hashmap_int_get(config, "player_turn_speed");
player->mesh = scene_static_mesh_create(scene, "Player_Mesh", player, "sphere.symbres", MAT_BLINN); player->mesh = scene_static_mesh_create(scene, "Player_Mesh", player, "sphere.symbres", MAT_BLINN);
struct Camera* player_camera = &scene->cameras[CAM_GAME]; struct Camera* player_camera = &scene->cameras[CAM_GAME];
entity_rename(player_camera, "Player_Camera"); entity_rename(player_camera, "Player_Camera");
player_camera->base.active = true; player_camera->base.active = true;
player_camera->clear_color.x = 0.6f; player_camera->clear_color.x = 0.6f;
player_camera->clear_color.y = 0.6f; player_camera->clear_color.y = 0.6f;
player_camera->clear_color.z = 0.9f; player_camera->clear_color.z = 0.9f;
player_camera->clear_color.w = 1.f; player_camera->clear_color.w = 1.f;
player->camera_node = player_camera; player->camera_node = player_camera;
int render_width = hashmap_int_get(config, "render_width"); int render_width = hashmap_int_get(config, "render_width");
int render_height = hashmap_int_get(config, "render_height"); int render_height = hashmap_int_get(config, "render_height");
camera_attach_fbo(player_camera, render_width, render_height, true, true, true); camera_attach_fbo(player_camera, render_width, render_height, true, true, true);
transform_parent_set(player_camera, player, true); transform_parent_set(player_camera, player, true);
vec3 cam_translation = {0.f, 20.f, 2.f}; vec3 cam_translation = {0.f, 20.f, 2.f};
transform_translate(player_camera, &cam_translation, TS_LOCAL); transform_translate(player_camera, &cam_translation, TS_LOCAL);
vec3 cam_axis = {-1.f, 0.f, 0.f}; vec3 cam_axis = {-1.f, 0.f, 0.f};
transform_rotate(player_camera, &cam_axis, 85.f, TS_LOCAL); transform_rotate(player_camera, &cam_axis, 85.f, TS_LOCAL);
} }
void player_destroy(struct Player* player) void player_destroy(struct Player* player)
{ {
entity_reset(player, player->base.id); entity_reset(player, player->base.id);
player->base.active = false; player->base.active = false;
} }
void player_update(struct Player* player, struct Scene* scene, float dt) void player_update(struct Player* player, struct Scene* scene, float dt)
{ {
float move_speed = player->move_speed; float move_speed = player->move_speed;
vec3 offset = {0.f, 0.f, 0.f}; vec3 offset = {0.f, 0.f, 0.f};
/* Movement */ /* Movement */
if(input_map_state_get("Sprint", KS_PRESSED)) move_speed *= player->move_speed_multiplier; if(input_map_state_get("Sprint", KS_PRESSED)) move_speed *= player->move_speed_multiplier;
if(input_map_state_get("Move_Forward", KS_PRESSED)) offset.z -= move_speed; if(input_map_state_get("Move_Forward", KS_PRESSED)) offset.z -= move_speed;
if(input_map_state_get("Move_Backward", KS_PRESSED)) offset.z += move_speed; if(input_map_state_get("Move_Backward", KS_PRESSED)) offset.z += move_speed;
if(input_map_state_get("Move_Left", KS_PRESSED)) offset.x -= move_speed; if(input_map_state_get("Move_Left", KS_PRESSED)) offset.x -= move_speed;
if(input_map_state_get("Move_Right", KS_PRESSED)) offset.x += move_speed; if(input_map_state_get("Move_Right", KS_PRESSED)) offset.x += move_speed;
if(input_map_state_get("Move_Up", KS_PRESSED)) offset.y += move_speed; if(input_map_state_get("Move_Up", KS_PRESSED)) offset.y += move_speed;
if(input_map_state_get("Move_Down", KS_PRESSED)) offset.y -= move_speed; if(input_map_state_get("Move_Down", KS_PRESSED)) offset.y -= move_speed;
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(player, &offset, TS_LOCAL); transform_translate(player, &offset, TS_LOCAL);
} }
/* Aiming and Projectiles*/ /* Aiming and Projectiles*/
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED)) if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED))
{ {
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(player->camera_node, mouse_x, mouse_y); struct Ray ray = camera_screen_coord_to_ray(player->camera_node, 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 Raycast_Result ray_result; struct Raycast_Result ray_result;
scene_ray_intersect(scene, &ray, &ray_result); scene_ray_intersect(scene, &ray, &ray_result);
} }
} }

@ -33,475 +33,474 @@ void on_framebuffer_size_change(int width, int height);
void renderer_init(struct Renderer* renderer) void renderer_init(struct Renderer* renderer)
{ {
assert(renderer); assert(renderer);
glClearColor(0.3f, 0.6f, 0.9f, 1.0f); glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
platform->windowresize_callback_set(on_framebuffer_size_change); platform->windowresize_callback_set(on_framebuffer_size_change);
struct Hashmap* cvars = platform->config.get(); struct Hashmap* cvars = platform->config.get();
renderer->settings.fog.mode = hashmap_int_get(cvars, "fog_mode"); renderer->settings.fog.mode = hashmap_int_get(cvars, "fog_mode");
renderer->settings.fog.density = hashmap_float_get(cvars, "fog_density"); renderer->settings.fog.density = hashmap_float_get(cvars, "fog_density");
renderer->settings.fog.start_dist = hashmap_float_get(cvars, "fog_start_dist"); renderer->settings.fog.start_dist = hashmap_float_get(cvars, "fog_start_dist");
renderer->settings.fog.max_dist = hashmap_float_get(cvars, "fog_max_dist"); renderer->settings.fog.max_dist = hashmap_float_get(cvars, "fog_max_dist");
renderer->settings.fog.color = hashmap_vec3_get(cvars, "fog_color"); renderer->settings.fog.color = hashmap_vec3_get(cvars, "fog_color");
renderer->settings.debug_draw_enabled = hashmap_bool_get(cvars, "debug_draw_enabled"); renderer->settings.debug_draw_enabled = hashmap_bool_get(cvars, "debug_draw_enabled");
renderer->settings.debug_draw_physics = hashmap_bool_get(cvars, "debug_draw_physics"); renderer->settings.debug_draw_physics = hashmap_bool_get(cvars, "debug_draw_physics");
renderer->settings.debug_draw_mode = hashmap_int_get(cvars, "debug_draw_mode"); renderer->settings.debug_draw_mode = hashmap_int_get(cvars, "debug_draw_mode");
renderer->settings.debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); renderer->settings.debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color");
renderer->settings.ambient_light = hashmap_vec3_get(cvars, "ambient_light"); renderer->settings.ambient_light = hashmap_vec3_get(cvars, "ambient_light");
/* Quad geometry for final render */ /* Quad geometry for final render */
vec3* vertices = array_new(vec3); vec3* vertices = array_new(vec3);
vec2* uvs = array_new(vec2); vec2* uvs = array_new(vec2);
vec3* normals = array_new(vec3); vec3* normals = array_new(vec3);
uint* indices = array_new(uint); uint* indices = array_new(uint);
vec3 temp_v3; vec3 temp_v3;
vec2 temp_v2; vec2 temp_v2;
/* Vertices */ /* Vertices */
temp_v3.x = -1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); temp_v3.x = -1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = 1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); temp_v3.x = 1; temp_v3.y = -1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = 1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); temp_v3.x = 1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
temp_v3.x = -1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3); temp_v3.x = -1; temp_v3.y = 1; temp_v3.z = 0; array_push(vertices, temp_v3, vec3);
/* Normals */ /* Normals */
temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3); temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3);
temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3); temp_v3.x = 0; temp_v3.y = 1; temp_v3.z = 0; array_push(normals, temp_v3, vec3);
/* Uvs */ /* Uvs */
temp_v2.x = 0; temp_v2.y = 0; array_push(uvs, temp_v2, vec2); temp_v2.x = 0; temp_v2.y = 0; array_push(uvs, temp_v2, vec2);
temp_v2.x = 1; temp_v2.y = 0; array_push(uvs, temp_v2, vec2); temp_v2.x = 1; temp_v2.y = 0; array_push(uvs, temp_v2, vec2);
temp_v2.x = 1; temp_v2.y = 1; array_push(uvs, temp_v2, vec2); temp_v2.x = 1; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2); temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
/* Indices */ /* Indices */
array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint); array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint);
array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint); array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint);
renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL); renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL);
array_free(vertices); array_free(vertices);
array_free(uvs); array_free(uvs);
array_free(normals); array_free(normals);
array_free(indices); array_free(indices);
int width = -1, height = -1; int width = -1, height = -1;
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);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
renderer->def_fbo = framebuffer_create(width, height, true, false, true); renderer->def_fbo = framebuffer_create(width, height, true, false, true);
framebuffer_texture_set(renderer->def_fbo, renderer->def_albedo_tex, FA_COLOR_ATTACHMENT0); framebuffer_texture_set(renderer->def_fbo, renderer->def_albedo_tex, FA_COLOR_ATTACHMENT0);
framebuffer_texture_set(renderer->def_fbo, renderer->def_depth_tex, FA_DEPTH_ATTACHMENT); framebuffer_texture_set(renderer->def_fbo, renderer->def_depth_tex, FA_DEPTH_ATTACHMENT);
renderer->composition_shader = shader_create("fbo.vert", "fbo.frag"); renderer->composition_shader = shader_create("fbo.vert", "fbo.frag");
renderer->debug_shader = shader_create("debug.vert", "debug.frag"); renderer->debug_shader = shader_create("debug.vert", "debug.frag");
renderer->num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); renderer->num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT);
renderer->num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); renderer->num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT);
renderer->num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); renderer->num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT);
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();
// 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);
} }
} }
void renderer_draw(struct Renderer* renderer, struct Scene* scene) 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];
if(!camera->base.active) continue;
int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo;
framebuffer_bind(fbo);
{ {
struct Camera* camera = &scene->cameras[i]; glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo));
if(!camera->base.active) continue; glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo; glClearColor(camera->clear_color.x,
framebuffer_bind(fbo); 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 */
{ {
glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); char uniform_name[MAX_UNIFORM_NAME_LEN];
glEnable(GL_DEPTH_TEST); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
glDepthFunc(GL_LEQUAL); int light_count = -1;
glClearColor(camera->clear_color.x, for(int i = 0; i < MAX_LIGHTS; i++)
camera->clear_color.y, {
camera->clear_color.z, struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */
camera->clear_color.w); if(!light->base.active && light->valid) continue;
glEnable(GL_CULL_FACE ); light_count++;
glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); vec3 light_pos = {0, 0, 0};
static mat4 mvp; transform_get_absolute_position(&light->base, &light_pos);
for(int i = 0; i < MAT_MAX; i++)
if(light->type != LT_POINT)
{ {
/* for each material, get all the registered models and render them */ snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count);
struct Material* material = &renderer->materials[i]; vec3 light_dir = {0.f, 0.f, 0.f};
GL_CHECK(shader_bind(material->shader)); transform_get_absolute_lookat(&light->base, &light_dir);
vec3_norm(&light_dir, &light_dir);
if(material->lit) /* Set light information */ shader_set_uniform_vec3(material->shader, uniform_name, &light_dir);
{ 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);
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 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, &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);
editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices);
renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0; if(light->type != LT_DIR)
} {
framebuffer_unbind(); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count);
glDisable(GL_DEPTH_TEST); shader_set_uniform_vec3(material->shader, uniform_name, &light_pos);
glDisable(GL_CULL_FACE); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
/* Final Render */ snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count);
struct Camera* active_camera = &scene->cameras[scene->active_camera_index]; shader_set_uniform_float(material->shader, uniform_name, light->outer_angle);
int width, height; memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader_bind(renderer->composition_shader);
int final_render_tex = active_camera->render_tex == -1 ? renderer->def_albedo_tex : active_camera->render_tex;
texture_bind(final_render_tex);
geom_render(renderer->quad_geo, GDM_TRIANGLES);
texture_unbind(final_render_tex);
shader_unbind();
/* Debug Render */ snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count);
struct Hashmap* cvars = platform->config.get(); shader_set_uniform_float(material->shader, uniform_name, light->inner_angle);
if(hashmap_bool_get(cvars, "debug_draw_enabled")) memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count);
vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); shader_set_uniform_float(material->shader, uniform_name, light->falloff);
shader_bind(renderer->debug_shader); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
{
static mat4 mvp; snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count);
shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color); shader_set_uniform_int(material->shader, uniform_name, light->radius);
for(int i = 0; i < MAX_STATIC_MESHES; i++) memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active) continue;
struct Model* model = &mesh->model;
struct Transform* transform = &mesh->base.transform;
int geometry = model->geometry_index;
mat4_identity(&mvp);
mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp);
geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode"));
} }
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 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));
} }
shader_unbind();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Debug Physics render /* Set material pipeline uniforms */
if(hashmap_bool_get(cvars, "debug_draw_physics")) 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));
static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; 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));
for(int i = 0; i < MAX_STATIC_MESHES; i++) 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));
struct Static_Mesh* mesh = &scene->static_meshes[i]; GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light));
if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue; 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));
//Get collision mesh and it's props then render it
vec3 pos = {0.f};
quat rot = {0.f, 0.f, 0.f, 1.f };
if(mesh->collision.rigidbody)
{
platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z);
platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w);
}
else
{
platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z);
platform->physics.cs_rotation_get(mesh->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w);
}
int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape); for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++)
switch(collision_shape_type) {
{ if(!material->registered_static_meshes[j]) continue;
case CST_SPHERE:
{ /* for each registered model, set up uniforms and render */
float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape); struct Static_Mesh* mesh = material->registered_static_meshes[j];
im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES); struct Geometry* geometry = geom_get(mesh->model.geometry_index);
}
break; /* Check if model is in frustum */
case CST_BOX: 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)
{ {
float x = 0.f, y = 0.f, z = 0.f; 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;
platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z); 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;
im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); 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;
break;
default: 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);
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 */
struct Camera* active_camera = &scene->cameras[scene->active_camera_index];
int width, height;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader_bind(renderer->composition_shader);
int final_render_tex = active_camera->render_tex == -1 ? renderer->def_albedo_tex : active_camera->render_tex;
texture_bind(final_render_tex);
geom_render(renderer->quad_geo, GDM_TRIANGLES);
texture_unbind(final_render_tex);
shader_unbind();
/* Debug Render */
struct Hashmap* cvars = platform->config.get();
if(hashmap_bool_get(cvars, "debug_draw_enabled"))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color");
shader_bind(renderer->debug_shader);
{
static mat4 mvp;
shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color);
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active) continue;
struct Model* model = &mesh->model;
struct Transform* transform = &mesh->base.transform;
int geometry = model->geometry_index;
mat4_identity(&mvp);
mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp);
geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode"));
}
}
shader_unbind();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Debug Physics render
if(hashmap_bool_get(cvars, "debug_draw_physics"))
{
static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f };
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue;
//Get collision mesh and it's props then render it
vec3 pos = {0.f};
quat rot = {0.f, 0.f, 0.f, 1.f };
if(mesh->collision.rigidbody)
{
platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z);
platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w);
}
else
{
platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z);
platform->physics.cs_rotation_get(mesh->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w);
}
int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape);
switch(collision_shape_type)
{
case CST_SPHERE:
{
float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape);
im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES);
}
break;
case CST_BOX:
{
float x = 0.f, y = 0.f, z = 0.f;
platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z);
im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES);
};
break;
default: break;
}
}
}
//Immediate mode geometry render //Immediate mode geometry render
im_render(active_camera); im_render(active_camera);
/* 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();
/* Render UI */ /* Render UI */
gui_render(NK_ANTI_ALIASING_ON); gui_render(NK_ANTI_ALIASING_ON);
} }
void renderer_cleanup(struct Renderer* renderer) 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], i); material_reset(&renderer->materials[i]);
} }
im_cleanup(); im_cleanup();
sprite_batch_remove(renderer->sprite_batch); sprite_batch_remove(renderer->sprite_batch);
free(renderer->sprite_batch); free(renderer->sprite_batch);
geom_remove(renderer->quad_geo); geom_remove(renderer->quad_geo);
framebuffer_remove(renderer->def_fbo); framebuffer_remove(renderer->def_fbo);
texture_remove(renderer->def_albedo_tex); texture_remove(renderer->def_albedo_tex);
texture_remove(renderer->def_depth_tex); texture_remove(renderer->def_depth_tex);
} }
void on_framebuffer_size_change(int width, int height) void on_framebuffer_size_change(int width, int height)
{ {
struct Scene* scene = game_state_get()->scene; struct Scene* scene = game_state_get()->scene;
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);
} }
void renderer_clearcolor_set(float red, float green, float blue, float alpha) void renderer_clearcolor_set(float red, float green, float blue, float alpha)
{ {
glClearColor(red, green, blue, alpha); glClearColor(red, green, blue, alpha);
} }
struct Material * renderer_material_get(int material_type) struct Material * renderer_material_get(int material_type)
{ {
return NULL; return NULL;
} }
void renderer_debug_draw_enabled(bool enabled) void renderer_debug_draw_enabled(struct Renderer* renderer, bool enabled)
{ {
struct Hashmap* cvars = platform->config.get(); renderer->settings.debug_draw_mode = enabled;
hashmap_bool_set(cvars, "debug_draw_enabled", enabled);
}
void renderer_settings_get(struct Render_Settings* settings)
{
struct Hashmap* cvars = platform->config.get();
settings->fog.mode = hashmap_int_get(cvars, "fog_mode");
settings->fog.density = hashmap_float_get(cvars, "fog_density");
settings->fog.start_dist = hashmap_float_get(cvars, "fog_start_dist");
settings->fog.max_dist = hashmap_float_get(cvars, "fog_max_dist");
settings->fog.color = hashmap_vec3_get(cvars, "fog_color");
settings->debug_draw_enabled = hashmap_bool_get(cvars, "debug_draw_enabled");
settings->debug_draw_physics = hashmap_bool_get(cvars, "debug_draw_physics");
settings->debug_draw_mode = hashmap_int_get(cvars, "debug_draw_mode");
settings->debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color");
settings->ambient_light = hashmap_vec3_get(cvars, "ambient_light");
} }
void renderer_settings_set(const struct Render_Settings* settings) /* void renderer_settings_get(struct Render_Settings* settings) */
{ /* { */
struct Hashmap* cvars = platform->config.get(); /* struct Hashmap* cvars = platform->config.get(); */
hashmap_int_set(cvars, "fog_mode", settings->fog.mode); /* settings->fog.mode = hashmap_int_get(cvars, "fog_mode"); */
hashmap_float_set(cvars, "fog_density", settings->fog.density); /* settings->fog.density = hashmap_float_get(cvars, "fog_density"); */
hashmap_float_set(cvars, "fog_start_dist", settings->fog.start_dist); /* settings->fog.start_dist = hashmap_float_get(cvars, "fog_start_dist"); */
hashmap_float_set(cvars, "fog_max_dist", settings->fog.max_dist); /* settings->fog.max_dist = hashmap_float_get(cvars, "fog_max_dist"); */
hashmap_vec3_set(cvars, "fog_color", &settings->fog.color); /* settings->fog.color = hashmap_vec3_get(cvars, "fog_color"); */
hashmap_bool_set(cvars, "debug_draw_enabled", settings->debug_draw_enabled); /* settings->debug_draw_enabled = hashmap_bool_get(cvars, "debug_draw_enabled"); */
hashmap_bool_set(cvars, "debug_draw_physics", settings->debug_draw_physics); /* settings->debug_draw_physics = hashmap_bool_get(cvars, "debug_draw_physics"); */
hashmap_int_set(cvars, "debug_draw_mode", settings->debug_draw_mode); /* settings->debug_draw_mode = hashmap_int_get(cvars, "debug_draw_mode"); */
hashmap_vec4_set(cvars, "debug_draw_color", &settings->debug_draw_color); /* settings->debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); */
hashmap_vec3_set(cvars, "ambient_light", &settings->ambient_light); /* settings->ambient_light = hashmap_vec3_get(cvars, "ambient_light"); */
} /* } */
/* void renderer_settings_set(const struct Render_Settings* settings) */
/* { */
/* struct Hashmap* cvars = platform->config.get(); */
/* hashmap_int_set(cvars, "fog_mode", settings->fog.mode); */
/* hashmap_float_set(cvars, "fog_density", settings->fog.density); */
/* hashmap_float_set(cvars, "fog_start_dist", settings->fog.start_dist); */
/* hashmap_float_set(cvars, "fog_max_dist", settings->fog.max_dist); */
/* hashmap_vec3_set(cvars, "fog_color", &settings->fog.color); */
/* hashmap_bool_set(cvars, "debug_draw_enabled", settings->debug_draw_enabled); */
/* hashmap_bool_set(cvars, "debug_draw_physics", settings->debug_draw_physics); */
/* hashmap_int_set(cvars, "debug_draw_mode", settings->debug_draw_mode); */
/* hashmap_vec4_set(cvars, "debug_draw_color", &settings->debug_draw_color); */
/* hashmap_vec3_set(cvars, "ambient_light", &settings->ambient_light); */
/* } */

@ -9,45 +9,45 @@ struct Sprite_Batch;
enum Fog_Mode enum Fog_Mode
{ {
FM_NONE = 0, FM_NONE = 0,
FM_LINEAR = 1, FM_LINEAR = 1,
FM_EXPONENTIAL = 2, FM_EXPONENTIAL = 2,
FM_EXPONENTIAL_SQRD = 3 FM_EXPONENTIAL_SQRD = 3
}; };
struct Fog struct Fog
{ {
int mode; int mode;
float density; float density;
float start_dist; float start_dist;
float max_dist; float max_dist;
vec3 color; vec3 color;
}; };
struct Render_Settings struct Render_Settings
{ {
struct Fog fog; struct Fog fog;
vec3 ambient_light; vec3 ambient_light;
bool debug_draw_enabled; bool debug_draw_enabled;
vec4 debug_draw_color; vec4 debug_draw_color;
int debug_draw_mode; int debug_draw_mode;
bool debug_draw_physics; bool debug_draw_physics;
}; };
struct Renderer struct Renderer
{ {
int def_fbo; int def_fbo;
int def_albedo_tex; int def_albedo_tex;
int def_depth_tex; int def_depth_tex;
int quad_geo; int quad_geo;
int composition_shader; int composition_shader;
int debug_shader; int debug_shader;
int num_culled , num_rendered , num_indices; int num_culled , num_rendered , num_indices;
int num_culled_slot, num_rendered_slot, num_indices_slot; int num_culled_slot, num_rendered_slot, num_indices_slot;
struct Sprite_Batch* sprite_batch; struct Sprite_Batch* sprite_batch;
struct Render_Settings settings; struct Render_Settings settings;
struct Material materials[MAT_MAX]; struct Material materials[MAT_MAX];
}; };
void renderer_init(struct Renderer* renderer); void renderer_init(struct Renderer* renderer);

File diff suppressed because it is too large Load Diff

@ -15,15 +15,15 @@ struct Ray;
struct Scene struct Scene
{ {
struct Render_Settings renderer_profile; struct Render_Settings renderer_profile;
struct Entity root_entity; struct Entity root_entity;
struct Player player; struct Player player;
struct Entity entities[MAX_ENTITIES]; struct Entity entities[MAX_ENTITIES];
struct Static_Mesh static_meshes[MAX_STATIC_MESHES]; struct Static_Mesh static_meshes[MAX_STATIC_MESHES];
struct Camera cameras[MAX_CAMERAS]; struct Camera cameras[MAX_CAMERAS];
struct Light lights[MAX_LIGHTS]; struct Light lights[MAX_LIGHTS];
struct Sound_Source sound_sources[MAX_SOUND_SOURCES]; struct Sound_Source sound_sources[MAX_SOUND_SOURCES];
int active_camera_index; int active_camera_index;
}; };
void scene_init(struct Scene* scene); void scene_init(struct Scene* scene);
@ -36,7 +36,7 @@ void scene_post_update(struct Scene* scene);
struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent); struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent);
struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type); struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type);
struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height); struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height);
struct Static_Model* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type); struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type);
struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play); struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play);
void scene_entity_remove(struct Scene* scene, struct Entity* entity); void scene_entity_remove(struct Scene* scene, struct Entity* entity);

Loading…
Cancel
Save