Phase 1 of the great refactoring complete

dev
shariq 8 years ago
parent ede02d950c
commit 8a44bdf4b1
  1. 57
      orgfile.org
  2. 1
      src/bounding_volumes.c
  3. 182
      src/camera.c
  4. 40
      src/camera.h
  5. 31
      src/components.h
  6. 212
      src/entity.c
  7. 124
      src/entity.h
  8. 80
      src/game.c
  9. 135
      src/light.c
  10. 37
      src/light.h
  11. 1
      src/material.c
  12. 171
      src/model.c
  13. 27
      src/model.h
  14. 1
      src/num_types.h
  15. 31
      src/renderer.c
  16. 19
      src/renderer.h
  17. 54
      src/scene.c
  18. 8
      src/scene.h
  19. 96
      src/sound.c
  20. 36
      src/sound.h
  21. 4
      src/texture.c
  22. 141
      src/transform.c
  23. 20
      src/transform.h

@ -56,6 +56,50 @@ Sprint: Left Shift
*** Level/Scene *** Level/Scene
*** Materials *** Materials
*** Mesh/Geometry *** Mesh/Geometry
** Notes on entity Systems
- Fat entites with all related properties, i.e. position, mesh etc in them. Easy to serialize, memory friendly, simple to implement
but would require significant changes to the current codebase. e.g.
struct Entity
{
int type;
char* name;
struct Transform {....};
struct Camera {....};
// Separate properties unique to entity types by using unions
struct Renderable
{
struct Model {....};
union
{
struct Player
{
int score;
int bullets;
};
struct Enemy
{
int target;
};
}
}
};
- Change component implementation by using anonymous unions to simulate interfaces. e.g
struct Component
{
int type;
union
{
struct Transform {....};
struct Model {....};
struct Camera {....};
}
}
- Use handles for assets
- Use something similar to Variant to use as entity, not sure what or how
- Don't forget to think of the actual use-case and usage when coming up with a solution, don't build castles in the air!
* Things TODO * Things TODO
** DONE Input ** DONE Input
- State "DONE" from "TODO" [2015-07-02 Thu 01:24] - State "DONE" from "TODO" [2015-07-02 Thu 01:24]
@ -161,7 +205,11 @@ x Font atlas proper cleanup
- Decoupled event handling of gui and input if possible - Decoupled event handling of gui and input if possible
- Custom rendering for gui - Custom rendering for gui
** TODO Allow passsing base path as commandline argument? ** TODO Allow passsing base path as commandline argument?
** TODO Show SDL dialogbox if we cannot launch at all? ** TODO Remove components and switch to "Fat Entities" i.e. one entity struct contains all combinations
** TODO Use variants for material params
** TODO In second refactor pass, use entities everywhere, no need to pass in transform and model separately for example since they're both part of the same entity anyway
** DONE Show SDL dialogbox if we cannot launch at all?
- State "DONE" from "TODO" [2017-05-26 Fri 00:41]
** DONE Writing back to config file ** DONE Writing back to config file
- State "DONE" from "TODO" [2017-05-08 Mon 00:57] - State "DONE" from "TODO" [2017-05-08 Mon 00:57]
** DONE Reading from config file ** DONE Reading from config file
@ -191,7 +239,8 @@ x Font atlas proper cleanup
** TODO Ray picking ** TODO Ray picking
** TODO Remove reduntant "settings" structures and move all configuration stuff to config variables ** TODO Remove reduntant "settings" structures and move all configuration stuff to config variables
** TODO Shadow maps ** TODO Shadow maps
** TODO Log output to file on every run ** DONE Log output to file on every run
- State "DONE" from "TODO" [2017-05-26 Fri 00:41]
** TODO Print processor stats and machine capabilites RAM etc on every run to log. ** TODO Print processor stats and machine capabilites RAM etc on every run to log.
** TODO Milestone: Pong! ** TODO Milestone: Pong!
- In order to put things into perspective and get a feel for what really needs to be prioritized, a very small but actual game release is necessary. - In order to put things into perspective and get a feel for what really needs to be prioritized, a very small but actual game release is necessary.
@ -201,17 +250,19 @@ x Font atlas proper cleanup
? Game .so with init, update and cleanup functions ? Game .so with init, update and cleanup functions
x Configuration files and "cvars" load/reload x Configuration files and "cvars" load/reload
x Keybindings in config x Keybindings in config
- Log output on every run. x Log output on every run.
- Implement entity load/save to file - Implement entity load/save to file
? Prefab load/save to file ? Prefab load/save to file
** TODO Do input maps really need to be queried by their string names? ** TODO Do input maps really need to be queried by their string names?
** TODO Reloading all the things! (textures/shaders/models/settings/entities etc) ** TODO Reloading all the things! (textures/shaders/models/settings/entities etc)
** TODO Separate Debug/Editor camera from the active camera in the scene that can be switched to at any time ** TODO Separate Debug/Editor camera from the active camera in the scene that can be switched to at any time
** TODO Make logging to file and console toggleable at complie-time or run-time
** DONE Add option to specify where to read/write files from instead of being hard-coded assets dir ** DONE Add option to specify where to read/write files from instead of being hard-coded assets dir
- State "DONE" from "TODO" [2017-05-24 Wed 17:12] - State "DONE" from "TODO" [2017-05-24 Wed 17:12]
** TODO Add default keybindings ** TODO Add default keybindings
** TODO Write default config/keybindings etc to file if none are found in preferences dir ** TODO Write default config/keybindings etc to file if none are found in preferences dir
** TODO Fix input map bugs ** TODO Fix input map bugs
** TODO Flatpak packaging for linux releases
** TODO Use hashmap for debugvar slots in editor ** TODO Use hashmap for debugvar slots in editor
** TODO Use hashmap to store input maps ** TODO Use hashmap to store input maps
** DONE Live data views in editor ** DONE Live data views in editor

@ -1,4 +1,5 @@
#include "bounding_volumes.h" #include "bounding_volumes.h"
#include "entity.h"
#include "transform.h" #include "transform.h"
#include <math.h> #include <math.h>

