Removed several warnings

dev
Shariq Shah 7 years ago
parent 785b762c7a
commit c651847d43
  1. 4
      .dir-locals.el
  2. 3
      README.md
  3. 350
      src/common/hashmap.c
  4. 78
      src/common/hashmap.h
  5. 901
      src/common/linmath.c
  6. 3
      src/common/linmath.h
  7. 398
      src/common/parser.c
  8. 116
      src/common/string_utils.c
  9. 163
      src/game/config_vars.c
  10. 620
      src/game/physics.c
  11. 492
      src/game/platform.c
  12. 348
      src/libsymmetry/camera.c
  13. 160
      src/libsymmetry/console.c
  14. 1193
      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. 829
      src/libsymmetry/renderer.c
  20. 52
      src/libsymmetry/renderer.h
  21. 1012
      src/libsymmetry/scene.c
  22. 20
      src/libsymmetry/scene.h

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

@ -163,6 +163,7 @@
- Console fix bug when enabled in editor mode
- Console command history
- Console command help
- Space partitioning and scene handling
- NPR and cross-hatching
- Move Gui_State and Editor_State into game_state and modify usage as needed
- Remove model and replace all usages with static mesh
@ -416,4 +417,4 @@
* Console log output
* Console error/warning output
* Implemented Auto scrolling to the bottom in console
* Implemented screen coordinate to ray conversion and ray-sphere collision
* Implemented screen coordinate to ray conversion and ray-sphere collision

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