@ -1,6 +1,7 @@
#include "camera.h" #include "camera.h"
#include "entity.h" #include "entity.h"
#include "transform.h" #include "transform.h"
#include "entity.h"
#include "array.h" #include "array.h"
#include "framebuffer.h" #include "framebuffer.h"
#include "texture.h" #include "texture.h"
@ -15,92 +16,45 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
static struct Camera* camera_list;
static int* empty_indices;
static int primary_camera_index;
static void update_frustum(struct Camera* camera); static void update_frustum(struct Camera* camera);
struct Camera* camera_get(int index) void camera_destroy(struct Camera* camera)
{
struct Camera* camera = NULL;
if(index > -1 && index < array_len(camera_list))
camera = &camera_list[index];
return camera;
}
void camera_init(void)
{ {
camera_list = array_new(struct Camera); assert(camera);
empty_indices = array_new(int); if(camera->fbo != -1) framebuffer_remove(camera->fbo);
primary_camera_index = -1; 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;
void camera_remove(int index) camera->ortho = camera->resizeable = false;
{ camera->fov = camera->aspect_ratio = camera->nearz = camera->farz = 0.f;
if(index > -1 && index < array_len(camera_list)) mat4_identity(&camera->view_mat);
{ mat4_identity(&camera->proj_mat);
struct Camera* camera = &camera_list[index]; mat4_identity(&camera->view_proj_mat);
if(camera->fbo != -1) framebuffer_remove(camera->fbo); for(int i = 0; i < FP_NUM_PLANES; i++)
if(camera->render_tex != -1) texture_remove(camera->render_tex); vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
if(camera->depth_tex != -1) texture_remove(camera->depth_tex); vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0);
camera->fbo = camera->render_tex = camera->depth_tex = camera->node = -1;
camera->ortho = camera->resizeable = 0;
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);
array_push(empty_indices, index, int);
}
}
void camera_cleanup(void)
{
for(int i = 0; i < array_len(camera_list); i++)
if(camera_list[i].node != -1) camera_remove(i);
array_free(camera_list);
array_free(empty_indices);
} }
int camera_create(int node, int width, int height) void camera_create(struct Camera* camera, struct Transform* transform, int width, int height)
{ {
int index = -1; camera->fbo = -1;
struct Camera* new_camera = NULL; camera->render_tex = -1;
if(array_len(empty_indices) > 0) camera->depth_tex = -1;
{ camera->farz = 1000.f;
index = *array_get_last(empty_indices, int); camera->nearz = 0.1f;
new_camera = &camera_list[index]; camera->fov = 60.f;
array_pop(empty_indices); camera->ortho = 0;
} camera->resizeable = 1;
else
{
new_camera = array_grow(camera_list, struct Camera);
index = array_len(camera_list) - 1;
}
new_camera->fbo = -1;
new_camera->render_tex = -1;
new_camera->depth_tex = -1;
new_camera->node = node;
new_camera->farz = 1000.f;
new_camera->nearz = 0.1f;
new_camera->fov = 60.f;
new_camera->ortho = 0;
new_camera->resizeable = 1;
float aspect_ratio = (float)width / (float)height; float aspect_ratio = (float)width / (float)height;
new_camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio;
mat4_identity(&new_camera->view_mat); mat4_identity(&camera->view_mat);
mat4_identity(&new_camera->proj_mat); mat4_identity(&camera->proj_mat);
mat4_identity(&new_camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++) for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&new_camera->frustum[i], 0.f, 0.f, 0.f, 0.f); vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(new_camera); camera_update_view(camera, transform);
camera_update_proj(new_camera); camera_update_proj(camera);
vec4_fill(&new_camera->clear_color, 1.f, 1.f, 1.f, 1.f); vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f);
return index;
} }
void camera_update_view_proj(struct Camera* camera) void camera_update_view_proj(struct Camera* camera)
@ -110,10 +64,8 @@ void camera_update_view_proj(struct Camera* camera)
update_frustum(camera); update_frustum(camera);
} }
void camera_update_view(struct Camera* camera) void camera_update_view(struct Camera* camera, struct Transform* transform)
{ {
struct Entity* entity = entity_get(camera->node);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
vec3 lookat = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f};
vec3 up = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f};
vec3 position = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f};
@ -157,11 +109,9 @@ void camera_attach_fbo(struct Camera* camera,
camera->fbo = framebuffer_create(width, height, has_depth, 0, resizeable); camera->fbo = framebuffer_create(width, height, has_depth, 0, resizeable);
if(camera->fbo > -1) if(camera->fbo > -1)
{ {
char tex_name[128];
if(has_color) if(has_color)
{ {
snprintf(tex_name, 128, "cam_render_tex_%d", camera->node); camera->render_tex = texture_create(NULL,
camera->render_tex = texture_create(tex_name,
TU_DIFFUSE, TU_DIFFUSE,
width, height, width, height,
GL_RGBA, GL_RGBA,
@ -175,12 +125,9 @@ void camera_attach_fbo(struct Camera* camera,
framebuffer_set_texture(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0); framebuffer_set_texture(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0);
} }
memset(tex_name, '\0', 128);
if(has_depth) if(has_depth)
{ {
snprintf(tex_name, 128, "cam_depth_tex_%d", camera->node); camera->depth_tex = texture_create(NULL,
camera->depth_tex = texture_create(tex_name,
TU_SHADOWMAP1, TU_SHADOWMAP1,
width, height, width, height,
GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT,
@ -202,41 +149,6 @@ void camera_attach_fbo(struct Camera* camera,
} }
} }
struct Camera* camera_get_all(void)
{
return camera_list;
}
void camera_set_primary_viewer(struct Camera* camera)
{
assert(camera);
if(camera->node == -1)
{
log_error("camera:set_primary_viewer", "Invalid camera!");
}
else
{
/* locate the index of this camera */
for(int i = 0; i < array_len(camera_list); i++)
{
if(camera_list[i].node == camera->node)
{
primary_camera_index = i;
break;
}
}
}
}
struct Camera* camera_get_primary(void)
{
struct Camera* primary_camera = NULL;
if(primary_camera_index != -1)
primary_camera = &camera_list[primary_camera_index];
return primary_camera;
}
static void update_frustum(struct Camera* camera) static void update_frustum(struct Camera* camera)
{ {
assert(camera); assert(camera);
@ -280,15 +192,15 @@ static void update_frustum(struct Camera* camera)
} }
} }
void camera_resize_all(int width, int height) /* void camera_resize_all(int width, int height) */
{ /* { */
for(int i = 0; i < array_len(camera_list); i++) /* for(int i = 0; i < array_len(camera_list); i++) */
{ /* { */
struct Camera* camera = &camera_list[i]; /* struct Camera* camera = &camera_list[i]; */
if(!camera->resizeable) continue; /* if(!camera->resizeable) continue; */
float aspect = (float)width / (float)height; /* float aspect = (float)width / (float)height; */
camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; /* camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; */
camera_update_proj(camera); /* camera_update_proj(camera); */
} /* } */
} /* } */

@ -1,36 +1,13 @@
#ifndef camera_H #ifndef CAMERA_H
#define camera_H #define CAMERA_H
#include "linmath.h" struct Camera;
struct Transform;
struct Camera void camera_destroy(struct Camera* camera);
{ void camera_create(struct Camera* camera, struct Transform* transform, int width, int height);
int node;
mat4 proj_mat;
mat4 view_mat;
mat4 view_proj_mat;
float fov;
float aspect_ratio;
float nearz;
float farz;
int ortho;
int fbo;
int render_tex;
int depth_tex;
vec4 clear_color;
vec4 frustum[6];
int resizeable;
};
struct Camera* camera_get(int index);
struct Camera* camera_get_all(void);
struct Camera* camera_get_primary(void);
void camera_init(void);
void camera_cleanup(void);
void camera_remove(int index);
int camera_create(int node, int width, int height);
void camera_update_view_proj(struct Camera* camera); void camera_update_view_proj(struct Camera* camera);
void camera_update_view(struct Camera* camera); void camera_update_view(struct Camera* camera, struct Transform* transform);
void camera_update_proj(struct Camera* camera); void camera_update_proj(struct Camera* camera);
void camera_attach_fbo(struct Camera* camera, void camera_attach_fbo(struct Camera* camera,
int width, int width,
@ -38,7 +15,6 @@ void camera_attach_fbo(struct Camera* camera,
int has_depth, int has_depth,
int has_color, int has_color,
int resizeable); int resizeable);
void camera_set_primary_viewer(struct Camera* camera); /* void camera_resize_all(int width, int height); */
void camera_resize_all(int width, int height);
#endif #endif

@ -1,31 +0,0 @@
#ifndef components_H
#define components_H
enum Component
{
C_TRANSFORM = 0,
C_MODEL,
C_CAMERA,
C_LIGHT,
C_SOUND_SOURCE,
C_RIGIDBODY,
NUM_COMPONENTS
};
inline static const char* comp_to_str(enum Component component)
{
const char* str = 0;
switch(component)
{
case C_TRANSFORM: str = "TRANSFORM"; break;
case C_MODEL: str = "MODEL"; break;
case C_CAMERA: str = "CAMERA"; break;
case C_LIGHT: str = "LIGHT"; break;
case C_SOUND_SOURCE: str = "SOUND_SOURCE"; break;
case C_RIGIDBODY: str = "RIGIDBODY"; break;
case NUM_COMPONENTS: str = "NUM_COMPONENTS"; break;
}
return str;
}
#endif

@ -34,32 +34,27 @@ void entity_cleanup(void)
void entity_remove(int index) void entity_remove(int index)
{ {
struct Entity* entity = &entity_list[index]; struct Entity* entity = &entity_list[index];
if(entity->node == -1) return;
transform_destroy(&entity->transform);
for(int i = 0; i < NUM_COMPONENTS; i++) switch(entity->type)
{ {
if(i == C_TRANSFORM) case ET_CAMERA: camera_destroy(&entity->camera); break;
{ case ET_LIGHT: light_destroy(&entity->light, entity->id); break;
transform_remove(entity->components[i]); case ET_SOUND_SOURCE: sound_source_destroy(&entity->sound_source); break;
entity->components[i] = -1; case ET_STATIC_MESH: model_destroy(&entity->model, entity->id); break;
} case ET_ROOT: break;
else default: log_error("entity:remove", "Invalid entity type"); break;
{ };
entity_component_remove(entity, i); entity->id = -1;
} entity->is_listener = false;
} entity->marked_for_deletion = false;
entity->node = -1; entity->renderable = false;
entity->parent = -1; entity->name = NULL;
entity->is_listener = 0;
array_free(entity->children);
entity->children = NULL;
free(entity->name); free(entity->name);
free(entity->tag);
entity->name = entity->tag = NULL;
array_push(empty_indices, index, int); array_push(empty_indices, index, int);
} }
struct Entity* entity_create(const char* name, const char* tag) struct Entity* entity_create(const char* name, const int type, int parent_id)
{ {
struct Entity* new_entity = NULL; struct Entity* new_entity = NULL;
int index = -1; int index = -1;
@ -73,23 +68,18 @@ struct Entity* entity_create(const char* name, const char* tag)
else else
{ {
new_entity = array_grow(entity_list, struct Entity); new_entity = array_grow(entity_list, struct Entity);
new_entity->name = new_entity->tag = NULL; new_entity->name = NULL;
index = array_len(entity_list) - 1; index = array_len(entity_list) - 1;
} }
if(new_entity->name) free(new_entity->name); if(new_entity->name) free(new_entity->name);
if(new_entity->tag) free(new_entity->tag); new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME");
new_entity->id = index;
new_entity->name = name ? str_new(name) : str_new("DEFAULT_NAME"); new_entity->is_listener = false;
new_entity->tag = tag ? str_new(tag) : str_new("DEFAULT_TAG"); new_entity->type = type;
new_entity->node = index; new_entity->marked_for_deletion = false;
new_entity->parent = -1; new_entity->renderable = false;
new_entity->is_listener = 0; transform_create(&new_entity->transform, parent_id);
new_entity->children = array_new(int);
for(int i = 0; i < NUM_COMPONENTS; i++)
new_entity->components[i] = -1;
new_entity->components[C_TRANSFORM] = transform_create(new_entity->node);
return new_entity; return new_entity;
} }
@ -119,145 +109,35 @@ struct Entity* entity_find(const char* name)
return entity; return entity;
} }
int entity_component_remove(struct Entity* entity, enum Component component) void entity_post_update(void)
{ {
int success = 1; for(int i = 0; i < array_len(entity_list); i++)
assert(entity);
int comp_index = entity->components[component];
switch(component)
{
case C_TRANSFORM: log_error("entity:remove_component", "Cannot remove TRANSFORM"); break;
case C_MODEL: if(comp_index != -1) model_remove(comp_index); break;
case C_CAMERA: if(comp_index != -1) camera_remove(comp_index); break;
case C_LIGHT: if(comp_index != -1) light_remove(comp_index); break;
case C_SOUND_SOURCE: if(comp_index != -1) sound_source_remove(comp_index); break;
case C_RIGIDBODY:
break;
default:
/* Only called for NUM_COMPONENTS, do nothing */
break;
}
entity->components[component] = -1;
if(success) entity->components[component] = -1;
return success;
}
void* entity_component_get(struct Entity* entity, enum Component component)
{
void* comp_obj = NULL;
assert(entity);
int comp_index = entity->components[component];
if(comp_index != -1)
{ {
switch(component) struct Entity* entity = &entity_list[i];
if(entity->id == -1) continue;
if(entity->marked_for_deletion)
{ {
case C_TRANSFORM: comp_obj = transform_get(comp_index); break; entity_remove(i);
case C_MODEL: comp_obj = model_get(comp_index); break; continue;
case C_CAMERA: comp_obj = camera_get(comp_index); break;
case C_LIGHT: comp_obj = light_get(comp_index); break;
case C_SOUND_SOURCE: comp_obj = sound_source_get(comp_index); break;
case C_RIGIDBODY:
break;
default: log_error("entity:component_get", "Invalid component type"); break;
} }
} }
else
{
log_error("entity:component_get", "Entity '%s' does not have component %s",
entity->name,
comp_to_str(component));
}
return comp_obj;
}
void* entity_component_add(struct Entity* entity, enum Component component, ...)
{
assert(entity);
void* new_comp = NULL;
va_list args;
va_start(args, component);
int new_comp_index = -1;
switch(component)
{
case C_TRANSFORM:
log_error("entity:add_component", "Entity already has Transform component");
case C_MODEL:
{
const char* filename = va_arg(args, const char*);
const char* material_name = va_arg(args, const char*);
new_comp_index = model_create(entity->node, filename, material_name);
new_comp = model_get(new_comp_index);
}
break;
case C_CAMERA:
{
int width = va_arg(args, int);
int height = va_arg(args, int);
new_comp_index = camera_create(entity->node, width, height);
new_comp = camera_get(new_comp_index);
}
break;
case C_LIGHT:
{
int light_type = va_arg(args, int);
new_comp_index = light_create(entity->node, light_type);
new_comp = light_get(new_comp_index);
}
break;
case C_SOUND_SOURCE:
{
new_comp_index = sound_source_create(entity->node);
new_comp = sound_source_get(new_comp_index);
}
break;
case C_RIGIDBODY:
log_error("entity:component_add", "Unsupported component RIGIDBODY");
break;
default:
log_error("entity:component_add", "Invalid component type");
break;
}
if(new_comp_index == -1)
{
log_error("entity:component_add", "%s component not added to %s",
comp_to_str(component),
entity->name);
}
else
{
entity->components[component] = new_comp_index;
log_message("%s component added to %s", comp_to_str(component), entity->name);
}
va_end(args);
return new_comp; for(int i = 0; i < array_len(entity_list); i++)
}
int entity_has_component(struct Entity* entity, enum Component component)
{
int has_comp = 0;
if(entity->components[component] != -1)
has_comp = 1;
return has_comp;
}
void entity_sync_components(struct Entity* entity)
{
if(entity_has_component(entity, C_CAMERA))
{ {
struct Camera* camera = entity_component_get(entity, C_CAMERA); struct Entity* entity = &entity_list[i];
camera_update_view(camera); if(entity->id == -1) continue;
}
if(entity_has_component(entity, C_SOUND_SOURCE)) if(entity->transform.is_modified)
{ {
struct Sound_Source* source = entity_component_get(entity, C_SOUND_SOURCE); if(entity->type == ET_CAMERA)
sound_source_update(source); camera_update_view(&entity->camera, &entity->transform);
} else if(entity->type == ET_SOUND_SOURCE)
sound_source_update(&entity->sound_source, &entity->transform);
if(entity->is_listener) sound_listener_update(); if(entity->is_listener) sound_listener_update();
}
}
} }
struct Entity* entity_get_all(void) struct Entity* entity_get_all(void)
@ -269,6 +149,6 @@ struct Entity* entity_get_parent(int node)
{ {
struct Entity* parent = NULL; struct Entity* parent = NULL;
struct Entity* entity = entity_get(node); struct Entity* entity = entity_get(node);
if(entity) parent = entity_get(entity->node); if(entity) parent = entity_get(entity->transform.parent);
return parent; return parent;
} }

@ -1,31 +1,123 @@
#ifndef entity_H #ifndef ENTITY_H
#define entity_H #define ENTITY_H
#include "components.h" #include "linmath.h"
#include "num_types.h"
struct Material_Param;
enum Entity_Type
{
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
};
struct Transform
{
vec3 position;
vec3 scale;
quat rotation;
mat4 trans_mat;
int parent;
int* children;
bool is_modified;
};
struct Model
{
int geometry_index;
int material;
struct Material_Param* material_params;
};
struct Sound_Source
{
uint al_source_handle;
uint al_buffer_handle;
bool active;
};
struct Camera
{
mat4 proj_mat;
mat4 view_mat;
mat4 view_proj_mat;
float fov;
float aspect_ratio;
float nearz;
float farz;
bool ortho;
int fbo;
int render_tex;
int depth_tex;
vec4 clear_color;
vec4 frustum[6];
bool resizeable;
};
struct Light
{
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 struct Entity
{ {
int node; int id;
char* name; int type;
char* tag; char* name;
int components[NUM_COMPONENTS]; bool is_listener; /* TODO: Replace all booleans with flags */
int parent; bool marked_for_deletion;
int* children; bool renderable;
int is_listener; struct Transform transform;
union
{
struct
{
struct Model model;
int health;
} Player;
struct Model model;
struct Camera camera;
struct Light light;
struct Sound_Source sound_source;
};
}; };
void entity_init(void); void entity_init(void);
void entity_cleanup(void); void entity_cleanup(void);
void entity_remove(int index); void entity_remove(int index);
struct Entity* entity_create(const char* name, const char* tag); void entity_post_update(void);
struct Entity* entity_create(const char* name, const int type, int parent_id);
struct Entity* entity_get(int index); struct Entity* entity_get(int index);
struct Entity* entity_find(const char* name); struct Entity* entity_find(const char* name);
struct Entity* entity_get_all(void); struct Entity* entity_get_all(void);
struct Entity* entity_get_parent(int node); struct Entity* entity_get_parent(int node);
int entity_component_remove(struct Entity* entity, enum Component component);
void* entity_component_get(struct Entity* entity, enum Component component);
void* entity_component_add(struct Entity* entity, enum Component component, ...);
int entity_has_component(struct Entity* entity, enum Component component);
void entity_sync_components(struct Entity* entity);
#endif #endif

@ -72,9 +72,7 @@ int game_init(struct Window* window)
framebuffer_init(); framebuffer_init();
geom_init(); geom_init();
renderer_init(); renderer_init();
transform_init();
light_init(); light_init();
camera_init();
material_init(); material_init();
editor_init(); editor_init();
model_init(); model_init();
@ -89,10 +87,10 @@ int game_init(struct Window* window)
void scene_setup(void) void scene_setup(void)
{ {
struct Entity* player = scene_add_new("player", "None"); struct Entity* player = scene_add_new("player", ET_CAMERA);
game_state->player_node = player->node; game_state->player_node = player->id;
vec3 viewer_pos = {10, 5, 100}; vec3 viewer_pos = {10, 5, 100};
struct Transform* viewer_tran = entity_component_get(player, C_TRANSFORM); struct Transform* viewer_tran = &player->transform;
/* struct Model* player_model = entity_component_add(player, C_MODEL, "sphere.pamesh", NULL); */ /* struct Model* player_model = entity_component_add(player, C_MODEL, "sphere.pamesh", NULL); */
/* model_set_material_param(player_model, "diffuse_color", &color); */ /* model_set_material_param(player_model, "diffuse_color", &color); */
/* vec4_fill(&color, 1.f, 1.f, 1.f, 1.f); */ /* vec4_fill(&color, 1.f, 1.f, 1.f, 1.f); */
@ -100,25 +98,28 @@ void scene_setup(void)
int render_width, render_height; int render_width, render_height;
render_width = 1024; render_width = 1024;
render_height = 768; render_height = 768;
struct Camera* camera = entity_component_add(player, C_CAMERA, render_width, render_height); struct Camera* camera = &player->camera;
camera_create(camera, &player->transform, render_width, render_height);
camera_attach_fbo(camera, render_width, render_height, 1, 1, 1); camera_attach_fbo(camera, render_width, render_height, 1, 1, 1);
vec4_fill(&camera->clear_color, 0.3f, 0.6f, 0.9f, 1.0f); vec4_fill(&camera->clear_color, 0.3f, 0.6f, 0.9f, 1.0f);
camera_set_primary_viewer(camera); sound_listener_set(player->id);
sound_listener_set(player->node);
vec4 color = {0.f, 1.f, 1.f, 1.f }; vec4 color = {0.f, 1.f, 1.f, 1.f };
struct Entity* new_ent = scene_add_new("Model_Entity", NULL); struct Entity* new_ent = scene_add_new("Model_Entity", ET_STATIC_MESH);
struct Transform* tran = entity_component_get(new_ent, C_TRANSFORM); struct Transform* tran = &new_ent->transform;
vec3 position = {0, 0, -5}; vec3 position = {0, 0, -5};
transform_translate(tran, &position, TS_WORLD); transform_translate(tran, &position, TS_WORLD);
struct Model* box_model = entity_component_add(new_ent, C_MODEL, "default.pamesh", "Blinn_Phong"); struct Model* box_model = &new_ent->model;
model_create(box_model, new_ent->id, "default.pamesh", "Blinn_Phong");
model_set_material_param(box_model, "diffuse_color", &color); model_set_material_param(box_model, "diffuse_color", &color);
int tex = texture_create_from_file("white.tga", TU_DIFFUSE); int tex = texture_create_from_file("white.tga", TU_DIFFUSE);
model_set_material_param(box_model, "diffuse_texture", &tex); model_set_material_param(box_model, "diffuse_texture", &tex);
struct Transform* model_tran = entity_component_get(new_ent, C_TRANSFORM);
vec3 scale = {1, 1, 1}; vec3 scale = {1, 1, 1};
transform_scale(model_tran, &scale); transform_scale(tran, &scale);
struct Sound_Source* source = entity_component_add(new_ent, C_SOUND_SOURCE);
struct Entity* sound_ent = scene_add_as_child("Sound_ENT", ET_SOUND_SOURCE, new_ent->id);
struct Sound_Source* source = &sound_ent->sound_source;
sound_source_create(source, &new_ent->transform);
if(source) if(source)
{ {
sound_source_load_wav(source, "BigExplosion.wav"); sound_source_load_wav(source, "BigExplosion.wav");
@ -128,7 +129,7 @@ void scene_setup(void)
sound_source_play(source); sound_source_play(source);
} }
int parent_node = new_ent->node; int parent_node = new_ent->id;
int num_suz = 2; int num_suz = 2;
srand(time(NULL)); srand(time(NULL));
for(int i = 0; i < num_suz; i++) for(int i = 0; i < num_suz; i++)
@ -137,30 +138,29 @@ void scene_setup(void)
int y = rand() % num_suz; int y = rand() % num_suz;
int z = rand() % num_suz; int z = rand() % num_suz;
x++; y++; z++; x++; y++; z++;
struct Entity* suz = scene_add_as_child("Suzanne", NULL, parent_node); struct Entity* suz = scene_add_as_child("Suzanne", ET_STATIC_MESH, parent_node);
//struct Entity* suz = scene_add_new("Suzanne", NULL); struct Model* suz_model = &suz->model;
struct Model* suz_model = entity_component_add(suz, C_MODEL, "suzanne.pamesh", "Blinn_Phong"); model_create(suz_model, suz->id, "suzanne.pamesh", "Blinn_Phong");
model_set_material_param(suz_model, "diffuse_color", &color); model_set_material_param(suz_model, "diffuse_color", &color);
float spec_str = 80.f; float spec_str = 80.f;
model_set_material_param(suz_model, "specular_strength", &spec_str); model_set_material_param(suz_model, "specular_strength", &spec_str);
struct Transform* s_tran = entity_component_get(suz, C_TRANSFORM);
vec3 s_pos = {x, 5, z}; vec3 s_pos = {x, 5, z};
transform_translate(s_tran, &s_pos, TS_WORLD); transform_translate(&suz->transform, &s_pos, TS_WORLD);
} }
struct Entity* ground = scene_add_new("Ground", NULL); struct Entity* ground = scene_add_new("Ground", ET_STATIC_MESH);
struct Model* ground_model = entity_component_add(ground, C_MODEL, "plane.pamesh", "Blinn_Phong"); struct Model* ground_model = &ground->model;
model_create(ground_model, ground->id, "plane.pamesh", "Blinn_Phong");
model_set_material_param(ground_model, "diffuse_color", &color); model_set_material_param(ground_model, "diffuse_color", &color);
int white_tex = texture_create_from_file("white.tga", TU_DIFFUSE); int white_tex = texture_create_from_file("white.tga", TU_DIFFUSE);
model_set_material_param(ground_model, "diffuse_texture", &white_tex); model_set_material_param(ground_model, "diffuse_texture", &white_tex);
float spec_str = 80.f; float spec_str = 80.f;
model_set_material_param(ground_model, "specular_strength", &spec_str); model_set_material_param(ground_model, "specular_strength", &spec_str);
struct Transform* ground_tran = entity_component_get(ground, C_TRANSFORM);
vec3 pos = {0, -15, 0}; vec3 pos = {0, -15, 0};
vec3 scale_ground = {200.f, 200.f, 200.f}; vec3 scale_ground = {200.f, 1.f, 200.f};
transform_set_position(ground_tran, &pos); transform_set_position(&ground->transform, &pos);
transform_scale(ground_tran, &scale_ground); transform_scale(&ground->transform, &scale_ground);
/* struct Entity* screen = scene_add_new("Screen", NULL); */ /* struct Entity* screen = scene_add_new("Screen", NULL); */
/* struct Model* screen_model = entity_component_add(screen, C_MODEL, NULL, NULL); */ /* struct Model* screen_model = entity_component_add(screen, C_MODEL, NULL, NULL); */
@ -182,11 +182,11 @@ void scene_setup(void)
int x = rand() % MAX_LIGHTS; int x = rand() % MAX_LIGHTS;
int z = rand() % MAX_LIGHTS; int z = rand() % MAX_LIGHTS;
x++; z++; x++; z++;
struct Entity* light_ent = scene_add_new("Light_Ent", NULL); struct Entity* light_ent = scene_add_new("Light_Ent", ET_LIGHT);
struct Transform* light_tran = entity_component_get(light_ent, C_TRANSFORM);
vec3 lt_pos = {x * 20, 0, z * 20}; vec3 lt_pos = {x * 20, 0, z * 20};
transform_set_position(light_tran, &lt_pos); transform_set_position(&light_ent->transform, &lt_pos);
struct Light* light_comp = entity_component_add(light_ent, C_LIGHT, LT_POINT); struct Light* light_comp = &light_ent->light;
light_create(&light_ent->light, light_ent->id, LT_POINT);
vec3_fill(&light_comp->color, 1.f / (float)x, 1.f / ((rand() % 10) + 1.f), 1.f / (float)z); vec3_fill(&light_comp->color, 1.f / (float)x, 1.f / ((rand() % 10) + 1.f), 1.f / (float)z);
light_comp->intensity = 1.f; light_comp->intensity = 1.f;
} }
@ -200,9 +200,8 @@ void debug(float dt)
{ {
//struct Entity* entity = entity_get(player_node); //struct Entity* entity = entity_get(player_node);
struct Entity* entity = entity_get(game_state->player_node); struct Entity* entity = entity_get(game_state->player_node);
struct Camera* cam = entity_component_get(entity, C_CAMERA); struct Camera* cam = &entity->camera;
camera_set_primary_viewer(cam); struct Transform* transform = &entity->transform;
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
float move_speed = 5.f, move_scale = 3.f, turn_speed = 50.f; float move_speed = 5.f, move_scale = 3.f, turn_speed = 50.f;
vec3 offset = {0, 0, 0}; vec3 offset = {0, 0, 0};
float turn_up_down = 0.f; float turn_up_down = 0.f;
@ -291,29 +290,26 @@ void debug(float dt)
if(input_is_key_pressed(KEY_SPACE)) if(input_is_key_pressed(KEY_SPACE))
{ {
struct Entity* model = scene_find("Model_Entity"); struct Entity* model = scene_find("Model_Entity");
struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM);
vec3 x_axis = {1, 0, 0}; vec3 x_axis = {1, 0, 0};
transform_rotate(mod_tran, &x_axis, 25.f * dt, TS_WORLD); transform_rotate(&model->transform, &x_axis, 25.f * dt, TS_WORLD);
} }
if(input_is_key_pressed(KEY_M)) if(input_is_key_pressed(KEY_M))
{ {
struct Entity* model = scene_find("Model_Entity"); struct Entity* model = scene_find("Model_Entity");
struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM);
//vec3 y_axis = {0, 0, 1}; //vec3 y_axis = {0, 0, 1};
//transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL); //transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL);
vec3 amount = {0, 0, -5 * dt}; vec3 amount = {0, 0, -5 * dt};
transform_translate(mod_tran, &amount, TS_LOCAL); transform_translate(&model->transform, &amount, TS_LOCAL);
} }
if(input_is_key_pressed(KEY_N)) if(input_is_key_pressed(KEY_N))
{ {
struct Entity* model = scene_find("Model_Entity"); struct Entity* model = scene_find("Model_Entity");
struct Transform* mod_tran = entity_component_get(model, C_TRANSFORM);
/* vec3 y_axis = {0, 0, 1}; */ /* vec3 y_axis = {0, 0, 1}; */
/* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */ /* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */
vec3 amount = {0, 0, 5 * dt}; vec3 amount = {0, 0, 5 * dt};
transform_translate(mod_tran, &amount, TS_LOCAL); transform_translate(&model->transform, &amount, TS_LOCAL);
} }
} }
@ -335,6 +331,7 @@ int run(void)
update(delta_time, &should_window_close); update(delta_time, &should_window_close);
render(); render();
window_swap_buffers(game_state->window); window_swap_buffers(game_state->window);
entity_post_update();
} }
return 1; return 1;
} }
@ -1559,7 +1556,8 @@ void debug_gui(float dt)
void render(void) void render(void)
{ {
renderer_draw(); struct Entity* viewer = entity_get(game_state->player_node);
renderer_draw(viewer);
} }
void game_cleanup(void) void game_cleanup(void)
@ -1575,8 +1573,6 @@ void game_cleanup(void)
material_cleanup(); material_cleanup();
geom_cleanup(); geom_cleanup();
light_cleanup(); light_cleanup();
transform_cleanup();
camera_cleanup();
input_cleanup(); input_cleanup();
renderer_cleanup(); renderer_cleanup();
io_file_cleanup(); io_file_cleanup();