@ -11,46 +11,46 @@
struct Hashmap;
struct Variant;
struct Hashmap* hashmap_new(void);
void hashmap_free(struct Hashmap* hashmap);
void hashmap_copy(struct Hashmap* from, struct Hashmap* to);
void hashmap_value_remove(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);
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_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_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_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_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_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_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_str_set(struct Hashmap* hashmap, const char* key, const char* value);
void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value);
float hashmap_float_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);
bool hashmap_bool_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);
vec4 hashmap_vec4_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 char* hashmap_str_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);
struct Hashmap* hashmap_new(void);
void hashmap_free(struct Hashmap* hashmap);
void hashmap_copy(struct Hashmap* from, struct Hashmap* to);
void hashmap_value_remove(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);
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_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_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_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_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_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_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_str_set(struct Hashmap* hashmap, const char* key, const char* value);
void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value);
float hashmap_float_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);
bool hashmap_bool_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);
vec4 hashmap_vec4_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 char* hashmap_str_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);
/* Only used during iteration */
void hashmap_iter_begin(struct Hashmap* hashmap);
int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value);
void hashmap_iter_begin(struct Hashmap* hashmap);
int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value);
#define HASHMAP_FOREACH(hashmap, key, value) \
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 */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#define M_PI 3.14159265358979323846f
#endif
#define EPSILON 0.0001
#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_identity(quat* res);
void quat_fill(quat* res, float x, float y, float z, float w);
void quat_mul_mat4(quat* res, quat* val, mat4* mat);
#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)
{
if(!file)
{
log_error("parser:load", "Invalid file handle for file %s", filename);
return false;
}
if(!file)
{
log_error("parser:load", "Invalid file handle for file %s", filename);
return false;
}
if(!assign_func)
{
log_error("parser:load", "No assign function provided to load file %s", filename);
return false;
}
if(!assign_func)
{
log_error("parser:load", "No assign function provided to load file %s", filename);
return false;
}
/* Read line by line, ignore comments */
char format_str[64];
char key_str[HASH_MAX_KEY_LEN];
char value_str[MAX_VALUE_LEN];
char line_buffer[MAX_LINE_LEN];
memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(line_buffer, '\0', MAX_LINE_LEN);
/* Read line by line, ignore comments */
char format_str[64];
char key_str[HASH_MAX_KEY_LEN];
char value_str[MAX_VALUE_LEN];
char line_buffer[MAX_LINE_LEN];
memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(line_buffer, '\0', MAX_LINE_LEN);
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);
while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{
current_line++;
memset(key_str, '\0', HASH_MAX_KEY_LEN);
memset(value_str, '\0', HASH_MAX_KEY_LEN);
if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{
if(return_on_emptyline)
return true;
else
continue;
}
if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{
if(return_on_emptyline)
return true;
else
continue;
}
if(line_buffer[0] == '#')
continue;
if(line_buffer[0] == '#')
continue;
if(sscanf(line_buffer, format_str, key_str, value_str) != 2)
{
log_warning("Malformed value in config file %s, line %d", filename, current_line);
continue;
}
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)
{
/* 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
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,
i may completely change the format in the future or switch to binary or use something like
JSON or TOML etc. */
/* 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
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,
i may completely change the format in the future or switch to binary or use something like
JSON or TOML etc. */
if(!file)
{
log_error("parser:load_objects", "Invalid file handle for file %s", filename);
return false;
}
if(!file)
{
log_error("parser:load_objects", "Invalid file handle for file %s", filename);
return false;
}
struct Parser* parser = malloc(sizeof(*parser));
if(!parser)
@ -89,109 +89,109 @@ struct Parser* parser_load_objects(FILE* file, const char* filename)
parser->objects = array_new(struct Parser_Object);
int current_line = 0;
char line_buffer[MAX_LINE_LEN];
char type_str[HASH_MAX_KEY_LEN];
char obj_str[1024];
int current_line = 0;
char line_buffer[MAX_LINE_LEN];
char type_str[HASH_MAX_KEY_LEN];
char obj_str[1024];
while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{
current_line++;
memset(type_str, '\0', HASH_MAX_KEY_LEN);
while(fgets(line_buffer, MAX_LINE_LEN - 1, file))
{
current_line++;
memset(type_str, '\0', HASH_MAX_KEY_LEN);
if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{
continue;
}
if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0)
{
continue;
}
if(line_buffer[0] == '#')
continue;
if(line_buffer[0] == '#')
continue;
/* Object type */
if(sscanf(line_buffer, "%s", type_str) != 1)
{
log_warning("Malformed line in config file %s, line %d", filename, current_line);
continue;
}
/* Object type */
if(sscanf(line_buffer, "%s", type_str) != 1)
{
log_warning("Malformed line in config file %s, line %d", filename, current_line);
continue;
}
// Check if type string is valid
int type_str_len = strnlen(type_str, HASH_MAX_KEY_LEN);
if(type_str_len < 3 || strncmp(type_str, "{", HASH_MAX_KEY_LEN) == 0 || strncmp(type_str, "}", HASH_MAX_KEY_LEN) == 0)
{
log_warning("Invalid object type '%s' on line %d", type_str, current_line);
continue;
}
// Check if type string is valid
size_t type_str_len = strnlen(type_str, HASH_MAX_KEY_LEN);
if(type_str_len < 3 || strncmp(type_str, "{", HASH_MAX_KEY_LEN) == 0 || strncmp(type_str, "}", HASH_MAX_KEY_LEN) == 0)
{
log_warning("Invalid object type '%s' on line %d", type_str, current_line);
continue;
}
long obj_beginning = -1;
long obj_ending = -1;
int obj_begin_expexted_at = current_line;
bool found_next_before_current_ended = false;
long obj_beginning = -1;
long obj_ending = -1;
int obj_begin_expexted_at = current_line;
bool found_next_before_current_ended = false;
/* Opening brace and closing brace */
char c = ' ';
int line_len = strnlen(line_buffer, MAX_LINE_LEN);
int seek_amount = line_len - type_str_len;
fseek(file, -seek_amount, SEEK_CUR);
/* Opening brace and closing brace */
char c = ' ';
size_t line_len = strnlen(line_buffer, MAX_LINE_LEN);
size_t seek_amount = line_len - type_str_len;
fseek(file, -seek_amount, SEEK_CUR);
while(!feof(file))
{
c = fgetc(file);
if(c == '\n')
{
current_line++;
continue;
}
if(c == '{')
{
obj_beginning = ftell(file);
c = ' ';
while(!feof(file))
{
c = fgetc(file);
if(c == '\n')
{
current_line++;
continue;
}
if(c == '{')
{
obj_beginning = ftell(file);
c = ' ';
while(!feof(file))
{
c = fgetc(file);
if(c == '\n')
{
current_line++;
continue;
}
c = fgetc(file);
if(c == '\n')
{
current_line++;
continue;
}
/* check if we found opening brace of next object,
if this is true then it means that this object is missing
it's closing brace and we should stop */
if(c == '{')
{
found_next_before_current_ended = true;
break;
}
if(c == '}')
{
/* check if we found opening brace of next object,
if this is true then it means that this object is missing
it's closing brace and we should stop */
if(c == '{')
{
found_next_before_current_ended = true;
break;
}
if(c == '}')
{
obj_ending = ftell(file) - 1;
break;
}
}
if(obj_ending != -1) break;
}
break;
}
}
if(obj_ending != -1) break;
}
}
if(obj_beginning == -1)
{
log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at);
return false;
}
if(obj_beginning == -1)
{
log_error("parser:load_object", "Syntax error while loading %s, expected '{' at line %d", filename, obj_begin_expexted_at);
return false;
}
if(obj_ending == -1)
{
if(found_next_before_current_ended)
log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line);
else
log_error("parser:load_object", "Syntax error while loading %s, expected '}' at line %d", filename, current_line);
return false;
}
if(obj_ending == -1)
{
if(found_next_before_current_ended)
log_error("parser:load_object", "Syntax error while loading %s, expected '}' before line %d but found '{'", filename, current_line);
else
log_error("parser:load_object", "Syntax error while loading %s, expected '}' at line %d", filename, current_line);
return false;
}
memset(obj_str, '\0', 1024);
memset(line_buffer, '\0', MAX_LINE_LEN);
fseek(file, obj_beginning, SEEK_SET);
fread(obj_str, obj_ending - obj_beginning, 1, file);
memset(obj_str, '\0', 1024);
memset(line_buffer, '\0', MAX_LINE_LEN);
fseek(file, obj_beginning, SEEK_SET);
fread(obj_str, obj_ending - obj_beginning, 1, file);
fseek(file, obj_ending + 1, SEEK_SET); // Position cursor after closing brace '}'
// Read into intermediate parser object and add it to the objects list
@ -229,7 +229,7 @@ struct Parser* parser_load_objects(FILE* file, const char* filename)
while((line = strtok(NULL, "\r\n")) != NULL);
//log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str);
}
}
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;
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, "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, "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, "Key", HASH_MAX_KEY_LEN) == 0) object_type = PO_KEY;
return object_type;
}
const char* parser_object_type_to_str(int type)
{
switch(type)
{
case PO_ENTITY: return "Entity";
case PO_MODEL: return "Model";
case PO_MATERIAL: return "Material";
case PO_CONFIG: return "Config";
case PO_KEY: return "Key";
case PO_UNKNOWN: return "Unknown";
default: return "Unknown";
}
switch(type)
{
case PO_ENTITY: return "Entity";
case PO_MODEL: return "Model";
case PO_MATERIAL: return "Material";
case PO_CONFIG: return "Config";
case PO_KEY: return "Key";
case PO_UNKNOWN: return "Unknown";
default: return "Unknown";
}
}
void parser_free(struct Parser *parser)
@ -276,68 +276,68 @@ void parser_free(struct Parser *parser)
struct Parser* parser_new(void)
{
struct Parser* parser = NULL;
parser = malloc(sizeof(*parser));
if(!parser)
{
log_error("parser:new", "Out of memory");
return NULL;
}
struct Parser* parser = NULL;
parser = malloc(sizeof(*parser));
if(!parser)
{
log_error("parser:new", "Out of memory");
return NULL;
}
parser->objects = array_new(struct Parser_Object);
if(!parser->objects)
{
log_error("parser:new", "Could not create objects array for parser");
free(parser);
return NULL;
}
parser->objects = array_new(struct Parser_Object);
if(!parser->objects)
{
log_error("parser:new", "Could not create objects array for parser");
free(parser);
return NULL;
}
return parser;
return parser;
}
struct Parser_Object* parser_object_new(struct Parser* parser, int type)
{
assert(parser);
struct Parser_Object* object = array_grow(parser->objects, struct Parser_Object);
if(!object)
{
log_error("parser:object_new", "Failed to add new parser object");
return NULL;
}
assert(parser);
struct Parser_Object* object = array_grow(parser->objects, struct Parser_Object);
if(!object)
{
log_error("parser:object_new", "Failed to add new parser object");
return NULL;
}
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)
{
assert(parser);
char value_str[MAX_VALUE_LEN];
int counter = 0;
for(int i = 0; i < array_len(parser->objects); i++)
assert(parser);
char value_str[MAX_VALUE_LEN];
int counter = 0;
for(int i = 0; i < array_len(parser->objects); i++)
{
struct Parser_Object* object = &parser->objects[i];
if(object->type == PO_UNKNOWN)
{
struct Parser_Object* object = &parser->objects[i];
if(object->type == PO_UNKNOWN)
{
log_warning("Unknown object type, cannot write to %s", filename);
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;
struct Variant* value = NULL;
HASHMAP_FOREACH(object->data, key, value)
{
memset(value_str, '\0', MAX_VALUE_LEN);
char* key = NULL;
struct Variant* value = NULL;
HASHMAP_FOREACH(object->data, key, value)
{
memset(value_str, '\0', MAX_VALUE_LEN);
variant_to_str(value, &value_str[0], MAX_VALUE_LEN);
fprintf(file, "\t%s : %s\n", key, value_str);
}
fprintf(file, "}\n\n");
counter++;
fprintf(file, "\t%s : %s\n", key, value_str);
}
fprintf(file, "}\n\n");
counter++;
}
log_message("%d objects written to %s", counter, filename);
return true;
log_message("%d objects written to %s", counter, filename);
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)
{
int* indices = array_new(int);
size_t string_len = strlen(string);
int* indices = array_new(int);
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);
/* 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)
int done = 0;
char* remaining_string = string;
while(!done)
{
char* location = strstr(remaining_string, pattern);
if(location)
{
char* location = strstr(remaining_string, pattern);
if(location)
{
int index = location - string;
array_push(indices, index, int);
remaining_string = location + pattern_len; /* Find the next occurance in the remaining string */
}
else
{
done = 1;
}
int index = (int)(location - string);
array_push(indices, index, int);
remaining_string = location + pattern_len; /* Find the next occurance in the remaining string */
}
int num_indices = array_len(indices);
if(num_indices > 0)
else
{
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);
done = 1;
}
}
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;
int num_indices = array_len(indices);
if(num_indices > 0)
{
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);
if(new_string)
{
done = 0;
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);
strncat(new_string, source_beg, (source_end - source_beg));
strcat(new_string, replacement);
count++;
prev_index = index + pattern_len;
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);
if(count == array_len(indices))
{
done = 1;
source_beg = string + prev_index;
strcat(new_string, source_beg);
}
array_free(indices);
return new_string;
}
else
{
return NULL;
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)
{
cvars = hashmap_new();
/* Initialize with default values incase there is no config file */
hashmap_int_set(cvars, "render_width", 1024);
hashmap_int_set(cvars, "render_height", 768);
hashmap_int_set(cvars, "fog_mode", 0);
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_start_dist", 10.f);
hashmap_float_set(cvars, "fog_max_dist", 50.f);
hashmap_vec3_setf(cvars, "ambient_light", 0.1f, 0.1f, 0.1f);
hashmap_bool_set(cvars, "msaa_enabled", 1);
hashmap_int_set(cvars, "msaa_levels", 4);
hashmap_bool_set(cvars, "debug_draw_enabled", true);
hashmap_bool_set(cvars, "debug_draw_physics", true);
cvars = hashmap_new();
/* Initialize with default values incase there is no config file */
hashmap_int_set(cvars, "render_width", 1024);
hashmap_int_set(cvars, "render_height", 768);
hashmap_int_set(cvars, "fog_mode", 0);
hashmap_vec3_setf(cvars, "fog_color", 0.9f, 0.2f, 0.2f);
hashmap_float_set(cvars, "fog_density", 0.1f);
hashmap_float_set(cvars, "fog_start_dist", 10.f);
hashmap_float_set(cvars, "fog_max_dist", 50.f);
hashmap_vec3_setf(cvars, "ambient_light", 0.1f, 0.1f, 0.1f);
hashmap_bool_set(cvars, "msaa_enabled", 1);
hashmap_int_set(cvars, "msaa_levels", 4);
hashmap_bool_set(cvars, "debug_draw_enabled", true);
hashmap_bool_set(cvars, "debug_draw_physics", true);
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_float_set(cvars, "player_move_speed", 10.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_move_speed", 10.f);
hashmap_float_set(cvars, "player_move_speed_multiplier", 2.f);
hashmap_float_set(cvars, "player_turn_speed", 5.f);
}
void config_vars_cleanup(void)
{
hashmap_free(cvars);
hashmap_free(cvars);
}
struct Hashmap* config_vars_get(void)
{
return cvars;
return cvars;
}
bool config_vars_load(const char* filename, int directory_type)
{
FILE* config_file = io_file_open(directory_type, filename, "rb");
if(!config_file)
{
log_error("config:vars_load", "Could not open %s", filename);
return false;
}
FILE* config_file = io_file_open(directory_type, filename, "rb");
if(!config_file)
{
log_error("config:vars_load", "Could not open %s", filename);
return false;
}
struct Parser* parser = parser_load_objects(config_file, filename);
if(!parser)
@ -65,74 +65,73 @@ bool config_vars_load(const char* filename, int directory_type)
return false;
}
bool config_loaded = false;
bool config_loaded = false;
for(int i = 0; i < array_len(parser->objects); i++)
{
struct Parser_Object* object = &parser->objects[i];
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)
if(object->type != PO_CONFIG)
{
log_error("config:vars_save", "Failed to open config file %s for writing");
return success;
log_warning("Unexpected config object type %s in %s", parser_object_type_to_str(object->type), filename);
continue;
}
struct Parser* parser = parser_new();
if(!parser)
config_loaded = true;
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);
fclose(config_file);
return false;
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);
}
}
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);
fclose(config_file);
return false;
}
if(config_loaded) log_message("Loaded config from %s", filename);
fclose(config_file);
return config_loaded;
}
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))
{
log_error("config_vars:save", "Failed to write config to '%s'", filename);
success = false;
}
struct Parser* parser = parser_new();
if(!parser)
{
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);
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
{
dWorldID world;
dSpaceID space;
dJointGroupID contact_group;
double step_size;
RigidbodyColCB on_collision;
RigidbodyMoveCB on_move;
dWorldID world;
dSpaceID space;
dJointGroupID contact_group;
double step_size;
RigidbodyColCB on_collision;
RigidbodyMoveCB on_move;
}
Physics;
Physics;
static void physics_near_callback(void* data, dGeomID body1, dGeomID body2);
static void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2);
void physics_init(void)
{
if(dInitODE2(0) == 0)
{
log_error("physics:init", "Failed to initialize ode");
return;
}
dAllocateODEDataForThread(dAllocateMaskAll);
Physics.world = dWorldCreate();
if(!Physics.world)
{
log_error("physics:init", "Physics world created!");
}
else
{
log_message("Physics world created");
Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.016;
dWorldSetCFM(Physics.world,1e-5);
dWorldSetAutoDisableFlag(Physics.world, 1);
dWorldSetLinearDamping(Physics.world, 0.00001);
dWorldSetAngularDamping(Physics.world, 0.005);
dWorldSetMaxAngularSpeed(Physics.world, 200);
dWorldSetContactMaxCorrectingVel(Physics.world,0.1);
dWorldSetContactSurfaceLayer(Physics.world,0.001);
}
if(dInitODE2(0) == 0)
{
log_error("physics:init", "Failed to initialize ode");
return;
}
dAllocateODEDataForThread(dAllocateMaskAll);
Physics.world = dWorldCreate();
if(!Physics.world)
{
log_error("physics:init", "Physics world created!");
}
else
{
log_message("Physics world created");
Physics.space = dHashSpaceCreate(0);
Physics.contact_group = dJointGroupCreate(0);
Physics.step_size = 0.016;
dWorldSetCFM(Physics.world,1e-5);
dWorldSetAutoDisableFlag(Physics.world, 1);
dWorldSetLinearDamping(Physics.world, 0.00001);
dWorldSetAngularDamping(Physics.world, 0.005);
dWorldSetMaxAngularSpeed(Physics.world, 200);
dWorldSetContactMaxCorrectingVel(Physics.world,0.1);
dWorldSetContactSurfaceLayer(Physics.world,0.001);
}
}
void physics_cleanup(void)
{
dJointGroupDestroy(Physics.contact_group);
dSpaceDestroy(Physics.space);
if(Physics.world)
{
dWorldDestroy(Physics.world);
}
dCleanupODEAllDataForThread();
dCloseODE();
dJointGroupDestroy(Physics.contact_group);
dSpaceDestroy(Physics.space);
if(Physics.world)
{
dWorldDestroy(Physics.world);
}
dCleanupODEAllDataForThread();
dCloseODE();
}
void physics_step(float delta_time)
{
int steps = (int)ceilf(delta_time / Physics.step_size);
for(int i = 0; i < steps; i++)
{
dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group);
}
int steps = (int)ceilf(delta_time / (float)Physics.step_size);
for(int i = 0; i < steps; i++)
{
dSpaceCollide(Physics.space, NULL, physics_near_callback);
dWorldQuickStep(Physics.world, Physics.step_size);
dJointGroupEmpty(Physics.contact_group);
}
}
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)
{
assert(x && y && z);
dVector3 gravity;
dWorldGetGravity(Physics.world, gravity);
*x = gravity[0];
*y = gravity[1];
*z = gravity[2];
assert(x && y && z);
dVector3 gravity;
dWorldGetGravity(Physics.world, gravity);
*x = (float)gravity[0];
*y = (float)gravity[1];
*z = (float)gravity[2];
}
void physics_body_position_get(Rigidbody body, float * x, float * y, float * z)
{
assert(x && y && z);
const dReal* position = dBodyGetPosition(body);
*x = position[0];
*y = position[1];
*z = position[2];
assert(x && y && z);
const dReal* position = dBodyGetPosition(body);
*x = (float)position[0];
*y = (float)position[1];
*z = (float)position[2];
}
void physics_body_position_set(Rigidbody body, float x, float y, float z)
{
dBodySetPosition(body, x, y, z);
dBodyEnable(body);
dBodySetPosition(body, x, y, z);
dBodyEnable(body);
}
void physics_body_rotation_get(Rigidbody body, float * x, float * y, float * z, float * w)
{
assert(x && y && z && w);
const dReal* rotation = dBodyGetQuaternion(body);
*x = rotation[1];
*y = rotation[2];
*z = rotation[3];
*w = rotation[0];
assert(x && y && z && w);
const dReal* rotation = dBodyGetQuaternion(body);
*x = (float)rotation[1];
*y = (float)rotation[2];
*z = (float)rotation[3];
*w = (float)rotation[0];
}
void physics_body_rotation_set(Rigidbody body, float x, float y, float z, float w)
{
dReal rotation[4] = { 0.f };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dBodySetQuaternion(body, &rotation[0]);
dBodyEnable(body);
dReal rotation[4] = { 0.f };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dBodySetQuaternion(body, &rotation[0]);
dBodyEnable(body);
}
void physics_near_callback(void* data, dGeomID o1, dGeomID o2)
{
assert(o1);
assert(o2);
assert(o1);
assert(o2);
//if(dGeomIsSpace(o1) || dGeomIsSpace(o2))
//{
// fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2);
// // colliding a space with something
// dSpaceCollide2(o1, o2, data, &physics_near_callback);
// // Note we do not want to test intersections within a space,
// // only between spaces.
// return;
//}
//if(dGeomIsSpace(o1) || dGeomIsSpace(o2))
//{
// fprintf(stderr, "testing space %p %p\n", (void*)o1, (void*)o2);
// // colliding a space with something
// dSpaceCollide2(o1, o2, data, &physics_near_callback);
// // Note we do not want to test intersections within a space,
// // only between spaces.
// 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
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
// exit without doing anything if the two bodies are connected by a joint
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))
return;
if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))
return;
if(o1 == o2)
log_message("same body!");
if(o1 == o2)
log_message("same body!");
#define MAX_CONTACTS 8
dContact contact[MAX_CONTACTS];
for (int i = 0; i < MAX_CONTACTS; i++)
{
//contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.1;
contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 0.01;
}
int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact));
if(n > 0)
{
Physics.on_collision(b1, b2);
for(int i = 0; i < n; i++)
{
//contact[i].surface.slip1 = 0.7;
//contact[i].surface.slip2 = 0.7;
//contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
//contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.soft_erp = 0.96;
//contact[i].surface.soft_cfm = 0.04;
dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]);
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
dContact contact[MAX_CONTACTS];
for (int i = 0; i < MAX_CONTACTS; i++)
{
//contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.1;
contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 0.01;
}
int n = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(dContact));
if(n > 0)
{
Physics.on_collision(b1, b2);
for(int i = 0; i < n; i++)
{
//contact[i].surface.slip1 = 0.7;
//contact[i].surface.slip2 = 0.7;
//contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
//contact[i].surface.mu = 50.0; // was: dInfinity
//contact[i].surface.soft_erp = 0.96;
//contact[i].surface.soft_cfm = 0.04;
dJointID c = dJointCreateContact(Physics.world, Physics.contact_group, &contact[i]);
dJointAttach(c, b1, b2);
/*dGeomGetBody(contact[i].geom.g1),
dGeomGetBody(contact[i].geom.g2));*/
}
}
}
Collision_Shape physics_body_cs_get(Rigidbody body)
{
return dBodyGetFirstGeom(body);
return dBodyGetFirstGeom(body);
}
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)
{
dGeomID plane = dCreatePlane(Physics.space, a, b, c, d);
return plane;
dGeomID plane = dCreatePlane(Physics.space, a, b, c, d);
return plane;
}
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)
{
assert(a && b && c && d);
*a = *b = *c = *d = 0.f;
float result[4] = { 0.f };
dGeomPlaneGetParams(shape, result);
*a = result[0];
*b = result[1];
*c = result[2];
*d = result[3];
assert(a && b && c && d);
*a = *b = *c = *d = 0.f;
float result[4] = { 0.f };
dGeomPlaneGetParams(shape, result);
*a = result[0];
*b = result[1];
*c = result[2];
*d = result[3];
}
Collision_Shape physics_cs_box_create(float x, float y, float z)
{
dGeomID box = dCreateBox(Physics.space, x, y, z);
if(!box)
{
log_error("physics:cs_box_create", "Failed to create box collision shape");
}
return box;
dGeomID box = dCreateBox(Physics.space, x, y, z);
if(!box)
{
log_error("physics:cs_box_create", "Failed to create box collision shape");
}
return box;
}
int physics_cs_type_get(Collision_Shape shape)
{
int geom_class = dGeomGetClass(shape);
switch(geom_class)
{
case dBoxClass: return CST_BOX;
case dSphereClass: return CST_SPHERE;
case dCylinderClass: return CST_CYLINDER;
case dTriMeshClass: return CST_TRIMESH;
case dPlaneClass: return CST_PLANE;
default: return CST_UNKNOWN;
}
int geom_class = dGeomGetClass(shape);
switch(geom_class)
{
case dBoxClass: return CST_BOX;
case dSphereClass: return CST_SPHERE;
case dCylinderClass: return CST_CYLINDER;
case dTriMeshClass: return CST_TRIMESH;
case dPlaneClass: return CST_PLANE;
default: return CST_UNKNOWN;
}
}
void physics_cs_box_params_get(Collision_Shape shape, float* x, float* y, float* z)
{
assert(x && y && z);
*x = *y = *z = 0.f;
dReal lengths[3] = { 0 };
dGeomBoxGetLengths(shape, &lengths[0]);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
assert(x && y && z);
*x = *y = *z = 0.f;
dReal lengths[3] = { 0 };
dGeomBoxGetLengths(shape, &lengths[0]);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
}
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)
{
dGeomID sphere = dCreateSphere(Physics.space, radius);
if(!sphere)
{
log_error("physics:cs_sphere_create", "Failed to create sphere collision shape");
}
return sphere;
dGeomID sphere = dCreateSphere(Physics.space, radius);
if(!sphere)
{
log_error("physics:cs_sphere_create", "Failed to create sphere collision shape");
}
return sphere;
}
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)
{
dGeomSphereSetRadius(shape, radius);
dGeomSphereSetRadius(shape, radius);
}
Collision_Shape physics_cs_capsule_create(float radius, float length)
{
dGeomID capsule = dCreateCapsule(Physics.space, radius, length);
if(!capsule)
{
log_error("physics:cs_capsule_create", "Failed to create capsule collision shape");
}
return capsule;
dGeomID capsule = dCreateCapsule(Physics.space, radius, length);
if(!capsule)
{
log_error("physics:cs_capsule_create", "Failed to create capsule collision shape");
}
return capsule;
}
void physics_cs_capsule_params_get(Collision_Shape shape, float* radius, float* length)
{
assert(radius && length);
*radius = *length = 0.f;
dGeomCapsuleGetParams(shape, radius, length);
assert(radius && length);
*radius = *length = 0.f;
dGeomCapsuleGetParams(shape, radius, 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)
{
assert(x && y && z);
*x = *y = *z = 0.f;
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
float lengths[3] = { 0.f };
dGeomBoxGetLengths(box, lengths);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
assert(x && y && z);
*x = *y = *z = 0.f;
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
float lengths[3] = { 0.f };
dGeomBoxGetLengths(box, lengths);
*x = lengths[0];
*y = lengths[1];
*z = lengths[2];
}
void physics_box_params_set(Rigidbody body, float x, float y, float z)
{
assert(x && y && z);
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
dGeomBoxSetLengths(box, x, y, z);
assert(x && y && z);
dGeomID box = dBodyGetFirstGeom(body);
if(box == 0)
{
log_error("physics:box_get_params", "Body has invalid geometry");
return;
}
dGeomBoxSetLengths(box, x, y, z);
}
Rigidbody physics_body_box_create(float x, float y, float z)
{
Rigidbody body = NULL;
Collision_Shape box = physics_cs_box_create(x, y, z);
if(box)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, box);
dBodySetMovedCallback(body, Physics.on_move);
}
Rigidbody body = NULL;
Collision_Shape box = physics_cs_box_create(x, y, z);
if(box)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, box);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
return body;
}
Rigidbody physics_body_sphere_create(float radius)
{
Rigidbody body = NULL;
Collision_Shape sphere = physics_cs_sphere_create(radius);
if(sphere)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, sphere);
dBodySetMovedCallback(body, Physics.on_move);
}
Rigidbody body = NULL;
Collision_Shape sphere = physics_cs_sphere_create(radius);
if(sphere)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, sphere);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
return body;
}
Rigidbody physics_body_capsule_create(float radius, float length)
{
Rigidbody body = NULL;
Collision_Shape capsule = physics_cs_capsule_create(radius, length);
if(capsule)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, capsule);
dBodySetMovedCallback(body, Physics.on_move);
}
Rigidbody body = NULL;
Collision_Shape capsule = physics_cs_capsule_create(radius, length);
if(capsule)
{
body = dBodyCreate(Physics.world);
physics_body_cs_set(body, capsule);
dBodySetMovedCallback(body, Physics.on_move);
}
return body;
return body;
}
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)
{
Physics.on_move = callback;
Physics.on_move = callback;
}
void physics_body_set_collision_callback(RigidbodyColCB callback)
{
Physics.on_collision = callback;
Physics.on_collision = callback;
}
float physics_body_mass_get(Rigidbody body)
{
return 0.0f;
return 0.0f;
}
void physics_body_mass_set(Rigidbody body, float mass)
{
/*dMass dmass;
dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/
/*dMass dmass;
dMassAdjust(&dmass, mass);
dBodySetMass(body, &dmass);*/
}
void physics_body_data_set(Rigidbody body, void * data)
{
dBodySetData(body, data);
dBodySetData(body, data);
}
void * physics_body_data_get(Rigidbody body)
{
return dBodyGetData(body);
return dBodyGetData(body);
}
void physics_body_kinematic_set(Rigidbody body)
{
dBodySetKinematic(body);
dBodySetKinematic(body);
}
void physics_cs_ray_hit_callback(void* data, dGeomID geom1, dGeomID geom2)
{
dContact contact;
if(dCollide(geom1, geom2, 1, &contact.geom, sizeof(contact)) == 1)
dContact contact;
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;
Rigidbody body = dGeomGetBody(geom2);
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;
}
int entity_id = (int)dGeomGetData(geom2);
if(entity_id != 0) rayhit->entity_id = entity_id;
}
}
}
bool physics_cs_ray_cast(Collision_Shape ray,
struct Raycast_Hit* out_rayhit,
float pos_x, float pos_y, float pos_z,
float dir_x, float dir_y, float dir_z)
struct Raycast_Hit* out_rayhit,
float pos_x, float pos_y, float pos_z,
float dir_x, float dir_y, float dir_z)
{
assert(out_rayhit);
out_rayhit->entity_id = -1;
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);
return out_rayhit->entity_id == -1 ? false : true;
assert(out_rayhit);
out_rayhit->entity_id = -1;
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);
return out_rayhit->entity_id == -1 ? false : true;
}
void physics_cs_position_get(Collision_Shape shape, float * x, float * y, float * z)
{
assert(x && y && z);
if(dGeomGetClass(shape) == dPlaneClass)
{
*x = 0.f;
*y = 0.f;
*z = 0.f;
return;
}
assert(x && y && z);
if(dGeomGetClass(shape) == dPlaneClass)
{
*x = 0.f;
*y = 0.f;
*z = 0.f;
return;
}
const dReal* pos = dGeomGetPosition(shape);
*x = pos[0];
*y = pos[1];
*z = pos[2];
const dReal* pos = dGeomGetPosition(shape);
*x = pos[0];
*y = pos[1];
*z = pos[2];
}
void physics_cs_position_set(Collision_Shape shape, float x, float y, float z)
{
if(dGeomGetClass(shape) == dPlaneClass)
return;
if(dGeomGetClass(shape) == dPlaneClass)
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)
{
assert(x && y && z && w);
assert(x && y && z && w);
if(dGeomGetClass(shape) == dPlaneClass)
{
*x = 0.f;
*y = 0.f;
*z = 0.f;
*w = 1.f;
return;
}
if(dGeomGetClass(shape) == dPlaneClass)
{
*x = 0.f;
*y = 0.f;
*z = 0.f;
*w = 1.f;
return;
}
dReal rotation[4] = { 1, 0, 0, 0 };
dGeomGetQuaternion(shape, &rotation[0]);
*x = rotation[1];
*y = rotation[2];
*z = rotation[3];
*w = rotation[0];
dReal rotation[4] = { 1, 0, 0, 0 };
dGeomGetQuaternion(shape, &rotation[0]);
*x = rotation[1];
*y = rotation[2];
*z = rotation[3];
*w = rotation[0];
}
void physics_cs_rotation_set(Collision_Shape shape, float x, float y, float z, float w)
{
if(dGeomGetClass(shape) == dPlaneClass)
return;
if(dGeomGetClass(shape) == dPlaneClass)
return;
dReal rotation[4] = { 0.f };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dGeomSetQuaternion(shape, &rotation[0]);
dReal rotation[4] = { 0.f };
rotation[1] = x;
rotation[2] = y;
rotation[3] = z;
rotation[0] = w;
dGeomSetQuaternion(shape, &rotation[0]);
}
Collision_Shape physics_cs_ray_create(float length, bool first_contact, bool backface_cull)
{
dGeomID ray = dCreateRay(Physics.space, length);
dGeomRaySetParams(ray, first_contact, backface_cull);
return ray;
dGeomID ray = dCreateRay(Physics.space, length);
dGeomRaySetParams(ray, first_contact, backface_cull);
return ray;
}
void physics_body_remove(Rigidbody body)
{
dGeomID shape = dBodyGetFirstGeom(body);
if(shape)
physics_cs_remove(shape);
dBodyDestroy(body);
dGeomID shape = dBodyGetFirstGeom(body);
if(shape)
physics_cs_remove(shape);
dBodyDestroy(body);
}
void physics_cs_remove(Collision_Shape shape)
{
dGeomDestroy(shape);
dGeomDestroy(shape);
}
void physics_cs_data_set(Collision_Shape shape, void* data)
{
assert(shape);
dGeomSetData(shape, data);
assert(shape);
dGeomSetData(shape, data);
}
void* physics_cs_data_get(Collision_Shape shape)
{
assert(shape);
return dGeomGetData(shape);
}
assert(shape);
return dGeomGetData(shape);
}