@ -1,117 +1,70 @@
#include "light.h" #include "light.h"
#include "log.h"
#include "array.h" #include "array.h"
#include <stdio.h> #include "entity.h"
#include <string.h>
static struct Light* light_list; #include <assert.h>
static int* empty_indices;
static int* valid_light_indices;
static int max_lights;
struct Light* light_get(int index) static int* light_list = NULL;
{
struct Light* light = NULL;
if(index > -1 && index < array_len(light_list))
light = &light_list[index];
return light;
}
struct Light* light_get_all(void)
{
return light_list;
}
void light_init(void) void light_init(void)
{ {
max_lights = 128; light_list = array_new(int);
light_list = array_new_cap(struct Light, max_lights);
for(int i = 0; i < max_lights; i++) light_list[i].valid = 0;
empty_indices = array_new(int);
valid_light_indices = array_new_cap(int, max_lights);
memset(valid_light_indices, -1, max_lights);
} }
void light_cleanup(void) void light_cleanup(void)
{ {
for(int i = 0; i < array_len(light_list); i++)
light_remove(i);
array_free(light_list); array_free(light_list);
array_free(empty_indices);
array_free(valid_light_indices);
} }
void light_remove(int index)
void light_create(struct Light* light, int entity_id, int light_type)
{ {
if(index > -1 && index < array_len(light_list)) assert(light && entity_id > -1);
{
light_list[index].valid = 0; light->valid = true;
array_push(empty_indices, index, int); light->cast_shadow = 0;
} light->depth_bias = 0.0005f;
light->type = light_type;
light->pcf_enabled = false;
light->intensity = 1.f;
light->falloff = 1.5f;
light->outer_angle = TO_RADIANS(30.f);
light->inner_angle = TO_RADIANS(20.f);
light->radius = 20;
vec3_fill(&light->color, 1.f, 1.f, 1.f);
int* new_index = array_grow(light_list, int);
*new_index = entity_id;
} }
int light_create(int node, int light_type) void light_destroy(struct Light* light, int entity_id)
{ {
int index = -1; assert(light && entity_id > -1);
struct Light* new_light = NULL;
if(array_len(empty_indices) > 0) int index_to_remove = -1;
{ for(int i = 0; i < array_len(light_list); i++)
index = *array_get_last(empty_indices, int);
new_light = &light_list[index];
array_pop(empty_indices);
}
else
{ {
for(index = 0; index < max_lights; index++) if(light_list[i] == entity_id)
{
if(!light_list[index].valid)
break;
}
if(index == max_lights - 1)
{ {
index = -1; index_to_remove = i;
log_warning("Max light limit(%d) reached, cannot add light", max_lights); break;
return index;
} }
new_light = &light_list[index];
} }
new_light->node = node; if(index_to_remove != -1) array_remove_at(light_list, index_to_remove);
new_light->valid = 1; light->valid = false;
new_light->cast_shadow = 0; light->cast_shadow = 0;
vec3_fill(&new_light->color, 1.f, 1.f, 1.f); light->depth_bias = 0.f;
new_light->depth_bias = 0.0005f; light->type = LT_INVALID;
new_light->type = light_type; light->pcf_enabled = false;
new_light->pcf_enabled = 0; light->intensity = 10.f;
new_light->intensity = 1.f; light->falloff = 0.f;
new_light->falloff = 1.5f; light->outer_angle = 0.f;
new_light->outer_angle = TO_RADIANS(30.f); light->inner_angle = 0.f;
new_light->inner_angle = TO_RADIANS(20.f); light->radius = 0.f;
new_light->radius = 20; vec3_fill(&light->color, 1.f, 0.f, 1.f);
return index;
}
int light_get_max_lights(void)
{
return max_lights;
} }
int* light_get_valid_indices(int* valid_light_count) int* light_get_valid_indices(int* out_count)
{ {
/* First, get all the valid(active) lights, then sort them in the *out_count = array_len(light_list);
order directional, point, spot return light_list;
*/
int light_count = 0;
for(int i = 0; i < array_len(light_list); i++)
{
if(light_list[i].valid)
{
valid_light_indices[light_count] = i;
light_count++;
}
}
*valid_light_count = light_count;
return valid_light_indices;
} }

@ -1,43 +1,14 @@
#ifndef LIGHT_H #ifndef LIGHT_H
#define LIGHT_H #define LIGHT_H
#include "num_types.h"
#include "linmath.h"
#define MAX_SHADOWMAPS 4 #define MAX_SHADOWMAPS 4
enum LightType struct Light;
{
LT_SPOT = 0,
LT_DIR,
LT_POINT
};
struct Light
{
float outer_angle;
float inner_angle;
float falloff;
float intensity;
vec3 color;
int32 node;
uint8 cast_shadow;
uint8 pcf_enabled;
uint8 valid;
int type;
int radius;
int shadow_map[4];
float depth_bias;
};
struct Light* light_get(int index);
struct Light* light_get_all(void);
void light_init(void); void light_init(void);
void light_cleanup(void); void light_cleanup(void);
void light_remove(int index); void light_destroy(struct Light* light, int entity_id);
int light_create(int node, int light_type); void light_create(struct Light* light, int entity_id, int light_type);
void light_set_radius(struct Light* light, int radius); int* light_get_valid_indices(int* out_count);
int light_get_max_lights(void);
int* light_get_valid_indices(int* valid_light_count);
#endif #endif

@ -1,6 +1,7 @@
#include "material.h" #include "material.h"
#include "array.h" #include "array.h"
#include "shader.h" #include "shader.h"
#include "entity.h"
#include "string_utils.h" #include "string_utils.h"
#include "log.h" #include "log.h"
#include "model.h" #include "model.h"