@ -13,19 +13,19 @@
struct Window
{
void* sdl_window;
SDL_GLContext gl_context;
int is_fullscreen;
void* sdl_window;
SDL_GLContext gl_context;
int is_fullscreen;
};
struct Platform_State
{
Keyboard_Event_Func on_keyboard_func;
Mousebutton_Event_Func on_mousebutton_func;
Mousemotion_Event_Func on_mousemotion_func;
Mousewheel_Event_Func on_mousewheel_func;
Windowresize_Event_Func on_windowresize_func;
Textinput_Event_Func on_textinput_func;
Keyboard_Event_Func on_keyboard_func;
Mousebutton_Event_Func on_mousebutton_func;
Mousemotion_Event_Func on_mousemotion_func;
Mousewheel_Event_Func on_mousewheel_func;
Windowresize_Event_Func on_windowresize_func;
Textinput_Event_Func on_textinput_func;
};
/* 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* new_window = NULL;
struct Window* new_window = NULL;
if(!new_window)
{
new_window = malloc(sizeof(*new_window));
if(!new_window)
{
new_window = malloc(sizeof(*new_window));
if(!new_window)
{
log_error("window_create", "Out of memory");
return NULL;
}
new_window->sdl_window = NULL;
new_window->gl_context = NULL;
new_window->is_fullscreen = 0;
log_error("window_create", "Out of memory");
return NULL;
}
new_window->sdl_window = NULL;
new_window->gl_context = NULL;
new_window->is_fullscreen = 0;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if(msaa)
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels);
}
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_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_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_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if(msaa)
{
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, msaa);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_levels);
}
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_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_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
#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
SDL_Window* sdl_window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_OPENGL |
SDL_WINDOW_RESIZABLE |
SDL_WINDOW_INPUT_FOCUS |
SDL_WINDOW_MOUSE_FOCUS);
if(!sdl_window)
{
log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError());
free(new_window);
new_window = NULL;
return new_window;
}
SDL_Window* sdl_window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_OPENGL |
SDL_WINDOW_RESIZABLE |
SDL_WINDOW_INPUT_FOCUS |
SDL_WINDOW_MOUSE_FOCUS);
if(!sdl_window)
{
log_error("window_create:SDL_CreateWindow", "Could not create window : %s", SDL_GetError());
free(new_window);
new_window = NULL;
return new_window;
}
new_window->sdl_window = sdl_window;
SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window);
if(!gl_context)
{
log_error("window_create:SDL_GL_CreateContext", "Failed to create GL context : %s", SDL_GetError());
new_window->sdl_window = sdl_window;
SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window);
if(!gl_context)
{
log_error("window_create:SDL_GL_CreateContext", "Failed to create GL context : %s", SDL_GetError());
window_destroy(new_window);
free(new_window);
new_window = NULL;
return new_window;
}
new_window->gl_context = gl_context;
SDL_Window* current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext current_context = SDL_GL_GetCurrentContext();
SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context);
SDL_GL_SetSwapInterval(1); /* 0: Vsync disabled, 1: Vsync enabled*/
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);
free(new_window);
new_window = NULL;
return new_window;
}
new_window->gl_context = gl_context;
SDL_Window* current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext current_context = SDL_GL_GetCurrentContext();
SDL_GL_MakeCurrent((SDL_Window*)new_window->sdl_window, new_window->gl_context);
SDL_GL_SetSwapInterval(1); /* 0: Vsync disabled, 1: Vsync enabled*/
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 success = 0;
int rc = SDL_SetWindowFullscreen(window->sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if(rc == 0)
{
window->is_fullscreen = fullscreen ? 1 : 0;
success = 1;
log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed");
int w, h;
window_get_size(window, &w, &h);
log_message("Window size : %dx%d", w, h);
window_get_drawable_size(window, &w, &h);
log_message("Drawable size : %dx%d", w, h);
}
else
{
log_error("platform:window_fullscreen", "window_fullscreen_set failed, %s", SDL_GetError());
}
return success;
int success = 0;
int rc = SDL_SetWindowFullscreen(window->sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if(rc == 0)
{
window->is_fullscreen = fullscreen ? 1 : 0;
success = 1;
log_message("Window set to %s mode", fullscreen ? "fullscreen" : "windowed");
int w, h;
window_get_size(window, &w, &h);
log_message("Window size : %dx%d", w, h);
window_get_drawable_size(window, &w, &h);
log_message("Drawable size : %dx%d", w, h);
}
else
{
log_error("platform:window_fullscreen", "window_fullscreen_set failed, %s", SDL_GetError());
}
return success;
}
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)
{
SDL_ShowWindow((SDL_Window*)window->sdl_window);
SDL_ShowWindow((SDL_Window*)window->sdl_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)
{
SDL_RaiseWindow((SDL_Window*)window->sdl_window);
SDL_RaiseWindow((SDL_Window*)window->sdl_window);
}
void window_destroy(struct Window* window)
{
if(window->gl_context) SDL_GL_DeleteContext(window->gl_context);
SDL_DestroyWindow((SDL_Window*)window->sdl_window);
if(window->gl_context) SDL_GL_DeleteContext(window->gl_context);
SDL_DestroyWindow((SDL_Window*)window->sdl_window);
}
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)
{
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)
{
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)
{
SDL_GL_SwapWindow(window->sdl_window);
SDL_GL_SwapWindow(window->sdl_window);
}
bool platform_init(void)
{
bool success = true;
if(SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0)
{
{
success = false;
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0)
log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError());
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0)
log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError());
}
else
{
platform_state = malloc(sizeof(*platform_state));
if(!platform_state)
{
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0)
log_to_stdout("platform_init", "Could not create platform state, out of memory");
success = false;
}
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
{
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;
}
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()
@ -234,228 +234,228 @@ bool platform_init_video()
void platform_cleanup(void)
{
if(platform_state) free(platform_state);
platform_state = NULL;
if(platform_state) free(platform_state);
platform_state = NULL;
SDL_VideoQuit();
SDL_Quit();
SDL_Quit();
}
void platform_poll_events(bool* out_quit)
{
static SDL_Event event;
while(SDL_PollEvent(&event) != 0)
static SDL_Event event;
while(SDL_PollEvent(&event) != 0)
{
switch(event.type)
{
case SDL_QUIT:
*out_quit = 1;
break;
case SDL_KEYDOWN: case SDL_KEYUP:
{
int scancode = event.key.keysym.scancode;
int key = event.key.keysym.sym;
int state = event.key.state;
int repeat = event.key.repeat;
int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0;
int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0;
int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0;
platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt);
//log_message("Key name : %s", SDL_GetKeyName(key));
break;
}
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
{
int button = event.button.button;
int state = event.button.state;
int num_clicks = event.button.clicks;
int x = event.button.x;
int y = event.button.y;
platform_state->on_mousebutton_func(button, state, x, y, num_clicks);
break;
}
case SDL_MOUSEMOTION:
{
switch(event.type)
{
case SDL_QUIT:
*out_quit = 1;
break;
case SDL_KEYDOWN: case SDL_KEYUP:
{
int scancode = event.key.keysym.scancode;
int key = event.key.keysym.sym;
int state = event.key.state;
int repeat = event.key.repeat;
int mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? 1 : 0;
int mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? 1 : 0;
int mod_alt = (event.key.keysym.mod & KMOD_ALT) ? 1 : 0;
platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt);
//log_message("Key name : %s", SDL_GetKeyName(key));
break;
}
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
{
int button = event.button.button;
int state = event.button.state;
int num_clicks = event.button.clicks;
int x = event.button.x;
int y = event.button.y;
platform_state->on_mousebutton_func(button, state, x, y, num_clicks);
break;
}
case SDL_MOUSEMOTION:
{
int xrel = event.motion.xrel;
int yrel = event.motion.yrel;
int x = event.motion.x;
int y = event.motion.y;
platform_state->on_mousemotion_func(x, y, xrel, yrel);
break;
}
case SDL_MOUSEWHEEL:
{
int x = event.wheel.x;
int y = event.wheel.y;
platform_state->on_mousewheel_func(x, y);
break;
}
case SDL_TEXTINPUT:
{
platform_state->on_textinput_func(event.text.text);
break;
}
case SDL_WINDOWEVENT:
{
if(event.window.event == SDL_WINDOWEVENT_RESIZED)
{
platform_state->on_windowresize_func(event.window.data1, event.window.data2);
}
}
break;
}
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;
}
}
}
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)
{
platform_state->on_mousebutton_func = func;
platform_state->on_mousebutton_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)
{
platform_state->on_mousewheel_func = func;
platform_state->on_mousewheel_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)
{
platform_state->on_windowresize_func = func;
platform_state->on_windowresize_func = func;
}
int platform_is_key_pressed(int key)
{
/* Returns 1 if key is pressed, 0 otherwise */
const Uint8* keyboard_state = SDL_GetKeyboardState(NULL);
return keyboard_state[SDL_GetScancodeFromKey(key)];
/* Returns 1 if key is pressed, 0 otherwise */
const Uint8* keyboard_state = SDL_GetKeyboardState(NULL);
return keyboard_state[SDL_GetScancodeFromKey(key)];
}
int platform_mousebutton_state_get(uint button)
{
int pressed = 0;
uint32 current_button_state = SDL_GetMouseState(NULL, NULL);
if((current_button_state & SDL_BUTTON(button))) pressed = 1;
return pressed;
int pressed = 0;
uint32 current_button_state = SDL_GetMouseState(NULL, NULL);
if((current_button_state & SDL_BUTTON(button))) pressed = 1;
return pressed;
}
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)
{
SDL_WarpMouseInWindow(window->sdl_window, x, y);
SDL_WarpMouseInWindow(window->sdl_window, x, 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)
{
SDL_SetRelativeMouseMode(relative_mode ? SDL_TRUE : SDL_FALSE);
SDL_SetRelativeMouseMode(relative_mode ? SDL_TRUE : SDL_FALSE);
}
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)
{
return SDL_GetTicks();
return SDL_GetTicks();
}
void platform_mouse_delta_get(int* x, int* y)
{
SDL_GetRelativeMouseState(x, y);
SDL_GetRelativeMouseState(x, y);
}
char* platform_install_directory_get(void)
{
char* returned_path = SDL_GetBasePath();
char* path = NULL;
if(returned_path)
{
path = str_new(returned_path);
SDL_free(returned_path);
}
return path;
char* returned_path = SDL_GetBasePath();
char* path = NULL;
if(returned_path)
{
path = str_new(returned_path);
SDL_free(returned_path);
}
return path;
}
void platform_clipboard_text_set(const char* text)
{
SDL_SetClipboardText(text);
SDL_SetClipboardText(text);
}
char* platform_clipboard_text_get(void)
{
char* returned_text = SDL_GetClipboardText();
char* text = NULL;
if(returned_text)
{
text = str_new(returned_text);
SDL_free(returned_text);
}
return text;
char* returned_text = SDL_GetClipboardText();
char* text = NULL;
if(returned_text)
{
text = str_new(returned_text);
SDL_free(returned_text);
}
return text;
}
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 */
#define max_name_len 30
char trimmed_key_name[max_name_len] = {'\0'};
/* Remove leading/trailing spaces, preserve spaces in-between */
#define max_name_len 30
char trimmed_key_name[max_name_len] = {'\0'};
int start = 0;
while(isspace(key_name[start]) != 0) start++;
int start = 0;
while(isspace(key_name[start]) != 0) start++;
int end = strlen(key_name) - 1;
while(isspace(key_name[end]) != 0) end--;
size_t end = strlen(key_name) - 1;
while(isspace(key_name[end]) != 0) end--;
strncpy(trimmed_key_name, &key_name[start], (end - start) + 1);
int key = SDL_GetKeyFromName(trimmed_key_name);
/*if(key == SDLK_UNKNOWN)
log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError());*/
return key;
strncpy(trimmed_key_name, &key_name[start], (end - start) + 1);
int key = SDL_GetKeyFromName(trimmed_key_name);
/*if(key == SDLK_UNKNOWN)
log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError());*/
return key;
}
const char* platform_key_name_get(int key)
{
if(key < 0) return "SDLK_UNKNOWN";
return SDL_GetKeyName(key);
if(key < 0) return "SDLK_UNKNOWN";
return SDL_GetKeyName(key);
}
char* platform_user_directory_get(const char* organization, const char* application)
{
char* user_directory = NULL;
char* temp_path = SDL_GetPrefPath(organization, application);
if(temp_path)
{
user_directory = str_new(temp_path);
SDL_free(temp_path);
}
else
{
char* user_directory = NULL;
char* temp_path = SDL_GetPrefPath(organization, application);
if(temp_path)
{
user_directory = str_new(temp_path);
SDL_free(temp_path);
}
else
{
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)
@ -469,7 +469,7 @@ void* platform_load_library(const char *name)
#elif defined(_MSC_VER)
snprintf(lib_name, MAX_LIB_NAME_LEN, "%s.dll", name);
#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
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());

@ -21,224 +21,224 @@ static void update_frustum(struct Camera* camera);
void camera_reset(struct Camera* camera)
{
if(camera->fbo != -1) framebuffer_remove(camera->fbo);
if(camera->render_tex != -1) texture_remove(camera->render_tex);
if(camera->depth_tex != -1) texture_remove(camera->depth_tex);
camera->fbo = camera->render_tex = camera->depth_tex = -1;
camera->ortho = camera->resizeable = false;
camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f;
mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat);
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->clear_color, 0.f, 1.f, 0.f, 1.0);
if(camera->fbo != -1) framebuffer_remove(camera->fbo);
if(camera->render_tex != -1) texture_remove(camera->render_tex);
if(camera->depth_tex != -1) texture_remove(camera->depth_tex);
camera->fbo = camera->render_tex = camera->depth_tex = -1;
camera->ortho = camera->resizeable = false;
camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f;
mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat);
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->clear_color, 0.f, 1.f, 0.f, 1.0);
}
void camera_init(struct Camera* camera, int width, int height)
{
camera->base.type = ET_CAMERA;
camera->fbo = -1;
camera->render_tex = -1;
camera->depth_tex = -1;
camera->farz = 1000.f;
camera->nearz = 0.1f;
camera->fov = 60.f;
camera->ortho = false;
camera->resizeable = true;
camera->zoom = 1.f;
float aspect_ratio = (float)width / (float)height;
camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio;
mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(camera);
camera_update_proj(camera);
vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f);
camera->base.type = ET_CAMERA;
camera->fbo = -1;
camera->render_tex = -1;
camera->depth_tex = -1;
camera->farz = 1000.f;
camera->nearz = 0.1f;
camera->fov = 60.f;
camera->ortho = false;
camera->resizeable = true;
camera->zoom = 1.f;
float aspect_ratio = (float)width / (float)height;
camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio;
mat4_identity(&camera->view_mat);
mat4_identity(&camera->proj_mat);
mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(camera);
camera_update_proj(camera);
vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f);
}
void camera_update_view_proj(struct Camera* camera)
{
mat4_identity(&camera->view_proj_mat);
mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat);
update_frustum(camera);
mat4_identity(&camera->view_proj_mat);
mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat);
update_frustum(camera);
}
void camera_update_view(struct Camera* camera)
{
vec3 lookat = {0.f, 0.f, 0.f};
vec3 up = {0.f, 0.f, 0.f};
vec3 position = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(&camera->base, &lookat);
transform_get_absolute_up(&camera->base, &up);
transform_get_absolute_position(&camera->base, &position);
mat4_lookat(&camera->view_mat, &position, &lookat, &up);
camera_update_view_proj(&camera->base);
vec3 lookat = {0.f, 0.f, 0.f};
vec3 up = {0.f, 0.f, 0.f};
vec3 position = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(&camera->base, &lookat);
transform_get_absolute_up(&camera->base, &up);
transform_get_absolute_position(&camera->base, &position);
mat4_lookat(&camera->view_mat, &position, &lookat, &up);
camera_update_view_proj(camera);
}
void camera_update_proj(struct Camera* camera)
{
if(!camera->ortho)
{
mat4_perspective(&camera->proj_mat,
camera->fov / camera->zoom,
camera->aspect_ratio,
camera->nearz,
camera->farz);
}
else
{
int width, height;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
mat4_ortho(&camera->proj_mat,
-width / camera->zoom,
width / camera->zoom,
height / camera->zoom,
-height / camera->zoom,
camera->nearz,
camera->farz);
}
camera_update_view_proj(camera);
if(!camera->ortho)
{
mat4_perspective(&camera->proj_mat,
camera->fov / camera->zoom,
camera->aspect_ratio,
camera->nearz,
camera->farz);
}
else
{
int width, height;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
mat4_ortho(&camera->proj_mat,
-width / camera->zoom,
width / camera->zoom,
height / camera->zoom,
-height / camera->zoom,
camera->nearz,
camera->farz);
}
camera_update_view_proj(camera);
}
void camera_attach_fbo(struct Camera* camera,
int width,
int height,
bool has_depth,
bool has_color,
bool resizeable)
int width,
int height,
bool has_depth,
bool has_color,
bool resizeable)
{
assert(width > 0 && height > 0);
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)
assert(width > 0 && height > 0);
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)
{
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);
}
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);
}
else
if(has_depth)
{
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)
{
assert(camera);
float* mvp = &camera->view_proj_mat.mat[0];
assert(camera);
float* mvp = &camera->view_proj_mat.mat[0];
camera->frustum[FP_LEFT].x = mvp[3] + mvp[0];
camera->frustum[FP_LEFT].y = mvp[7] + mvp[4];
camera->frustum[FP_LEFT].z = mvp[11] + mvp[2];
camera->frustum[FP_LEFT].w = mvp[15] + mvp[12];
camera->frustum[FP_LEFT].x = mvp[3] + mvp[0];
camera->frustum[FP_LEFT].y = mvp[7] + mvp[4];
camera->frustum[FP_LEFT].z = mvp[11] + mvp[2];
camera->frustum[FP_LEFT].w = mvp[15] + mvp[12];
camera->frustum[FP_RIGHT].x = mvp[3] - mvp[0];
camera->frustum[FP_RIGHT].y = mvp[7] - mvp[4];
camera->frustum[FP_RIGHT].z = mvp[11] - mvp[8];
camera->frustum[FP_RIGHT].w = mvp[15] - mvp[12];
camera->frustum[FP_RIGHT].x = mvp[3] - mvp[0];
camera->frustum[FP_RIGHT].y = mvp[7] - mvp[4];
camera->frustum[FP_RIGHT].z = mvp[11] - mvp[8];
camera->frustum[FP_RIGHT].w = mvp[15] - mvp[12];
camera->frustum[FP_BOTTOM].x = mvp[3] + mvp[1];
camera->frustum[FP_BOTTOM].y = mvp[11] + mvp[5];
camera->frustum[FP_BOTTOM].z = mvp[11] + mvp[9];
camera->frustum[FP_BOTTOM].w = mvp[15] + mvp[13];
camera->frustum[FP_BOTTOM].x = mvp[3] + mvp[1];
camera->frustum[FP_BOTTOM].y = mvp[11] + mvp[5];
camera->frustum[FP_BOTTOM].z = mvp[11] + mvp[9];
camera->frustum[FP_BOTTOM].w = mvp[15] + mvp[13];
camera->frustum[FP_TOP].x = mvp[3] - mvp[1];
camera->frustum[FP_TOP].y = mvp[7] - mvp[5];
camera->frustum[FP_TOP].z = mvp[11] - mvp[9];
camera->frustum[FP_TOP].w = mvp[15] - mvp[13];
camera->frustum[FP_TOP].x = mvp[3] - mvp[1];
camera->frustum[FP_TOP].y = mvp[7] - mvp[5];
camera->frustum[FP_TOP].z = mvp[11] - mvp[9];
camera->frustum[FP_TOP].w = mvp[15] - mvp[13];
camera->frustum[FP_NEAR].x = mvp[3] + mvp[2];
camera->frustum[FP_NEAR].y = mvp[7] + mvp[6];
camera->frustum[FP_NEAR].z = mvp[11] + mvp[10];
camera->frustum[FP_NEAR].w = mvp[15] + mvp[14];
camera->frustum[FP_NEAR].x = mvp[3] + mvp[2];
camera->frustum[FP_NEAR].y = mvp[7] + mvp[6];
camera->frustum[FP_NEAR].z = mvp[11] + mvp[10];
camera->frustum[FP_NEAR].w = mvp[15] + mvp[14];
camera->frustum[FP_FAR].x = mvp[3] - mvp[2];
camera->frustum[FP_FAR].y = mvp[7] - mvp[6];
camera->frustum[FP_FAR].z = mvp[11] - mvp[10];
camera->frustum[FP_FAR].w = mvp[15] - mvp[14];
for(int i = 0; i < FP_NUM_PLANES; i++)
{
vec3 plane_xyz = {camera->frustum[i].x, camera->frustum[i].y, camera->frustum[i].z};
float length = fabsf(vec3_len(&plane_xyz));
vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length));
}
camera->frustum[FP_FAR].x = mvp[3] - mvp[2];
camera->frustum[FP_FAR].y = mvp[7] - mvp[6];
camera->frustum[FP_FAR].z = mvp[11] - mvp[10];
camera->frustum[FP_FAR].w = mvp[15] - mvp[14];
for(int i = 0; i < FP_NUM_PLANES; i++)
{
vec3 plane_xyz = {camera->frustum[i].x, camera->frustum[i].y, camera->frustum[i].z};
float length = fabsf(vec3_len(&plane_xyz));
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 ray;
struct Ray ray;
int win_width = 0, win_height = 0;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &win_width, &win_height);
int win_width = 0, win_height = 0;
struct Game_State* game_state = game_state_get();
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_y = 1.f - (2.f * (float)mouse_y) / (float)win_height;
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;
vec3 near_point = {0.f};
vec3 far_point = {0.f};
vec3 near_point = {0.f};
vec3 far_point = {0.f};
mat4 inverse_view_proj_mat;
mat4_identity(&inverse_view_proj_mat);
mat4_inverse(&inverse_view_proj_mat, &camera->view_proj_mat);
mat4 inverse_view_proj_mat;
mat4_identity(&inverse_view_proj_mat);
mat4_inverse(&inverse_view_proj_mat, &camera->view_proj_mat);
//Project the near point
quat rot_near = {normalized_x, normalized_y, 0.f, 1.f};
vec4_mul_mat4(&rot_near, &rot_near, &inverse_view_proj_mat);
near_point.x = rot_near.x / rot_near.w;
near_point.y = rot_near.y / rot_near.w;
near_point.z = rot_near.z / rot_near.w;
//Project the near point
quat rot_near = {normalized_x, normalized_y, 0.f, 1.f};
quat_mul_mat4(&rot_near, &rot_near, &inverse_view_proj_mat);
near_point.x = rot_near.x / rot_near.w;
near_point.y = rot_near.y / rot_near.w;
near_point.z = rot_near.z / rot_near.w;
//Project far point
quat rot_far = {normalized_x, normalized_y, 1.f, 1.f};
vec4_mul_mat4(&rot_far, &rot_far, &inverse_view_proj_mat);
far_point.x = rot_far.x / rot_far.w;
far_point.y = rot_far.y / rot_far.w;
far_point.z = rot_far.z / rot_far.w;
//Project far point
quat rot_far = {normalized_x, normalized_y, 1.f, 1.f};
quat_mul_mat4(&rot_far, &rot_far, &inverse_view_proj_mat);
far_point.x = rot_far.x / rot_far.w;
far_point.y = rot_far.y / rot_far.w;
far_point.z = rot_far.z / rot_far.w;
vec3_sub(&ray.direction, &far_point, &near_point);
vec3_norm(&ray.direction, &ray.direction);
vec3_sub(&ray.direction, &far_point, &near_point);
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)
{
assert(console);
assert(console);
console_message_color[CMT_MESSAGE] = nk_rgb(255, 255, 255);
console_message_color[CMT_WARNING] = nk_rgb(255, 255, 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_NONE] = nk_rgb(255, 0, 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_ERROR] = nk_rgb(255, 0, 0);
console_message_color[CMT_COMMAND] = nk_rgb(114, 173, 224);
console_message_color[CMT_NONE] = nk_rgb(255, 0, 255);
console->visible = false;
console->scroll_to_bottom = true;
console->text_region_height = 22.f;
console->line_height = 20.f;
console->current_message_index = -1;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
for(int i = 0; i < MAX_CONSOLE_MESSAGES; i++)
{
memset(console->console_messages[i].message, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->console_messages[i].type = CMT_NONE;
}
console->visible = false;
console->scroll_to_bottom = true;
console->text_region_height = 22.f;
console->line_height = 20.f;
console->current_message_index = -1;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
for(int i = 0; i < MAX_CONSOLE_MESSAGES; i++)
{
memset(console->console_messages[i].message, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->console_messages[i].type = CMT_NONE;
}
}
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)
{
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;
struct Game_State* game_state = game_state_get();
int win_width = 0, win_height = 0;
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;
platform->window.get_drawable_size(game_state->window, &win_width, &win_height);
int half_height = win_height / 2;
if(nk_begin_titled(context, "Console", "Console", nk_recti(0, 0, win_width, half_height), NK_WINDOW_SCROLL_AUTO_HIDE))
if(nk_begin_titled(context, "Console", "Console", nk_recti(0, 0, win_width, half_height), NK_WINDOW_SCROLL_AUTO_HIDE))
{
nk_layout_row_dynamic(context, nk_window_get_height(context) - console->text_region_height * 2, 1);
if(nk_group_begin(context, "Log", NK_WINDOW_BORDER))
{
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 = context->current->layout->at_y;
console->scroll_to_bottom = false;
}
for(int i = 0; i <= console->current_message_index; i++)
{
nk_layout_row_dynamic(context, console->line_height, 1);
nk_labelf_colored(context, NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, console_message_color[console->console_messages[i].type], console->console_messages[i].message);
}
if(console->scroll_to_bottom == true) // scroll console message area to the bottom if required
{
*context->current->layout->offset_y = (nk_uint)context->current->layout->at_y;
console->scroll_to_bottom = false;
}
nk_group_end(context);
}
//Edit-string/Textfield for command
nk_layout_row_dynamic(context, console->text_region_height, 1);
int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER;
nk_edit_focus(context, edit_flags);
int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter);
if(edit_state & NK_EDIT_COMMITED)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
nk_group_end(context);
}
//Edit-string/Textfield for command
nk_layout_row_dynamic(context, console->text_region_height, 1);
int edit_flags = NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD | NK_EDIT_SIG_ENTER;
nk_edit_focus(context, edit_flags);
int edit_state = nk_edit_string_zero_terminated(context, edit_flags, console->console_command_text, MAX_CONSOLE_MESSAGE_LEN, console_filter);
if(edit_state & NK_EDIT_COMMITED)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text);
console->console_messages[console->current_message_index].type = CMT_COMMAND;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->scroll_to_bottom = true;
}
snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "> %s", console->console_command_text);
console->console_messages[console->current_message_index].type = CMT_COMMAND;
memset(console->console_command_text, '\0', MAX_CONSOLE_MESSAGE_LEN);
console->scroll_to_bottom = true;
}
nk_end(context);
}
nk_end(context);
}
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)
{
NK_UNUSED(box);
if(unicode > 128 || unicode == 96) // Ignore tilde or anything other than ascii
return nk_false;
else
return nk_true;
NK_UNUSED(box);
if(unicode > 128 || unicode == 96) // Ignore tilde or anything other than ascii
return nk_false;
else
return nk_true;
}
void console_on_log_message(struct Console* console, const char* message, va_list args)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, message, args);
console->console_messages[console->current_message_index].type = CMT_MESSAGE;
console->scroll_to_bottom = true;
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, message, args);
console->console_messages[console->current_message_index].type = CMT_MESSAGE;
console->scroll_to_bottom = true;
}
void console_on_log_warning(struct Console* console, const char* warning_message, va_list args)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, warning_message, args);
console->console_messages[console->current_message_index].type = CMT_WARNING;
console->scroll_to_bottom = true;
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
vsnprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, warning_message, args);
console->console_messages[console->current_message_index].type = CMT_WARNING;
console->scroll_to_bottom = true;
}
void console_on_log_error(struct Console* console, const char* context, const char* error, va_list args)
{
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
int loc = snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "(%s)", context);
vsnprintf(console->console_messages[console->current_message_index].message + loc, MAX_CONSOLE_MESSAGE_LEN, error, args);
console->console_messages[console->current_message_index].type = CMT_ERROR;
console->scroll_to_bottom = true;
if(++console->current_message_index >= MAX_CONSOLE_MESSAGES)
console->current_message_index = 0;
int loc = snprintf(console->console_messages[console->current_message_index].message, MAX_CONSOLE_MESSAGE_LEN, "(%s)", context);
vsnprintf(console->console_messages[console->current_message_index].message + loc, MAX_CONSOLE_MESSAGE_LEN, error, args);
console->console_messages[console->current_message_index].type = CMT_ERROR;
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
{
ET_NONE,
ET_DEFAULT,
ET_PLAYER,
ET_ROOT,
ET_CAMERA,
ET_LIGHT,
ET_STATIC_MESH,
ET_SOUND_SOURCE,
ET_MAX
ET_NONE,
ET_DEFAULT,
ET_PLAYER,
ET_ROOT,
ET_CAMERA,
ET_LIGHT,
ET_STATIC_MESH,
ET_SOUND_SOURCE,
ET_MAX
};
enum LightType
{
LT_SPOT = 0,
LT_DIR,
LT_POINT,
LT_INVALID,
LT_MAX
LT_SPOT = 0,
LT_DIR,
LT_POINT,
LT_INVALID,
LT_MAX
};
enum Camera_Type
{
CAM_EDITOR = 0,
CAM_GAME,
CAM_MAX
CAM_EDITOR = 0,
CAM_GAME,
CAM_MAX
};
struct Transform
{
vec3 position;
vec3 scale;
quat rotation;
mat4 trans_mat;
bool is_modified;
bool sync_physics;
struct Entity* parent;
struct Entity** children;
vec3 position;
vec3 scale;
quat rotation;
mat4 trans_mat;
bool is_modified;
bool sync_physics;
struct Entity* parent;
struct Entity** children;
};
struct Entity
{
int id;
int type;
char name[MAX_ENTITY_NAME_LEN];
bool marked_for_deletion;
bool active;
bool editor_selected;
struct Transform transform;
int id;
int type;
char name[MAX_ENTITY_NAME_LEN];
bool marked_for_deletion;
bool active;
bool editor_selected;
struct Transform transform;
};
struct Model
{
int geometry_index;
struct Material* material;
struct Variant material_params[MMP_MAX];
int geometry_index;
struct Material* material;
struct Variant material_params[MMP_MAX];
};
struct Sound_Source
{
struct Entity base;
int type;
bool playing;
bool loop;
struct Entity base;
int type;
bool playing;
bool loop;
uint source_instance;
float min_distance;
float max_distance;
float rolloff_factor;
float volume;
int attenuation_type;
struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played
float min_distance;
float max_distance;
float rolloff_factor;
float volume;
int attenuation_type;
struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played
};
struct Camera
{
struct Entity base;
mat4 proj_mat;
mat4 view_mat;
mat4 view_proj_mat;
float fov;
float aspect_ratio;
float nearz;
float farz;
float zoom;
bool ortho;
int fbo;
int render_tex;
int depth_tex;
vec4 clear_color;
vec4 frustum[6];
bool resizeable;
struct Entity base;
mat4 proj_mat;
mat4 view_mat;
mat4 view_proj_mat;
float fov;
float aspect_ratio;
float nearz;
float farz;
float zoom;
bool ortho;
int fbo;
int render_tex;
int depth_tex;
vec4 clear_color;
vec4 frustum[6];
bool resizeable;
};
struct Light
{
struct Entity base;
float outer_angle;
float inner_angle;
float falloff;
float intensity;
vec3 color;
bool cast_shadow;
bool pcf_enabled;
bool valid;
int type;
int radius;
int shadow_map[4];
float depth_bias;
struct Entity base;
float outer_angle;
float inner_angle;
float falloff;
float intensity;
vec3 color;
bool cast_shadow;
bool pcf_enabled;
bool valid;
int type;
int radius;
int shadow_map[4];
float depth_bias;
};
struct Collision
{
Rigidbody rigidbody;
Collision_Shape collision_shape;
Collision_CB on_collision;
Rigidbody rigidbody;
Collision_Shape collision_shape;
Collision_CB on_collision;
};
struct Static_Mesh
{
struct Entity base;
struct Model model;
struct Collision collision;
struct Entity base;
struct Model model;
struct Collision collision;
};
struct Player
{
struct Entity base;
struct Static_Mesh* mesh;
struct Camera* camera_node;
float move_speed;
float move_speed_multiplier;
float turn_speed;
struct Entity base;
struct Static_Mesh* mesh;
struct Camera* camera_node;
float move_speed;
float move_speed_multiplier;
float turn_speed;
};
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
{
int location;
int type;
int location;
int type;
};
enum Mat_Type
{
MAT_BLINN = 0,
MAT_UNSHADED,
MAT_MAX
MAT_BLINN = 0,
MAT_UNSHADED,
MAT_MAX
};
enum Mat_Model_Param
{
MMP_DIFFUSE_TEX = 0,
MMP_DIFFUSE_COL,
MMP_DIFFUSE,
MMP_SPECULAR_STRENGTH,
MMP_SPECULAR,
MMP_MAX
MMP_DIFFUSE_TEX = 0,
MMP_DIFFUSE_COL,
MMP_DIFFUSE,
MMP_SPECULAR_STRENGTH,
MMP_SPECULAR,
MMP_MAX
};
enum Mat_Pipeline_Param
{
MPP_MODEL_MAT = 0,
MPP_INV_MODEL_MAT,
MPP_VIEW_MAT,
MPP_MVP,
MPP_FOG_MODE,
MPP_FOG_DENSITY,
MPP_FOG_START_DIST,
MPP_FOG_MAX_DIST,
MPP_FOG_COLOR,
MPP_CAM_POS,
MPP_TOTAL_LIGHTS,
MPP_AMBIENT_LIGHT,
MPP_MAX
MPP_MODEL_MAT = 0,
MPP_INV_MODEL_MAT,
MPP_VIEW_MAT,
MPP_MVP,
MPP_FOG_MODE,
MPP_FOG_DENSITY,
MPP_FOG_START_DIST,
MPP_FOG_MAX_DIST,
MPP_FOG_COLOR,
MPP_CAM_POS,
MPP_TOTAL_LIGHTS,
MPP_AMBIENT_LIGHT,
MPP_MAX
};
struct Material
{
int type;
int shader;
struct Static_Mesh* registered_static_meshes[MAX_MATERIAL_REGISTERED_STATIC_MESHES];
bool lit;
struct Uniform model_params[MMP_MAX];
struct Uniform pipeline_params[MPP_MAX];
int type;
int shader;
struct Static_Mesh* registered_static_meshes[MAX_MATERIAL_REGISTERED_STATIC_MESHES];
bool lit;
struct Uniform model_params[MMP_MAX];
struct Uniform pipeline_params[MPP_MAX];
};
bool material_init(struct Material* material, int material_type);

@ -6,77 +6,79 @@
#include "../common/common.h"
#include "camera.h"
#include "bounding_volumes.h"
#include "../common/hashmap.h"
#include "../common/log.h"
void player_init(struct Player* player, struct Scene* scene)
{
entity_init(player, "Player", &scene->root_entity);
player->base.active = true;
player->base.id = 1;
player->base.type = ET_PLAYER;
entity_init(player, "Player", &scene->root_entity);
player->base.active = true;
player->base.id = 1;
player->base.type = ET_PLAYER;
struct Hashmap* config = platform->config.get();
player->move_speed = hashmap_int_get(config, "player_move_speed");
player->move_speed_multiplier = hashmap_int_get(config, "player_move_speed_multiplier");
player->turn_speed = hashmap_int_get(config, "player_turn_speed");
struct Hashmap* config = platform->config.get();
player->move_speed = hashmap_int_get(config, "player_move_speed");
player->move_speed_multiplier = hashmap_int_get(config, "player_move_speed_multiplier");
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];
entity_rename(player_camera, "Player_Camera");
player_camera->base.active = true;
player_camera->clear_color.x = 0.6f;
player_camera->clear_color.y = 0.6f;
player_camera->clear_color.z = 0.9f;
player_camera->clear_color.w = 1.f;
player->camera_node = player_camera;
struct Camera* player_camera = &scene->cameras[CAM_GAME];
entity_rename(player_camera, "Player_Camera");
player_camera->base.active = true;
player_camera->clear_color.x = 0.6f;
player_camera->clear_color.y = 0.6f;
player_camera->clear_color.z = 0.9f;
player_camera->clear_color.w = 1.f;
player->camera_node = player_camera;
int render_width = hashmap_int_get(config, "render_width");
int render_height = hashmap_int_get(config, "render_height");
camera_attach_fbo(player_camera, render_width, render_height, true, true, true);
transform_parent_set(player_camera, player, true);
int render_width = hashmap_int_get(config, "render_width");
int render_height = hashmap_int_get(config, "render_height");
camera_attach_fbo(player_camera, render_width, render_height, true, true, true);
transform_parent_set(player_camera, player, true);
vec3 cam_translation = {0.f, 20.f, 2.f};
transform_translate(player_camera, &cam_translation, TS_LOCAL);
vec3 cam_translation = {0.f, 20.f, 2.f};
transform_translate(player_camera, &cam_translation, TS_LOCAL);
vec3 cam_axis = {-1.f, 0.f, 0.f};
transform_rotate(player_camera, &cam_axis, 85.f, TS_LOCAL);
vec3 cam_axis = {-1.f, 0.f, 0.f};
transform_rotate(player_camera, &cam_axis, 85.f, TS_LOCAL);
}
void player_destroy(struct Player* player)
{
entity_reset(player, player->base.id);
player->base.active = false;
entity_reset(player, player->base.id);
player->base.active = false;
}
void player_update(struct Player* player, struct Scene* scene, float dt)
{
float move_speed = player->move_speed;
vec3 offset = {0.f, 0.f, 0.f};
float move_speed = player->move_speed;
vec3 offset = {0.f, 0.f, 0.f};
/* Movement */
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_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_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_Down", KS_PRESSED)) offset.y -= move_speed;
/* Movement */
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_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_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_Down", KS_PRESSED)) offset.y -= move_speed;
vec3_scale(&offset, &offset, dt);
if(offset.x != 0 || offset.y != 0 || offset.z != 0)
{
transform_translate(player, &offset, TS_LOCAL);
}
vec3_scale(&offset, &offset, dt);
if(offset.x != 0 || offset.y != 0 || offset.z != 0)
{
transform_translate(player, &offset, TS_LOCAL);
}
/* Aiming and Projectiles*/
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED))
{
int mouse_x = 0, mouse_y = 0;
platform->mouse_position_get(&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);
/* Aiming and Projectiles*/
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED))
{
int mouse_x = 0, mouse_y = 0;
platform->mouse_position_get(&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);
struct Raycast_Result ray_result;
scene_ray_intersect(scene, &ray, &ray_result);
}
struct Raycast_Result 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)
{
assert(renderer);
assert(renderer);
glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
platform->windowresize_callback_set(on_framebuffer_size_change);
struct Hashmap* cvars = platform->config.get();
renderer->settings.fog.mode = hashmap_int_get(cvars, "fog_mode");
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.max_dist = hashmap_float_get(cvars, "fog_max_dist");
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_physics = hashmap_bool_get(cvars, "debug_draw_physics");
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.ambient_light = hashmap_vec3_get(cvars, "ambient_light");
struct Hashmap* cvars = platform->config.get();
renderer->settings.fog.mode = hashmap_int_get(cvars, "fog_mode");
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.max_dist = hashmap_float_get(cvars, "fog_max_dist");
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_physics = hashmap_bool_get(cvars, "debug_draw_physics");
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.ambient_light = hashmap_vec3_get(cvars, "ambient_light");
/* Quad geometry for final render */
vec3* vertices = array_new(vec3);
vec2* uvs = array_new(vec2);
vec3* normals = array_new(vec3);
uint* indices = array_new(uint);
vec3 temp_v3;
vec2 temp_v2;
/* 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);
/* 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);
/* Uvs */
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 = 1; array_push(uvs, temp_v2, vec2);
temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
/* Indices */
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);
/* Quad geometry for final render */
vec3* vertices = array_new(vec3);
vec2* uvs = array_new(vec2);
vec3* normals = array_new(vec3);
uint* indices = array_new(uint);
vec3 temp_v3;
vec2 temp_v2;
/* 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);
/* 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);
/* Uvs */
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 = 1; array_push(uvs, temp_v2, vec2);
temp_v2.x = 0; temp_v2.y = 1; array_push(uvs, temp_v2, vec2);
/* Indices */
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);
renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL);
array_free(vertices);
array_free(uvs);
array_free(normals);
array_free(indices);
int width = -1, height = -1;
struct Game_State* game_state = game_state_get();
renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL);
array_free(vertices);
array_free(uvs);
array_free(normals);
array_free(indices);
int width = -1, height = -1;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
renderer->def_albedo_tex = texture_create("def_albedo_texture",
TU_DIFFUSE,
width, height,
GL_RGB,
GL_RGB16F,
GL_FLOAT,
NULL);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
renderer->def_depth_tex = texture_create("def_depth_texture",
TU_SHADOWMAP4,
width, height,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT32F,
GL_FLOAT,
NULL);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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_FUNC, GL_LEQUAL);
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_depth_tex, FA_DEPTH_ATTACHMENT);
renderer->composition_shader = shader_create("fbo.vert", "fbo.frag");
renderer->debug_shader = shader_create("debug.vert", "debug.frag");
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_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT);
renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch));
if(!renderer->sprite_batch)
{
log_error("renderer:init", "Failed to allocated sprite batch");
}
else
{
sprite_batch_create(renderer->sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES);
}
im_init();
// Initialize materials
for(int i = 0; i < MAT_MAX; i++)
{
material_init(&renderer->materials[i], i);
}
renderer->def_albedo_tex = texture_create("def_albedo_texture",
TU_DIFFUSE,
width, height,
GL_RGB,
GL_RGB16F,
GL_FLOAT,
NULL);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
renderer->def_depth_tex = texture_create("def_depth_texture",
TU_SHADOWMAP4,
width, height,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT32F,
GL_FLOAT,
NULL);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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_FUNC, GL_LEQUAL);
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_depth_tex, FA_DEPTH_ATTACHMENT);
renderer->composition_shader = shader_create("fbo.vert", "fbo.frag");
renderer->debug_shader = shader_create("debug.vert", "debug.frag");
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_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT);
renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch));
if(!renderer->sprite_batch)
{
log_error("renderer:init", "Failed to allocated sprite batch");
}
else
{
sprite_batch_create(renderer->sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES);
}
im_init();
// Initialize materials
for(int i = 0; i < MAT_MAX; i++)
{
material_init(&renderer->materials[i], i);
}
}
void renderer_draw(struct Renderer* renderer, struct Scene* scene)
{
/* Render each camera output into it's framebuffer or to the default framebuffer */
for(int i = 0; i < MAX_CAMERAS; i++)
/* Render each camera output into it's framebuffer or to the default framebuffer */
for(int i = 0; i < MAX_CAMERAS; i++)
{
struct Camera* camera = &scene->cameras[i];
if(!camera->base.active) continue;
int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo;
framebuffer_bind(fbo);
{
struct Camera* camera = &scene->cameras[i];
if(!camera->base.active) continue;
int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo;
framebuffer_bind(fbo);
glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearColor(camera->clear_color.x,
camera->clear_color.y,
camera->clear_color.z,
camera->clear_color.w);
glEnable(GL_CULL_FACE );
glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static mat4 mvp;
for(int i = 0; i < MAT_MAX; i++)
{
/* for each material, get all the registered models and render them */
struct Material* material = &renderer->materials[i];
GL_CHECK(shader_bind(material->shader));
if(material->lit) /* Set light information */
{
glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearColor(camera->clear_color.x,
camera->clear_color.y,
camera->clear_color.z,
camera->clear_color.w);
glEnable(GL_CULL_FACE );
glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static mat4 mvp;
for(int i = 0; i < MAT_MAX; i++)
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)
{
/* for each material, get all the registered models and render them */
struct Material* material = &renderer->materials[i];
GL_CHECK(shader_bind(material->shader));
if(material->lit) /* Set light information */
{
char uniform_name[MAX_UNIFORM_NAME_LEN];
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
int light_count = -1;
for(int i = 0; i < MAX_LIGHTS; i++)
{
struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */
if(!light->base.active && light->valid) continue;
light_count++;
vec3 light_pos = {0, 0, 0};
transform_get_absolute_position(&light->base, &light_pos);
if(light->type != LT_POINT)
{
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count);
vec3 light_dir = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(&light->base, &light_dir);
vec3_norm(&light_dir, &light_dir);
shader_set_uniform_vec3(material->shader, uniform_name, &light_dir);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
if(light->type != LT_DIR)
{
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light_pos);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->outer_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count);
vec3 light_dir = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(&light->base, &light_dir);
vec3_norm(&light_dir, &light_dir);
shader_set_uniform_vec3(material->shader, uniform_name, &light_dir);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
if(light->type != LT_DIR)
{
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light_pos);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->outer_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->inner_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->inner_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->falloff);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->radius);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->falloff);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->radius);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light->color);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light->color);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->intensity);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->intensity);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->type);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
}
light_count++; // this variable is going to be used for looping an array so increase its length by one
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_TOTAL_LIGHTS].type, material->pipeline_params[MPP_TOTAL_LIGHTS].location, &light_count));
vec3 camera_pos = {0, 0, 0};
transform_get_absolute_position(&camera->base, &camera_pos);
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos));
}
/* Set material pipeline uniforms */
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode));
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density));
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_START_DIST].type, material->pipeline_params[MPP_FOG_START_DIST].location, &renderer->settings.fog.start_dist));
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MAX_DIST].type, material->pipeline_params[MPP_FOG_MAX_DIST].location, &renderer->settings.fog.max_dist));
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color));
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light));
if(material->lit) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat));
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;
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));
}
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();
/* 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));
/* 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);
for(int j = 0; j < MAX_MATERIAL_REGISTERED_STATIC_MESHES; j++)
{
static mat4 mvp;
shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color);
for(int i = 0; i < MAX_STATIC_MESHES; i++)
if(!material->registered_static_meshes[j]) continue;
/* for each registered model, set up uniforms and render */
struct Static_Mesh* mesh = material->registered_static_meshes[j];
struct Geometry* geometry = geom_get(mesh->model.geometry_index);
/* Check if model is in frustum */
vec3 abs_pos, abs_scale;
transform_get_absolute_position(&mesh->base, &abs_pos);
transform_get_absolute_scale(&mesh->base, &abs_scale);
int intersection = bv_intersect_frustum_sphere(&camera->frustum[0], &geometry->bounding_sphere, &abs_pos, &abs_scale);
if(intersection == IT_OUTSIDE)
{
renderer->num_culled++;
continue;
}
else
{
renderer->num_indices += array_len(geometry->indices);
renderer->num_rendered++;
}
/* set material params for the model */
for(int k = 0; k < MMP_MAX; k++)
{
switch(mesh->model.material_params[k].type)
{
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"));
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();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
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);
// Debug Physics render
if(hashmap_bool_get(cvars, "debug_draw_physics"))
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 vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f };
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue;
//Get collision mesh and it's props then render it
vec3 pos = {0.f};
quat rot = {0.f, 0.f, 0.f, 1.f };
if(mesh->collision.rigidbody)
{
platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z);
platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w);
}
else
{
platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z);
platform->physics.cs_rotation_get(mesh->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w);
}
int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape);
switch(collision_shape_type)
{
case CST_SPHERE:
{
float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape);
im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES);
}
break;
case CST_BOX:
{
float x = 0.f, y = 0.f, z = 0.f;
platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z);
im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES);
};
break;
default: break;
}
}
static 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
im_render(active_camera);
//Immediate mode geometry render
im_render(active_camera);
/* Render 2D stuff */
shader_bind(renderer->sprite_batch->shader);
{
static mat4 ortho_mat;
mat4_identity(&ortho_mat);
int width, height;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
/* Render 2D stuff */
shader_bind(renderer->sprite_batch->shader);
{
static mat4 ortho_mat;
mat4_identity(&ortho_mat);
int width, height;
struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height);
mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f);
shader_set_uniform_mat4(renderer->sprite_batch->shader, "mvp", &ortho_mat);
mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f);
shader_set_uniform_mat4(renderer->sprite_batch->shader, "mvp", &ortho_mat);
sprite_batch_render(renderer->sprite_batch);
}
shader_unbind();
sprite_batch_render(renderer->sprite_batch);
}
shader_unbind();
/* Render UI */
gui_render(NK_ANTI_ALIASING_ON);
/* Render UI */
gui_render(NK_ANTI_ALIASING_ON);
}
void renderer_cleanup(struct Renderer* renderer)
{
for(int i = 0; i < MAT_MAX; i++)
{
material_reset(&renderer->materials[i], i);
}
im_cleanup();
sprite_batch_remove(renderer->sprite_batch);
free(renderer->sprite_batch);
geom_remove(renderer->quad_geo);
framebuffer_remove(renderer->def_fbo);
texture_remove(renderer->def_albedo_tex);
texture_remove(renderer->def_depth_tex);
for(int i = 0; i < MAT_MAX; i++)
{
material_reset(&renderer->materials[i]);
}
im_cleanup();
sprite_batch_remove(renderer->sprite_batch);
free(renderer->sprite_batch);
geom_remove(renderer->quad_geo);
framebuffer_remove(renderer->def_fbo);
texture_remove(renderer->def_albedo_tex);
texture_remove(renderer->def_depth_tex);
}
void on_framebuffer_size_change(int width, int height)
{
struct Scene* scene = game_state_get()->scene;
float aspect = (float)width / (float)height;
for(int i = 0; i < MAX_CAMERAS; i++)
{
struct Camera* viewer = &scene->cameras[i];
viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(viewer);
}
struct Scene* scene = game_state_get()->scene;
float aspect = (float)width / (float)height;
for(int i = 0; i < MAX_CAMERAS; i++)
{
struct Camera* viewer = &scene->cameras[i];
viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(viewer);
}
framebuffer_resize_all(width, height);
framebuffer_resize_all(width, height);
}
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)
{
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();
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");
renderer->settings.debug_draw_mode = enabled;
}
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);
}
/* 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) */
/* { */
/* 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
{
FM_NONE = 0,
FM_LINEAR = 1,
FM_EXPONENTIAL = 2,
FM_EXPONENTIAL_SQRD = 3
FM_NONE = 0,
FM_LINEAR = 1,
FM_EXPONENTIAL = 2,
FM_EXPONENTIAL_SQRD = 3
};
struct Fog
{
int mode;
float density;
float start_dist;
float max_dist;
vec3 color;
int mode;
float density;
float start_dist;
float max_dist;
vec3 color;
};
struct Render_Settings
{
struct Fog fog;
vec3 ambient_light;
bool debug_draw_enabled;
vec4 debug_draw_color;
int debug_draw_mode;
bool debug_draw_physics;
struct Fog fog;
vec3 ambient_light;
bool debug_draw_enabled;
vec4 debug_draw_color;
int debug_draw_mode;
bool debug_draw_physics;
};
struct Renderer
{
int def_fbo;
int def_albedo_tex;
int def_depth_tex;
int quad_geo;
int composition_shader;
int debug_shader;
int num_culled , num_rendered , num_indices;
int num_culled_slot, num_rendered_slot, num_indices_slot;
struct Sprite_Batch* sprite_batch;
struct Render_Settings settings;
struct Material materials[MAT_MAX];
int def_fbo;
int def_albedo_tex;
int def_depth_tex;
int quad_geo;
int composition_shader;
int debug_shader;
int num_culled , num_rendered , num_indices;
int num_culled_slot, num_rendered_slot, num_indices_slot;
struct Sprite_Batch* sprite_batch;
struct Render_Settings settings;
struct Material materials[MAT_MAX];
};
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 Render_Settings renderer_profile;
struct Entity root_entity;
struct Player player;
struct Entity entities[MAX_ENTITIES];
struct Static_Mesh static_meshes[MAX_STATIC_MESHES];
struct Camera cameras[MAX_CAMERAS];
struct Light lights[MAX_LIGHTS];
struct Sound_Source sound_sources[MAX_SOUND_SOURCES];
int active_camera_index;
struct Render_Settings renderer_profile;
struct Entity root_entity;
struct Player player;
struct Entity entities[MAX_ENTITIES];
struct Static_Mesh static_meshes[MAX_STATIC_MESHES];
struct Camera cameras[MAX_CAMERAS];
struct Light lights[MAX_LIGHTS];
struct Sound_Source sound_sources[MAX_SOUND_SOURCES];
int active_camera_index;
};
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 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 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);
void scene_entity_remove(struct Scene* scene, struct Entity* entity);

Loading…
Cancel
Save