@ -1,7 +1,6 @@
#include "model.h" #include "model.h"
#include "array.h" #include "array.h"
#include "log.h" #include "log.h"
#include "camera.h"
#include "entity.h" #include "entity.h"
#include "shader.h" #include "shader.h"
#include "transform.h" #include "transform.h"
@ -10,6 +9,7 @@
#include "material.h" #include "material.h"
#include "light.h" #include "light.h"
#include "editor.h" #include "editor.h"
#include "geometry.h"
#include "variant.h" #include "variant.h"
#include "bounding_volumes.h" #include "bounding_volumes.h"
#include "gl_load.h" #include "gl_load.h"
@ -21,100 +21,50 @@
#define MAX_NAME_LEN 64 #define MAX_NAME_LEN 64
static struct Model* model_list; static int num_culled = 0, num_rendered = 0, num_indices = 0;
static int* empty_indices; static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1;
static int num_culled = 0, num_rendered = 0, num_indices = 0;
static int num_culled_slot = -1, num_rendered_slot = -1, num_indices_slot = -1;
struct Model* model_get(int index)
{
struct Model* model = NULL;
if(index > -1 && index < array_len(model_list))
model = &model_list[index];
else
log_error("model:get", "Invalid index");
return model;
}
void model_init(void) void model_init(void)
{ {
model_list = array_new(struct Model);
empty_indices = array_new(int);
num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT);
num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT);
num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT);
} }
int model_create(int node, const char* geo_name, const char* material_name) void model_create(struct Model* model, int entity_id, const char* geo_name, const char* material_name)
{ {
assert(model);
/* if no name is given for geometry, use default */ /* if no name is given for geometry, use default */
if(!geo_name) geo_name = "default.pamesh"; if(!geo_name) geo_name = "default.pamesh";
int geo_index = geom_create_from_file(geo_name); int geo_index = geom_create_from_file(geo_name);
int index = -1;
struct Model* new_model = NULL; model->geometry_index = geo_index;
if(geo_index > -1) if(!material_register_model(model, entity_id, material_name ? material_name : "Unshaded"))
{
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_model = &model_list[index];
}
else
{
new_model = array_grow(model_list, struct Model);
index = array_len(model_list) - 1;
}
new_model->node = node;
new_model->geometry_index = geo_index;
if(!material_register_model(new_model, index, material_name ? material_name : "Unshaded"))
{
log_error("model:create", "Unable to register model with Unshaded material, component not added");
model_remove(index);
index = -1;
}
}
else
{ {
log_error("model:create", "Geometry '%s' not found.", geo_name); log_error("model:create", "Unable to register model with Unshaded material, component not added");
model_destroy(model, entity_id);
} }
return index;
} }
void model_remove(int index) void model_destroy(struct Model* model, int entity_id)
{ {
if(index > -1 && index < array_len(model_list)) assert(model);
{ geom_remove(model->geometry_index);
struct Model* model = &model_list[index]; model->geometry_index = -1;
model->node = -1; material_unregister_model(model, entity_id);
geom_remove(model->geometry_index); /* deallocate all params */
model->geometry_index = -1; for(int i = 0; i < array_len(model->material_params); i++)
material_unregister_model(model, index); free(model->material_params[i].value);
/* deallocate all params */
for(int i = 0; i < array_len(model->material_params); i++)
free(model->material_params[i].value);
array_free(model->material_params); array_free(model->material_params);
array_push(empty_indices, index, int);
}
else
{
log_error("model:remove", "Invalid index");
}
} }
void model_cleanup(void) void model_cleanup(void)
{ {
for(int i = 0; i < array_len(model_list); i++)
{
if(model_list[i].node != -1)
model_remove(i);
}
array_free(model_list);
array_free(empty_indices);
} }
void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode) void model_render_all(struct Entity* camera_entity, int draw_mode)
{ {
static mat4 mvp; static mat4 mvp;
struct Material* material_list = material_get_all_materials(); struct Material* material_list = material_get_all_materials();
@ -130,9 +80,9 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode)
for(int j = 0; j < array_len(material->registered_models); j++) for(int j = 0; j < array_len(material->registered_models); j++)
{ {
/* for each registered model, set up uniforms and render */ /* for each registered model, set up uniforms and render */
struct Model* model = &model_list[material->registered_models[j]]; struct Entity* entity = entity_get(material->registered_models[i]);
struct Entity* entity = entity_get(model->node); struct Model* model = &entity->model;
struct Transform* transform = entity_component_get(entity, C_TRANSFORM); struct Transform* transform = &entity->transform;
/* set material params for the model */ /* set material params for the model */
for(int k = 0; k < array_len(model->material_params); k++) for(int k = 0; k < array_len(model->material_params); k++)
@ -152,7 +102,7 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode)
if(strcmp(uniform->name, "mvp") == 0) if(strcmp(uniform->name, "mvp") == 0)
{ {
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &camera_entity->camera.view_proj_mat, &transform->trans_mat);
shader_set_uniform(uniform->type, uniform->location, &mvp); shader_set_uniform(uniform->type, uniform->location, &mvp);
renderer_check_glerror("model:render_all:material_pipeline"); renderer_check_glerror("model:render_all:material_pipeline");
} }
@ -163,7 +113,7 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode)
} }
else if(strcmp(uniform->name, "view_mat") == 0) else if(strcmp(uniform->name, "view_mat") == 0)
{ {
shader_set_uniform(uniform->type, uniform->location, &camera->view_mat); shader_set_uniform(uniform->type, uniform->location, &camera_entity->camera.view_mat);
renderer_check_glerror("model:render_all:material_pipeline"); renderer_check_glerror("model:render_all:material_pipeline");
} }
else if(strcmp(uniform->name, "inv_model_mat") == 0) else if(strcmp(uniform->name, "inv_model_mat") == 0)
@ -214,16 +164,16 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode)
memset(uniform_name, '\0', MAX_NAME_LEN); memset(uniform_name, '\0', MAX_NAME_LEN);
for(int i = 0; i < valid_light_count; i++) for(int i = 0; i < valid_light_count; i++)
{ {
struct Light* light = light_get(light_index_list[i]); /* TODO: Cull lights according to camera frustum */ struct Entity* light_entity = entity_get(light_index_list[i]);
struct Entity* light_entity = entity_get(light->node); struct Light* light = &light_entity->light; /* TODO: Cull lights according to camera frustum */
struct Transform* transform = entity_component_get(light_entity, C_TRANSFORM); struct Transform* light_transform = &light_entity->transform;
vec3 light_pos = {0, 0, 0}; vec3 light_pos = {0, 0, 0};
transform_get_absolute_pos(transform, &light_pos); transform_get_absolute_pos(light_transform, &light_pos);
if(light->type != LT_POINT) if(light->type != LT_POINT)
{ {
snprintf(uniform_name, MAX_NAME_LEN, "lights[%d].direction", i); snprintf(uniform_name, MAX_NAME_LEN, "lights[%d].direction", i);
transform_get_absolute_lookat(transform, &light_pos); transform_get_absolute_lookat(light_transform, &light_pos);
vec3_norm(&light_pos, &light_pos); vec3_norm(&light_pos, &light_pos);
shader_set_uniform_vec3(material->shader, uniform_name, &light_pos); shader_set_uniform_vec3(material->shader, uniform_name, &light_pos);
memset(uniform_name, '\0', MAX_NAME_LEN); memset(uniform_name, '\0', MAX_NAME_LEN);
@ -267,15 +217,14 @@ void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode)
} }
shader_set_uniform_int(material->shader, "total_active_lights", valid_light_count); shader_set_uniform_int(material->shader, "total_active_lights", valid_light_count);
struct Entity* camera_entity = entity_get(camera->node); struct Transform* camera_tran = &camera_entity->transform;
struct Transform* camera_tran = entity_component_get(camera_entity, C_TRANSFORM);
vec3 camera_pos = {0, 0, 0}; vec3 camera_pos = {0, 0, 0};
transform_get_absolute_pos(camera_tran, &camera_pos); transform_get_absolute_pos(camera_tran, &camera_pos);
shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos); shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos);
} }
/* Render the geometry */ /* Render the geometry */
int indices = geom_render_in_frustum(model->geometry_index, &camera->frustum[0], transform, draw_mode); int indices = geom_render_in_frustum(model->geometry_index, &camera_entity->camera.frustum[0], transform, draw_mode);
if(indices > 0) if(indices > 0)
{ {
num_rendered++; num_rendered++;
@ -322,27 +271,13 @@ int model_set_material_param(struct Model* model, const char* name, void* value)
success = 1; success = 1;
switch(uniform->type) switch(uniform->type)
{ {
case UT_INT: case UT_INT: *((int*)param->value) = *((int*)value); break;
*((int*)param->value) = *((int*)value); case UT_FLOAT: *((float*)param->value) = *((float*)value); break;
break; case UT_VEC2: vec2_assign((vec2*)param->value, (vec2*)value); break;
case UT_FLOAT: case UT_VEC3: vec3_assign((vec3*)param->value, (vec3*)value); break;
*((float*)param->value) = *((float*)value); case UT_VEC4: vec4_assign((vec4*)param->value, (vec4*)value); break;
break; case UT_MAT4: mat4_assign((mat4*)param->value, (mat4*)value); break;
case UT_VEC2: case UT_TEX: *((int*)param->value) = *((int*)value); break;
vec2_assign((vec2*)param->value, (vec2*)value);
break;
case UT_VEC3:
vec3_assign((vec3*)param->value, (vec3*)value);
break;
case UT_VEC4:
vec4_assign((vec4*)param->value, (vec4*)value);
break;
case UT_MAT4:
mat4_assign((mat4*)param->value, (mat4*)value);
break;
case UT_TEX:
*((int*)param->value) = *((int*)value);
break;
default: default:
log_error("model:set_material_param", "Invalid parameter type"); log_error("model:set_material_param", "Invalid parameter type");
success = 0; success = 0;
@ -374,36 +309,32 @@ int model_get_material_param(struct Model* model, const char* name, void* value_
case UT_VEC4: vec4_assign((vec4*)value_out, (vec4*)param->value); break; case UT_VEC4: vec4_assign((vec4*)value_out, (vec4*)param->value); break;
case UT_MAT4: mat4_assign((mat4*)value_out, (mat4*)param->value); break; case UT_MAT4: mat4_assign((mat4*)value_out, (mat4*)param->value); break;
} }
break; /* break for */
success = 1; success = 1;
break;
} }
} }
return success; return success;
} }
struct Model* model_get_all(void) void model_render_all_debug(struct Entity* camera_entity,
{ int debug_shader,
return model_list; int draw_mode,
} const vec4* debug_color)
void model_render_all_debug(struct Camera* camera,
int debug_shader,
enum Geometry_Draw_Mode draw_mode,
const vec4* debug_color)
{ {
assert(debug_shader > -1); assert(debug_shader > -1);
shader_bind(debug_shader); shader_bind(debug_shader);
{ {
static mat4 mvp; static mat4 mvp;
shader_set_uniform_vec4(debug_shader, "debug_color", debug_color); shader_set_uniform_vec4(debug_shader, "debug_color", debug_color);
for(int i = 0; i < array_len(model_list); i++) struct Entity* entity_list = entity_get_all();
for(int i = 0; i < array_len(entity_list); i++)
{ {
struct Model* model = &model_list[i]; if(!entity_list[i].renderable) continue;
struct Entity* entity = entity_get(model->node); struct Model* model = &entity_list[i].model;
struct Transform* transform = entity_component_get(entity, C_TRANSFORM); struct Transform* transform = &entity_list[i].transform;
int geometry = model->geometry_index; int geometry = model->geometry_index;
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &camera_entity->camera.view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(debug_shader, "mvp", &mvp); shader_set_uniform_mat4(debug_shader, "mvp", &mvp);
geom_render(geometry, draw_mode); geom_render(geometry, draw_mode);
} }

@ -2,31 +2,22 @@
#define MODEL_H #define MODEL_H
#include "linmath.h" #include "linmath.h"
#include "geometry.h"
struct Camera; struct Camera;
struct Material_Param; struct Material_Param;
struct Model;
struct Entity;
struct Model
{
int node;
int geometry_index;
int material;
struct Material_Param* material_params;
};
struct Model* model_get(int index);
struct Model* model_get_all(void);
void model_init(void); void model_init(void);
int model_create(int node, const char* geo_name, const char* material_name); void model_create(struct Model* model, int entity_id, const char* geo_name, const char* material_name);
void model_remove(int index); void model_destroy(struct Model* model, int entity_id);
void model_cleanup(void); void model_cleanup(void);
void model_render_all(struct Camera* camera, enum Geometry_Draw_Mode draw_mode); void model_render_all(struct Entity* camera_entity, int draw_mode);
int model_set_material_param(struct Model* model, const char* name, void* value); int model_set_material_param(struct Model* model, const char* name, void* value);
int model_get_material_param(struct Model* model, const char* name, void* value_out); int model_get_material_param(struct Model* model, const char* name, void* value_out);
void model_render_all_debug(struct Camera* camera, void model_render_all_debug(struct Entity* camera_entity,
int debug_shader, int debug_shader,
enum Geometry_Draw_Mode draw_mode, int draw_mode,
const vec4* debug_color); const vec4* debug_color);
#endif #endif

@ -2,6 +2,7 @@
#define num_types_H #define num_types_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
typedef int8_t int8; typedef int8_t int8;
typedef int32_t int32; typedef int32_t int32;

@ -16,6 +16,7 @@
#include "gui.h" #include "gui.h"
#include "config_vars.h" #include "config_vars.h"
#include "hashmap.h" #include "hashmap.h"
#include "geometry.h"
static int def_fbo = -1; static int def_fbo = -1;
static int def_albedo_tex = -1; static int def_albedo_tex = -1;
@ -122,14 +123,14 @@ void renderer_init(void)
debug_shader = shader_create("debug.vert", "debug.frag"); debug_shader = shader_create("debug.vert", "debug.frag");
} }
void renderer_draw(void) void renderer_draw(struct Entity* active_viewer)
{ {
struct Camera* camera_list = camera_get_all(); struct Entity* entity_list = entity_get_all();
for(int i = 0; i < array_len(camera_list); i++) for(int i = 0; i < array_len(entity_list); i++)
{ {
struct Camera* camera = &camera_list[i]; struct Entity* viewer = &entity_list[i];
if(camera->node < 0) if(entity_list[i].type != ET_CAMERA) continue;
continue; struct Camera* camera = &viewer->camera;
/* if(camera->fbo == -1) continue; */ /* if(camera->fbo == -1) continue; */
int fbo = camera->fbo == -1 ? def_fbo : camera->fbo; int fbo = camera->fbo == -1 ? def_fbo : camera->fbo;
@ -145,7 +146,7 @@ void renderer_draw(void)
glEnable(GL_CULL_FACE ); glEnable(GL_CULL_FACE );
glCullFace(GL_BACK); glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model_render_all(camera, GDM_TRIANGLES); model_render_all(viewer, GDM_TRIANGLES);
} }
framebuffer_unbind(); framebuffer_unbind();
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -176,7 +177,7 @@ void renderer_draw(void)
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader_bind(composition_shader); shader_bind(composition_shader);
struct Camera* active_camera = camera_get_primary(); struct Camera* active_camera = &active_viewer->camera;
int final_render_tex = active_camera->render_tex == -1 ? def_albedo_tex : active_camera->render_tex; int final_render_tex = active_camera->render_tex == -1 ? def_albedo_tex : active_camera->render_tex;
texture_bind(final_render_tex); texture_bind(final_render_tex);
geom_render(quad_geo, GDM_TRIANGLES); geom_render(quad_geo, GDM_TRIANGLES);
@ -186,7 +187,7 @@ void renderer_draw(void)
if(settings.debug_draw_enabled) if(settings.debug_draw_enabled)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
model_render_all_debug(active_camera, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color); model_render_all_debug(active_viewer, debug_shader, settings.debug_draw_mode, &settings.debug_draw_color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
@ -204,7 +205,17 @@ void renderer_cleanup(void)
void on_framebuffer_size_change(int width, int height) void on_framebuffer_size_change(int width, int height)
{ {
camera_resize_all(width, height); struct Entity* entity_list = entity_get_all();
float aspect = (float)width / (float)height;
for(int i = 0; i < array_len(entity_list); i++)
{
struct Entity* viewer = &entity_list[i];
if(viewer->type != ET_CAMERA) continue;
viewer->camera.aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(&viewer->camera);
}
framebuffer_resize_all(width, height); framebuffer_resize_all(width, height);
} }

@ -2,7 +2,6 @@
#define renderer_H #define renderer_H
#include "linmath.h" #include "linmath.h"
#include "geometry.h"
enum Fog_Mode enum Fog_Mode
{ {
@ -24,18 +23,20 @@ struct Fog
struct Render_Settings struct Render_Settings
{ {
struct Fog fog; struct Fog fog;
vec3 ambient_light; vec3 ambient_light;
int max_gui_vertex_memory; int max_gui_vertex_memory;
int max_gui_element_memory; int max_gui_element_memory;
int debug_draw_enabled; int debug_draw_enabled;
vec4 debug_draw_color; vec4 debug_draw_color;
enum Geometry_Draw_Mode debug_draw_mode; int debug_draw_mode;
}; };
struct Entity;
struct Render_Settings* renderer_settings_get(void); struct Render_Settings* renderer_settings_get(void);
void renderer_init(void); void renderer_init(void);
void renderer_draw(void); void renderer_draw(struct Entity* active_viewer);
void renderer_cleanup(void); void renderer_cleanup(void);
void renderer_clearcolor_set(float r, float g, float b, float a); void renderer_clearcolor_set(float r, float g, float b, float a);
void renderer_debug_draw_enabled(int enabled); void renderer_debug_draw_enabled(int enabled);

@ -12,52 +12,50 @@ static int root_node = -1;
void scene_init(void) void scene_init(void)
{ {
/* Add root node to scene */ /* Add root node to scene */
struct Entity* root = entity_create("ROOT", NULL); struct Entity* root = entity_create("ROOT", ET_ROOT, -1);
root_node = root->node; root_node = root->id;
} }
struct Entity* scene_add_new(const char* name, const char* tag) struct Entity* scene_add_new(const char* name, const int type)
{ {
return scene_add_as_child(name, tag, root_node); return scene_add_as_child(name, type, root_node);
} }
struct Entity* scene_add_as_child(const char* name, const char* tag, int parent_node) struct Entity* scene_add_as_child(const char* name, const int type, int parent_id)
{ {
assert(parent_node > -1); assert(parent_id > -1);
struct Entity* new_entity = NULL; struct Entity* new_entity = NULL;
new_entity = entity_create(name, tag); new_entity = entity_create(name, type, parent_id);
struct Entity* parent = entity_get(parent_node); struct Entity* parent = entity_get(parent_id);
new_entity->parent = parent->node; new_entity->transform.parent = parent->id;
array_push(parent->children, new_entity->node, int); transform_update_transmat(&new_entity->transform);
struct Transform* new_ent_tran = entity_component_get(new_entity, C_TRANSFORM);
transform_update_transmat(new_ent_tran);
return new_entity; return new_entity;
} }
void scene_remove(struct Entity* entity) void scene_remove(struct Entity* entity)
{ {
assert(entity); assert(entity);
for(int i = 0; i < array_len(entity->children); i++) for(int i = 0; i < array_len(entity->transform.children); i++)
{ {
struct Entity* child = entity_get(entity->children[i]); struct Entity* child = entity_get(entity->transform.children[i]);
scene_remove(child); scene_remove(child);
} }
entity_remove(entity->node); entity_remove(entity->id);
} }
void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) void scene_reset_parent(struct Entity* entity, struct Entity* new_parent)
{ {
assert(entity && new_parent); assert(entity && new_parent);
struct Entity* curr_parent = entity_get(entity->parent); struct Entity* curr_parent = entity_get(entity->transform.parent);
if(curr_parent) if(curr_parent)
{ {
/* find the index that the entity is at in the cuurent parent's /* find the index that the entity is at in the cuurent parent's
children array and remove it from there. Then set the new_parent children array and remove it from there. Then set the new_parent
as the entity's parent */ as the entity's parent */
int index = -1; int index = -1;
for(int i = 0; i < array_len(curr_parent->children); i++) for(int i = 0; i < array_len(curr_parent->transform.children); i++)
{ {
if(curr_parent->children[i] == entity->node) if(curr_parent->transform.children[i] == entity->id)
{ {
index = i; index = i;
break; break;
@ -66,11 +64,10 @@ void scene_reset_parent(struct Entity* entity, struct Entity* new_parent)
if(index > -1) if(index > -1)
{ {
array_remove_at(curr_parent->children, index); array_remove_at(curr_parent->transform.children, index);
entity->parent = new_parent->node; entity->transform.parent = new_parent->id;
array_push(new_parent, entity->node, int); array_push(new_parent, entity->id, int);
struct Transform* entity_tran = entity_component_get(entity, C_TRANSFORM); transform_update_transmat(&entity->transform);
transform_update_transmat(entity_tran);
} }
else else
{ {
@ -88,9 +85,10 @@ void scene_cleanup(void)
struct Entity* entity_list = entity_get_all(); struct Entity* entity_list = entity_get_all();
for(int i = 0; i < array_len(entity_list); i++) for(int i = 0; i < array_len(entity_list); i++)
{ {
if(entity_list[i].node != -1) if(entity_list[i].id != -1)
entity_remove(i); entity_remove(i);
} }
entity_post_update();
} }
struct Entity* scene_find(const char* name) struct Entity* scene_find(const char* name)
@ -107,9 +105,9 @@ struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name)
{ {
assert(parent); assert(parent);
struct Entity* child = NULL; struct Entity* child = NULL;
for(int i = 0; i < array_len(parent->children); i++) for(int i = 0; i < array_len(parent->transform.children); i++)
{ {
struct Entity* curr_child = entity_get(parent->children[i]); struct Entity* curr_child = entity_get(parent->transform.children[i]);
if(strcmp(curr_child->name, name) == 0) if(strcmp(curr_child->name, name) == 0)
{ {
child = curr_child; child = curr_child;
@ -123,7 +121,7 @@ struct Entity* scene_get_parent(struct Entity* entity)
{ {
assert(entity); assert(entity);
struct Entity* parent = NULL; struct Entity* parent = NULL;
if(entity->parent != -1) if(entity->transform.parent != -1)
parent = entity_get(entity->parent); parent = entity_get(entity->transform.parent);
return parent; return parent;
} }

@ -1,5 +1,5 @@
#ifndef scene_H #ifndef SCENE_H
#define scene_H #define SCENE_H
struct Entity; struct Entity;
@ -7,8 +7,8 @@ void scene_init(void);
void scene_remove(struct Entity* entity); void scene_remove(struct Entity* entity);
void scene_reset_parent(struct Entity* entity, struct Entity* new_parent); void scene_reset_parent(struct Entity* entity, struct Entity* new_parent);
void scene_cleanup(void); void scene_cleanup(void);
struct Entity* scene_add_new(const char* name, const char* tag); /* Add as child of Root */ struct Entity* scene_add_new(const char* name, const int type); /* Add as child of Root */
struct Entity* scene_add_as_child(const char* name, const char* tag, int parent_node); struct Entity* scene_add_as_child(const char* name, const int type, int parent);
struct Entity* scene_find(const char* name); struct Entity* scene_find(const char* name);
struct Entity* scene_get_root(void); struct Entity* scene_get_root(void);
struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name);

@ -22,14 +22,10 @@ struct Sound_State
}; };
static struct Sound_State sound_state; static struct Sound_State sound_state;
static struct Sound_Source* sound_sources_list = NULL;
static int* empty_indices = NULL;
int sound_init(void) bool sound_init(void)
{ {
int success = 0; bool success = false;
sound_sources_list = array_new(struct Sound_Source);
empty_indices = array_new(int);
sound_state.device = alcOpenDevice(NULL); sound_state.device = alcOpenDevice(NULL);
if(!sound_state.device) if(!sound_state.device)
@ -61,7 +57,7 @@ int sound_init(void)
al_check(alListener3f(AL_POSITION, 0.f, 0.f, 0.f)) al_check(alListener3f(AL_POSITION, 0.f, 0.f, 0.f))
al_check(alListenerfv(AL_ORIENTATION, orientation)) al_check(alListenerfv(AL_ORIENTATION, orientation))
success = 1; success = true;
return success; return success;
} }
@ -71,27 +67,26 @@ void sound_listener_set(int listener_entity)
if(sound_state.listener_entity != -1) if(sound_state.listener_entity != -1)
{ {
struct Entity* current_listener = entity_get(sound_state.listener_entity); struct Entity* current_listener = entity_get(sound_state.listener_entity);
current_listener->is_listener = 0; current_listener->is_listener = false;
} }
sound_state.listener_entity = listener_entity; sound_state.listener_entity = listener_entity;
struct Entity* entity = entity_get(listener_entity); struct Entity* entity = entity_get(listener_entity);
entity->is_listener = 1; entity->is_listener = true;
sound_listener_update(); sound_listener_update();
} }
void sound_listener_update(void) void sound_listener_update(void)
{ {
if(sound_state.listener_entity == -1) return; if(sound_state.listener_entity == -1) return;
struct Entity* entity = entity_get(sound_state.listener_entity); struct Entity* entity = entity_get(sound_state.listener_entity);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
vec3 abs_pos = {0.f, 0.f, 0.f}; vec3 abs_pos = {0.f, 0.f, 0.f};
vec3 abs_up = {0.f, 1.f, 0.f}; vec3 abs_up = {0.f, 1.f, 0.f};
vec3 abs_forward = {0.f, 0.f, -1.f}; vec3 abs_forward = {0.f, 0.f, -1.f};
transform_get_absolute_pos(transform, &abs_pos); transform_get_absolute_pos(&entity->transform, &abs_pos);
transform_get_absolute_up(transform, &abs_up); transform_get_absolute_up(&entity->transform, &abs_up);
transform_get_absolute_forward(transform, &abs_forward); transform_get_absolute_forward(&entity->transform, &abs_forward);
float orientation[] = float orientation[] =
{ {
abs_forward.x, abs_forward.y, abs_forward.z, abs_forward.x, abs_forward.y, abs_forward.z,
@ -112,10 +107,9 @@ void sound_volume_set(float volume)
al_check(alListenerf(AL_GAIN, volume)) al_check(alListenerf(AL_GAIN, volume))
} }
void sound_source_remove(int index) void sound_source_destroy(struct Sound_Source* source)
{ {
assert(index > -1 && index < array_len(sound_sources_list)); assert(source);
struct Sound_Source* source = &sound_sources_list[index];
if(!source->active) return; if(!source->active) return;
if(alIsBuffer(source->al_buffer_handle) == AL_TRUE) if(alIsBuffer(source->al_buffer_handle) == AL_TRUE)
{ {
@ -124,21 +118,13 @@ void sound_source_remove(int index)
al_check(alDeleteBuffers(1, &source->al_buffer_handle)) al_check(alDeleteBuffers(1, &source->al_buffer_handle))
} }
if(alIsSource(source->al_source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source->al_source_handle)) if(alIsSource(source->al_source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source->al_source_handle))
source->entity = -1;
source->al_buffer_handle = 0; source->al_buffer_handle = 0;
source->al_source_handle = 0; source->al_source_handle = 0;
source->active = 0; source->active = false;
array_push(empty_indices, index, int);
} }
void sound_cleanup(void) void sound_cleanup(void)
{ {
for(int i = 0; i < array_len(sound_sources_list); i++)
sound_source_remove(i);
array_free(sound_sources_list);
array_free(empty_indices);
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(sound_state.context); alcDestroyContext(sound_state.context);
alcCloseDevice(sound_state.device); alcCloseDevice(sound_state.device);
@ -162,39 +148,21 @@ void sound_error_check(const char* file, unsigned int line, const char* expressi
} }
} }
int sound_source_create(int entity) void sound_source_create(struct Sound_Source* source, struct Transform* transform)
{ {
int index = -1; assert(source);
struct Sound_Source* new_source = NULL; source->active = true;
if(array_len(empty_indices) > 0) al_check(alGenSources(1, &source->al_source_handle))
{ al_check(alGenBuffers(1, &source->al_buffer_handle))
index = *array_get_last(empty_indices, int); sound_source_volume_set(source, 1.f);
array_pop(empty_indices); if(transform)
new_source = &sound_sources_list[index]; sound_source_update(source, transform);
}
else
{
new_source = array_grow(sound_sources_list, struct Sound_Source);
index = array_len(sound_sources_list) - 1;
}
new_source->entity = entity;
new_source->active = 1;
al_check(alGenSources(1, &new_source->al_source_handle))
al_check(alGenBuffers(1, &new_source->al_buffer_handle))
sound_source_volume_set(new_source, 1.f);
if(entity > -1)
sound_source_update(new_source);
else else
sound_source_relative_set(new_source, 1); sound_source_relative_set(source, 1);
return index;
} }
void sound_source_update(struct Sound_Source* source) void sound_source_update(struct Sound_Source* source, struct Transform* transform)
{ {
if(source->entity < 0) return;
struct Entity* entity = entity_get(source->entity);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
vec3 abs_pos = {0.f, 0.f, 0.f}; vec3 abs_pos = {0.f, 0.f, 0.f};
vec3 abs_up = {0.f, 1.f, 0.f}; vec3 abs_up = {0.f, 1.f, 0.f};
vec3 abs_forward = {0.f, 0.f, -1.f}; vec3 abs_forward = {0.f, 0.f, -1.f};
@ -223,13 +191,13 @@ void sound_source_pitch_set(struct Sound_Source* source, float pitch)
al_check(alSourcef(source->al_source_handle, AL_PITCH, pitch)) al_check(alSourcef(source->al_source_handle, AL_PITCH, pitch))
} }
void sound_source_loop_set(struct Sound_Source* source, int loop) void sound_source_loop_set(struct Sound_Source* source, bool loop)
{ {
loop = loop ? AL_TRUE : AL_FALSE; loop = loop ? AL_TRUE : AL_FALSE;
al_check(alSourcei(source->al_source_handle, AL_LOOPING, loop)) al_check(alSourcei(source->al_source_handle, AL_LOOPING, loop))
} }
void sound_source_relative_set(struct Sound_Source* source, int relative) void sound_source_relative_set(struct Sound_Source* source, bool relative)
{ {
relative = relative ? AL_TRUE : AL_FALSE; relative = relative ? AL_TRUE : AL_FALSE;
al_check(alSourcei(source->al_source_handle, AL_SOURCE_RELATIVE, relative)); al_check(alSourcei(source->al_source_handle, AL_SOURCE_RELATIVE, relative));
@ -263,7 +231,7 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name)
return; return;
} }
int mono = wav_spec.channels == 1 ? 1 : 0; bool mono = wav_spec.channels == 1 ? true : false;
int format = -1; int format = -1;
if(mono) if(mono)
{ {
@ -277,10 +245,12 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name)
else else
{ {
/* TODO: FIX THIS!!!! This should resemble the if condition */ /* TODO: FIX THIS!!!! This should resemble the if condition */
if(wav_spec.format == AUDIO_U8) if(wav_spec.format == AUDIO_U8 || wav_spec.format == AUDIO_S8)
format = AL_FORMAT_STEREO8; format = AL_FORMAT_STEREO8;
else if(wav_spec.format == AUDIO_S16) else if(wav_spec.format == AUDIO_S16 || wav_spec.format == AUDIO_S16LSB || wav_spec.format == AUDIO_S16MSB || wav_spec.format == AUDIO_S16SYS)
format = AL_FORMAT_STEREO16; format = AL_FORMAT_STEREO16;
else if(wav_spec.format == AUDIO_F32 || wav_spec.format == AUDIO_F32LSB || wav_spec.format == AUDIO_F32MSB || wav_spec.format == AUDIO_F32SYS || wav_spec.format == AUDIO_S32 || wav_spec.format == AUDIO_S32LSB)
format = AL_FORMAT_STEREO_FLOAT32;
} }
if(format == -1) if(format == -1)
@ -295,12 +265,6 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name)
SDL_FreeWAV(wav_data); SDL_FreeWAV(wav_data);
} }
struct Sound_Source* sound_source_get(int index)
{
assert(index > -1 && index < array_len(sound_sources_list));
return &sound_sources_list[index];
}
void sound_source_play(struct Sound_Source* source) { al_check(alSourcePlay(source->al_source_handle)) } void sound_source_play(struct Sound_Source* source) { al_check(alSourcePlay(source->al_source_handle)) }
void sound_source_pause(struct Sound_Source* source) { al_check(alSourcePause(source->al_source_handle)) } void sound_source_pause(struct Sound_Source* source) { al_check(alSourcePause(source->al_source_handle)) }
void sound_source_rewind(struct Sound_Source* source) { al_check(alSourceRewind(source->al_source_handle)) } void sound_source_rewind(struct Sound_Source* source) { al_check(alSourceRewind(source->al_source_handle)) }

@ -9,15 +9,10 @@
#define al_check(expr) expr; #define al_check(expr) expr;
#endif #endif
struct Sound_Source struct Sound_Source;
{ struct Transform;
int entity;
uint al_source_handle;
uint al_buffer_handle;
int active;
};
int sound_init(void); bool sound_init(void);
void sound_cleanup(void); void sound_cleanup(void);
void sound_volume_set(float volume); void sound_volume_set(float volume);
void sound_error_check(const char* file, unsigned int line, const char* expression); void sound_error_check(const char* file, unsigned int line, const char* expression);
@ -26,18 +21,17 @@ void sound_listener_set(int entity);
int sound_listener_get(void); int sound_listener_get(void);
void sound_listener_update(void); void sound_listener_update(void);
struct Sound_Source* sound_source_get(int index); void sound_source_create(struct Sound_Source* source, struct Transform* transform);
int sound_source_create(int entity); void sound_source_destroy(struct Sound_Source* source);
void sound_source_remove(int index); void sound_source_update(struct Sound_Source* source, struct Transform* transform);
void sound_source_update(struct Sound_Source* source); void sound_source_volume_set(struct Sound_Source* source, float volume);
void sound_source_volume_set(struct Sound_Source* source, float volume); void sound_source_pitch_set(struct Sound_Source* source, float pitch);
void sound_source_pitch_set(struct Sound_Source* source, float pitch); void sound_source_load_wav(struct Sound_Source* source, const char* file_name);
void sound_source_load_wav(struct Sound_Source* source, const char* file_name); void sound_source_loop_set(struct Sound_Source* source, bool loop);
void sound_source_loop_set(struct Sound_Source* source, int loop); void sound_source_relative_set(struct Sound_Source* source, bool relative);
void sound_source_relative_set(struct Sound_Source* source, int relative); void sound_source_play(struct Sound_Source* source);
void sound_source_play(struct Sound_Source* source); void sound_source_pause(struct Sound_Source* source);
void sound_source_pause(struct Sound_Source* source); void sound_source_rewind(struct Sound_Source* source);
void sound_source_rewind(struct Sound_Source* source); void sound_source_stop(struct Sound_Source* source);
void sound_source_stop(struct Sound_Source* source);
#endif #endif

@ -380,7 +380,7 @@ int texture_create(const char* name,
int type, int type,
const void* data) const void* data)
{ {
assert(name && texture_unit > -1 && texture_unit <= TU_SHADOWMAP4); assert(texture_unit > -1 && texture_unit <= TU_SHADOWMAP4);
int index = -1; int index = -1;
uint handle = 0; uint handle = 0;
int success = create_gl_texture(&handle, width, height, format, internal_format, type, data); int success = create_gl_texture(&handle, width, height, format, internal_format, type, data);
@ -398,7 +398,7 @@ int texture_create(const char* name,
new_tex = array_grow(texture_list, struct Texture); new_tex = array_grow(texture_list, struct Texture);
index = array_len(texture_list) - 1; index = array_len(texture_list) - 1;
} }
new_tex->name = str_new(name); new_tex->name = name ? str_new(name) : str_new("texture_%d", index);
new_tex->handle = handle; new_tex->handle = handle;
new_tex->ref_count = 1; new_tex->ref_count = 1;
new_tex->texture_unit = texture_unit; new_tex->texture_unit = texture_unit;

@ -5,46 +5,16 @@
#include "utils.h" #include "utils.h"
#include <assert.h> #include <assert.h>
static struct Transform* transform_list; void transform_create(struct Transform* transform, int parent_entity)
static int* empty_indices;
void transform_init(void)
{ {
transform_list = array_new(struct Transform); assert(transform);
empty_indices = array_new(int); vec3_fill(&transform->position, 0.f, 0.f, 0.f);
} vec3_fill(&transform->scale, 1.f, 1.f, 1.f);
quat_identity(&transform->rotation);
void transform_cleanup(void) mat4_identity(&transform->trans_mat);
{ transform->parent = parent_entity;
array_free(transform_list); transform->children = array_new(int);
array_free(empty_indices); transform_update_transmat(transform);
}
int transform_create(int node)
{
int index = -1;
if(node > -1)
{
struct Transform* new_transform = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_transform = &transform_list[index];
}
else
{
new_transform = array_grow(transform_list, struct Transform);
index = array_len(transform_list) - 1;
}
new_transform->node = node;
vec3_fill(&new_transform->position, 0.f, 0.f, 0.f);
vec3_fill(&new_transform->scale, 1.f, 1.f, 1.f);
quat_identity(&new_transform->rotation);
mat4_identity(&new_transform->trans_mat);
transform_update_transmat(new_transform);
}
return index;
} }
void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space) void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space)
@ -57,16 +27,20 @@ void transform_translate(struct Transform* transform, vec3* amount, enum Transfo
} }
else if(space == TS_PARENT) else if(space == TS_PARENT)
{ {
struct Entity* parent = entity_get_parent(transform->node); struct Entity* parent = entity_get_parent(transform->parent);
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); if(parent)
quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount); {
struct Transform* parent_tran = &parent->transform;
quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount);
}
} }
vec3_add(&transform->position, &transform->position, &translation_amount); vec3_add(&transform->position, &transform->position, &translation_amount);
transform_update_transmat(transform); transform_update_transmat(transform);
} }
void transform_rotate(struct Transform* transform,
vec3* axis, void transform_rotate(struct Transform* transform,
float angle, vec3* axis,
float angle,
enum Transform_Space space) enum Transform_Space space)
{ {
quat new_rot; quat new_rot;
@ -158,42 +132,48 @@ void transform_update_transmat(struct Transform* transform)
mat4_mul(&transform->trans_mat, &transform->trans_mat, &rotation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &rotation);
mat4_mul(&transform->trans_mat, &transform->trans_mat, &scale); mat4_mul(&transform->trans_mat, &transform->trans_mat, &scale);
struct Entity* entity = entity_get(transform->node); struct Entity* parent = entity_get(transform->parent);
if(entity) /* Only update if transform is attached to an entity */ if(parent)
{ {
struct Entity* parent = entity_get(entity->parent); struct Transform* parent_tran = &parent->transform;
if(parent) mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat);
{ }
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM);
mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat);
}
/* Update all children */ /* Update all children */
int children = array_len(entity->children); int children = array_len(transform->children);
if(children > 0) if(children > 0)
{
for(int i = 0; i < children; i++)
{ {
for(int i = 0; i < children; i++) struct Entity* child = entity_get(transform->children[i]);
{ struct Transform* child_tran = &child->transform;
struct Entity* child = entity_get(entity->children[i]); transform_update_transmat(child_tran);
struct Transform* child_tran = entity_component_get(child, C_TRANSFORM);
transform_update_transmat(child_tran);
}
} }
entity_sync_components(entity);
} }
transform->is_modified = true;
} }
struct Transform* transform_get(int index) void transform_destroy(struct Transform* transform)
{ {
assert(index > -1 && index < array_len(transform_list)); assert(transform);
return &transform_list[index]; int children = array_len(transform->children);
} if(children > 0)
{
void transform_remove(int index) for(int i = 0; i < children; i++)
{ {
assert(index > -1 && index < array_len(transform_list)); struct Entity* child = entity_get(transform->children[i]);
transform_list[index].node = -1; child->marked_for_deletion = true;
array_push(empty_indices, index, int); }
}
/* Remove transform */
array_free(transform->children);
vec3_fill(&transform->position, 0.f, 0.f, 0.f);
vec3_fill(&transform->scale, 1.f, 1.f, 1.f);
quat_identity(&transform->rotation);
mat4_identity(&transform->trans_mat);
transform->parent = -1;
transform->is_modified = false;
} }
void transform_set_position(struct Transform* transform, vec3* new_position) void transform_set_position(struct Transform* transform, vec3* new_position)
@ -204,11 +184,10 @@ void transform_set_position(struct Transform* transform, vec3* new_position)
void transform_get_absolute_pos(struct Transform* transform, vec3* res) void transform_get_absolute_pos(struct Transform* transform, vec3* res)
{ {
struct Entity* entity = entity_get(transform->node); struct Entity* parent = entity_get(transform->parent);
struct Entity* parent = entity_get(entity->parent);
if(parent) if(parent)
{ {
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); struct Transform* parent_tran = &parent->transform;
transform_get_absolute_pos(parent_tran, res); transform_get_absolute_pos(parent_tran, res);
} }
vec3_add(res, res, &transform->position); vec3_add(res, res, &transform->position);
@ -216,11 +195,10 @@ void transform_get_absolute_pos(struct Transform* transform, vec3* res)
void transform_get_absolute_scale(struct Transform* transform, vec3* res) void transform_get_absolute_scale(struct Transform* transform, vec3* res)
{ {
struct Entity* entity = entity_get(transform->node); struct Entity* parent = entity_get(transform->parent);
struct Entity* parent = entity_get(entity->parent);
if(parent) if(parent)
{ {
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); struct Transform* parent_tran = &parent->transform;
transform_get_absolute_scale(parent_tran, res); transform_get_absolute_scale(parent_tran, res);
} }
vec3_add(res, res, &transform->scale); vec3_add(res, res, &transform->scale);
@ -228,11 +206,10 @@ void transform_get_absolute_scale(struct Transform* transform, vec3* res)
void transform_get_absolute_rot(struct Transform* transform, quat* res) void transform_get_absolute_rot(struct Transform* transform, quat* res)
{ {
struct Entity* entity = entity_get(transform->node); struct Entity* parent = entity_get(transform->parent);
struct Entity* parent = entity_get(entity->parent);
if(parent) if(parent)
{ {
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM); struct Transform* parent_tran = &parent->transform;
transform_get_absolute_rot(parent_tran, res); transform_get_absolute_rot(parent_tran, res);
} }
quat_mul(res, res, &transform->rotation); quat_mul(res, res, &transform->rotation);

@ -1,24 +1,14 @@
#ifndef _transform_H #ifndef TRANSFORM_H
#define _transform_H #define TRANSFORM_H
#include "linmath.h" #include "linmath.h"
enum Transform_Space { TS_LOCAL, TS_PARENT, TS_WORLD}; enum Transform_Space { TS_LOCAL, TS_PARENT, TS_WORLD};
struct Transform struct Transform;
{
int node;
vec3 position;
vec3 scale;
quat rotation;
mat4 trans_mat;
};
struct Transform* transform_get(int index); void transform_create(struct Transform* transform, int parent_entity);
void transform_remove(int index); void transform_destroy(struct Transform* transform);
void transform_init(void);
void transform_cleanup(void);
int transform_create(int node);
void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space); void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space);
void transform_rotate(struct Transform* transform, void transform_rotate(struct Transform* transform,
vec3* axis, vec3* axis,

Loading…
Cancel
Save