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. 162
      src/camera.c
  4. 40
      src/camera.h
  5. 31
      src/components.h
  6. 200
      src/entity.c
  7. 122
      src/entity.h
  8. 80
      src/game.c
  9. 131
      src/light.c
  10. 37
      src/light.h
  11. 1
      src/material.c
  12. 149
      src/model.c
  13. 23
      src/model.h
  14. 1
      src/num_types.h
  15. 31
      src/renderer.c
  16. 7
      src/renderer.h
  17. 54
      src/scene.c
  18. 8
      src/scene.h
  19. 92
      src/sound.c
  20. 22
      src/sound.h
  21. 4
      src/texture.c
  22. 115
      src/transform.c
  23. 20
      src/transform.h

@ -56,6 +56,50 @@ Sprint: Left Shift
*** Level/Scene
*** Materials
*** 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
** DONE Input
- 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
- Custom rendering for gui
** 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
- State "DONE" from "TODO" [2017-05-08 Mon 00:57]
** DONE Reading from config file
@ -191,7 +239,8 @@ x Font atlas proper cleanup
** TODO Ray picking
** TODO Remove reduntant "settings" structures and move all configuration stuff to config variables
** 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 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.
@ -201,17 +250,19 @@ x Font atlas proper cleanup
? Game .so with init, update and cleanup functions
x Configuration files and "cvars" load/reload
x Keybindings in config
- Log output on every run.
x Log output on every run.
- Implement entity load/save to file
? Prefab load/save to file
** 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 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
- State "DONE" from "TODO" [2017-05-24 Wed 17:12]
** TODO Add default keybindings
** TODO Write default config/keybindings etc to file if none are found in preferences dir
** TODO Fix input map bugs
** TODO Flatpak packaging for linux releases
** TODO Use hashmap for debugvar slots in editor
** TODO Use hashmap to store input maps
** DONE Live data views in editor

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

@ -1,6 +1,7 @@
#include "camera.h"
#include "entity.h"
#include "transform.h"
#include "entity.h"
#include "array.h"
#include "framebuffer.h"
#include "texture.h"
@ -15,38 +16,16 @@
#include <string.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);
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);
empty_indices = array_new(int);
primary_camera_index = -1;
}
void camera_remove(int index)
{
if(index > -1 && index < array_len(camera_list))
{
struct Camera* camera = &camera_list[index];
assert(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 = camera->node = -1;
camera->ortho = camera->resizeable = 0;
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);
@ -54,53 +33,28 @@ void camera_remove(int index)
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;
struct Camera* new_camera = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
new_camera = &camera_list[index];
array_pop(empty_indices);
}
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;
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 = 0;
camera->resizeable = 1;
float aspect_ratio = (float)width / (float)height;
new_camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio;
mat4_identity(&new_camera->view_mat);
mat4_identity(&new_camera->proj_mat);
mat4_identity(&new_camera->view_proj_mat);
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(&new_camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(new_camera);
camera_update_proj(new_camera);
vec4_fill(&new_camera->clear_color, 1.f, 1.f, 1.f, 1.f);
return index;
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(camera, transform);
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)
@ -110,10 +64,8 @@ void camera_update_view_proj(struct Camera* 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 up = {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);
if(camera->fbo > -1)
{
char tex_name[128];
if(has_color)
{
snprintf(tex_name, 128, "cam_render_tex_%d", camera->node);
camera->render_tex = texture_create(tex_name,
camera->render_tex = texture_create(NULL,
TU_DIFFUSE,
width, height,
GL_RGBA,
@ -175,12 +125,9 @@ void camera_attach_fbo(struct Camera* camera,
framebuffer_set_texture(camera->fbo, camera->render_tex, FA_COLOR_ATTACHMENT0);
}
memset(tex_name, '\0', 128);
if(has_depth)
{
snprintf(tex_name, 128, "cam_depth_tex_%d", camera->node);
camera->depth_tex = texture_create(tex_name,
camera->depth_tex = texture_create(NULL,
TU_SHADOWMAP1,
width, height,
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)
{
assert(camera);
@ -280,15 +192,15 @@ static void update_frustum(struct Camera* camera)
}
}
void camera_resize_all(int width, int height)
{
for(int i = 0; i < array_len(camera_list); i++)
{
struct Camera* camera = &camera_list[i];
if(!camera->resizeable) continue;
float aspect = (float)width / (float)height;
camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(camera);
}
}
/* void camera_resize_all(int width, int height) */
/* { */
/* for(int i = 0; i < array_len(camera_list); i++) */
/* { */
/* struct Camera* camera = &camera_list[i]; */
/* if(!camera->resizeable) continue; */
/* float aspect = (float)width / (float)height; */
/* camera->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; */
/* camera_update_proj(camera); */
/* } */
/* } */

@ -1,36 +1,13 @@
#ifndef camera_H
#define camera_H
#ifndef CAMERA_H
#define CAMERA_H
#include "linmath.h"
struct Camera;
struct Transform;
struct Camera
{
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_destroy(struct Camera* camera);
void camera_create(struct Camera* camera, struct Transform* transform, int width, int height);
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_attach_fbo(struct Camera* camera,
int width,
@ -38,7 +15,6 @@ void camera_attach_fbo(struct Camera* camera,
int has_depth,
int has_color,
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

@ -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)
{
struct Entity* entity = &entity_list[index];
if(entity->node == -1) return;
for(int i = 0; i < NUM_COMPONENTS; i++)
{
if(i == C_TRANSFORM)
{
transform_remove(entity->components[i]);
entity->components[i] = -1;
}
else
{
entity_component_remove(entity, i);
}
}
entity->node = -1;
entity->parent = -1;
entity->is_listener = 0;
array_free(entity->children);
entity->children = NULL;
transform_destroy(&entity->transform);
switch(entity->type)
{
case ET_CAMERA: camera_destroy(&entity->camera); break;
case ET_LIGHT: light_destroy(&entity->light, entity->id); break;
case ET_SOUND_SOURCE: sound_source_destroy(&entity->sound_source); break;
case ET_STATIC_MESH: model_destroy(&entity->model, entity->id); break;
case ET_ROOT: break;
default: log_error("entity:remove", "Invalid entity type"); break;
};
entity->id = -1;
entity->is_listener = false;
entity->marked_for_deletion = false;
entity->renderable = false;
entity->name = NULL;
free(entity->name);
free(entity->tag);
entity->name = entity->tag = NULL;
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;
int index = -1;
@ -73,23 +68,18 @@ struct Entity* entity_create(const char* name, const char* tag)
else
{
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;
}
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->tag = tag ? str_new(tag) : str_new("DEFAULT_TAG");
new_entity->node = index;
new_entity->parent = -1;
new_entity->is_listener = 0;
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);
new_entity->id = index;
new_entity->is_listener = false;
new_entity->type = type;
new_entity->marked_for_deletion = false;
new_entity->renderable = false;
transform_create(&new_entity->transform, parent_id);
return new_entity;
}
@ -119,145 +109,35 @@ struct Entity* entity_find(const char* name)
return entity;
}
int entity_component_remove(struct Entity* entity, enum Component component)
void entity_post_update(void)
{
int success = 1;
assert(entity);
int comp_index = entity->components[component];
switch(component)
for(int i = 0; i < array_len(entity_list); i++)
{
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;
}
struct Entity* entity = &entity_list[i];
if(entity->id == -1) continue;
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)
if(entity->marked_for_deletion)
{
case C_TRANSFORM: comp_obj = transform_get(comp_index); break;
case C_MODEL: comp_obj = model_get(comp_index); break;
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;
}
entity_remove(i);
continue;
}
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:
for(int i = 0; i < array_len(entity_list); i++)
{
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;
}
struct Entity* entity = &entity_list[i];
if(entity->id == -1) continue;
if(new_comp_index == -1)
{
log_error("entity:component_add", "%s component not added to %s",
comp_to_str(component),
entity->name);
}
else
if(entity->transform.is_modified)
{
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;
}
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;
}
if(entity->type == ET_CAMERA)
camera_update_view(&entity->camera, &entity->transform);
else if(entity->type == ET_SOUND_SOURCE)
sound_source_update(&entity->sound_source, &entity->transform);
void entity_sync_components(struct Entity* entity)
{
if(entity_has_component(entity, C_CAMERA))
{
struct Camera* camera = entity_component_get(entity, C_CAMERA);
camera_update_view(camera);
if(entity->is_listener) sound_listener_update();
}
if(entity_has_component(entity, C_SOUND_SOURCE))
{
struct Sound_Source* source = entity_component_get(entity, C_SOUND_SOURCE);
sound_source_update(source);
}
if(entity->is_listener) sound_listener_update();
}
struct Entity* entity_get_all(void)
@ -269,6 +149,6 @@ struct Entity* entity_get_parent(int node)
{
struct Entity* parent = NULL;
struct Entity* entity = entity_get(node);
if(entity) parent = entity_get(entity->node);
if(entity) parent = entity_get(entity->transform.parent);
return parent;
}

@ -1,31 +1,123 @@
#ifndef entity_H
#define entity_H
#ifndef ENTITY_H
#define ENTITY_H
#include "components.h"
#include "linmath.h"
#include "num_types.h"
struct Entity
struct Material_Param;
enum Entity_Type
{
int node;
char* name;
char* tag;
int components[NUM_COMPONENTS];
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;
int is_listener;
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
{
int id;
int type;
char* name;
bool is_listener; /* TODO: Replace all booleans with flags */
bool marked_for_deletion;
bool renderable;
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_cleanup(void);
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_find(const char* name);
struct Entity* entity_get_all(void);
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

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

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

@ -1,43 +1,14 @@
#ifndef LIGHT_H
#define LIGHT_H
#include "num_types.h"
#include "linmath.h"
#define MAX_SHADOWMAPS 4
enum LightType
{
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;
struct Light* light_get(int index);
struct Light* light_get_all(void);
void light_init(void);
void light_cleanup(void);
void light_remove(int index);
int light_create(int node, int light_type);
void light_set_radius(struct Light* light, int radius);
int light_get_max_lights(void);
int* light_get_valid_indices(int* valid_light_count);
void light_destroy(struct Light* light, int entity_id);
void light_create(struct Light* light, int entity_id, int light_type);
int* light_get_valid_indices(int* out_count);
#endif

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

@ -1,7 +1,6 @@
#include "model.h"
#include "array.h"
#include "log.h"
#include "camera.h"
#include "entity.h"
#include "shader.h"
#include "transform.h"
@ -10,6 +9,7 @@
#include "material.h"
#include "light.h"
#include "editor.h"
#include "geometry.h"
#include "variant.h"
#include "bounding_volumes.h"
#include "gl_load.h"
@ -21,100 +21,50 @@
#define MAX_NAME_LEN 64
static struct Model* model_list;
static int* empty_indices;
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)
{
model_list = array_new(struct Model);
empty_indices = array_new(int);
num_culled_slot = editor_debugvar_slot_create("Culled 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);
}
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(!geo_name) geo_name = "default.pamesh";
int geo_index = geom_create_from_file(geo_name);
int index = -1;
struct Model* new_model = NULL;
if(geo_index > -1)
{
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"))
model->geometry_index = geo_index;
if(!material_register_model(model, entity_id, material_name ? material_name : "Unshaded"))
{
log_error("model:create", "Unable to register model with Unshaded material, component not added");
model_remove(index);
index = -1;
}
model_destroy(model, entity_id);
}
else
{
log_error("model:create", "Geometry '%s' not found.", geo_name);
}
return index;
}
void model_remove(int index)
void model_destroy(struct Model* model, int entity_id)
{
if(index > -1 && index < array_len(model_list))
{
struct Model* model = &model_list[index];
model->node = -1;
assert(model);
geom_remove(model->geometry_index);
model->geometry_index = -1;
material_unregister_model(model, index);
material_unregister_model(model, entity_id);
/* 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_push(empty_indices, index, int);
}
else
{
log_error("model:remove", "Invalid index");
}
}
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;
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 each registered model, set up uniforms and render */
struct Model* model = &model_list[material->registered_models[j]];
struct Entity* entity = entity_get(model->node);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
struct Entity* entity = entity_get(material->registered_models[i]);
struct Model* model = &entity->model;
struct Transform* transform = &entity->transform;
/* set material params for the model */
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)
{
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);
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)
{
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");
}
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);
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->node);
struct Transform* transform = entity_component_get(light_entity, C_TRANSFORM);
struct Entity* light_entity = entity_get(light_index_list[i]);
struct Light* light = &light_entity->light; /* TODO: Cull lights according to camera frustum */
struct Transform* light_transform = &light_entity->transform;
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)
{
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);
shader_set_uniform_vec3(material->shader, uniform_name, &light_pos);
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);
struct Entity* camera_entity = entity_get(camera->node);
struct Transform* camera_tran = entity_component_get(camera_entity, C_TRANSFORM);
struct Transform* camera_tran = &camera_entity->transform;
vec3 camera_pos = {0, 0, 0};
transform_get_absolute_pos(camera_tran, &camera_pos);
shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos);
}
/* 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)
{
num_rendered++;
@ -322,27 +271,13 @@ int model_set_material_param(struct Model* model, const char* name, void* value)
success = 1;
switch(uniform->type)
{
case UT_INT:
*((int*)param->value) = *((int*)value);
break;
case UT_FLOAT:
*((float*)param->value) = *((float*)value);
break;
case UT_VEC2:
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;
case UT_INT: *((int*)param->value) = *((int*)value); break;
case UT_FLOAT: *((float*)param->value) = *((float*)value); break;
case UT_VEC2: 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:
log_error("model:set_material_param", "Invalid parameter type");
success = 0;
@ -374,21 +309,16 @@ 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_MAT4: mat4_assign((mat4*)value_out, (mat4*)param->value); break;
}
break; /* break for */
success = 1;
break;
}
}
return success;
}
struct Model* model_get_all(void)
{
return model_list;
}
void model_render_all_debug(struct Camera* camera,
void model_render_all_debug(struct Entity* camera_entity,
int debug_shader,
enum Geometry_Draw_Mode draw_mode,
int draw_mode,
const vec4* debug_color)
{
assert(debug_shader > -1);
@ -396,14 +326,15 @@ void model_render_all_debug(struct Camera* camera,
{
static mat4 mvp;
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];
struct Entity* entity = entity_get(model->node);
struct Transform* transform = entity_component_get(entity, C_TRANSFORM);
if(!entity_list[i].renderable) continue;
struct Model* model = &entity_list[i].model;
struct Transform* transform = &entity_list[i].transform;
int geometry = model->geometry_index;
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);
geom_render(geometry, draw_mode);
}

@ -2,31 +2,22 @@
#define MODEL_H
#include "linmath.h"
#include "geometry.h"
struct Camera;
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);
int model_create(int node, const char* geo_name, const char* material_name);
void model_remove(int index);
void model_create(struct Model* model, int entity_id, const char* geo_name, const char* material_name);
void model_destroy(struct Model* model, int entity_id);
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_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,
enum Geometry_Draw_Mode draw_mode,
int draw_mode,
const vec4* debug_color);
#endif

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

@ -16,6 +16,7 @@
#include "gui.h"
#include "config_vars.h"
#include "hashmap.h"
#include "geometry.h"
static int def_fbo = -1;
static int def_albedo_tex = -1;
@ -122,14 +123,14 @@ void renderer_init(void)
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();
for(int i = 0; i < array_len(camera_list); i++)
struct Entity* entity_list = entity_get_all();
for(int i = 0; i < array_len(entity_list); i++)
{
struct Camera* camera = &camera_list[i];
if(camera->node < 0)
continue;
struct Entity* viewer = &entity_list[i];
if(entity_list[i].type != ET_CAMERA) continue;
struct Camera* camera = &viewer->camera;
/* if(camera->fbo == -1) continue; */
int fbo = camera->fbo == -1 ? def_fbo : camera->fbo;
@ -145,7 +146,7 @@ void renderer_draw(void)
glEnable(GL_CULL_FACE );
glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model_render_all(camera, GDM_TRIANGLES);
model_render_all(viewer, GDM_TRIANGLES);
}
framebuffer_unbind();
glDisable(GL_DEPTH_TEST);
@ -176,7 +177,7 @@ void renderer_draw(void)
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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;
texture_bind(final_render_tex);
geom_render(quad_geo, GDM_TRIANGLES);
@ -186,7 +187,7 @@ void renderer_draw(void)
if(settings.debug_draw_enabled)
{
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);
}
@ -204,7 +205,17 @@ void renderer_cleanup(void)
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);
}

@ -2,7 +2,6 @@
#define renderer_H
#include "linmath.h"
#include "geometry.h"
enum Fog_Mode
{
@ -30,12 +29,14 @@ struct Render_Settings
int max_gui_element_memory;
int debug_draw_enabled;
vec4 debug_draw_color;
enum Geometry_Draw_Mode debug_draw_mode;
int debug_draw_mode;
};
struct Entity;
struct Render_Settings* renderer_settings_get(void);
void renderer_init(void);
void renderer_draw(void);
void renderer_draw(struct Entity* active_viewer);
void renderer_cleanup(void);
void renderer_clearcolor_set(float r, float g, float b, float a);
void renderer_debug_draw_enabled(int enabled);

@ -12,52 +12,50 @@ static int root_node = -1;
void scene_init(void)
{
/* Add root node to scene */
struct Entity* root = entity_create("ROOT", NULL);
root_node = root->node;
struct Entity* root = entity_create("ROOT", ET_ROOT, -1);
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;
new_entity = entity_create(name, tag);
struct Entity* parent = entity_get(parent_node);
new_entity->parent = parent->node;
array_push(parent->children, new_entity->node, int);
struct Transform* new_ent_tran = entity_component_get(new_entity, C_TRANSFORM);
transform_update_transmat(new_ent_tran);
new_entity = entity_create(name, type, parent_id);
struct Entity* parent = entity_get(parent_id);
new_entity->transform.parent = parent->id;
transform_update_transmat(&new_entity->transform);
return new_entity;
}
void scene_remove(struct Entity* 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);
}
entity_remove(entity->node);
entity_remove(entity->id);
}
void scene_reset_parent(struct Entity* entity, struct 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)
{
/* 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
as the entity's parent */
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;
break;
@ -66,11 +64,10 @@ void scene_reset_parent(struct Entity* entity, struct Entity* new_parent)
if(index > -1)
{
array_remove_at(curr_parent->children, index);
entity->parent = new_parent->node;
array_push(new_parent, entity->node, int);
struct Transform* entity_tran = entity_component_get(entity, C_TRANSFORM);
transform_update_transmat(entity_tran);
array_remove_at(curr_parent->transform.children, index);
entity->transform.parent = new_parent->id;
array_push(new_parent, entity->id, int);
transform_update_transmat(&entity->transform);
}
else
{
@ -88,9 +85,10 @@ void scene_cleanup(void)
struct Entity* entity_list = entity_get_all();
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_post_update();
}
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);
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)
{
child = curr_child;
@ -123,7 +121,7 @@ struct Entity* scene_get_parent(struct Entity* entity)
{
assert(entity);
struct Entity* parent = NULL;
if(entity->parent != -1)
parent = entity_get(entity->parent);
if(entity->transform.parent != -1)
parent = entity_get(entity->transform.parent);
return parent;
}

@ -1,5 +1,5 @@
#ifndef scene_H
#define scene_H
#ifndef SCENE_H
#define SCENE_H
struct Entity;
@ -7,8 +7,8 @@ void scene_init(void);
void scene_remove(struct Entity* entity);
void scene_reset_parent(struct Entity* entity, struct Entity* new_parent);
void scene_cleanup(void);
struct Entity* scene_add_new(const char* name, const char* tag); /* Add as child of Root */
struct Entity* scene_add_as_child(const char* name, const char* tag, int parent_node);
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 int type, int parent);
struct Entity* scene_find(const char* name);
struct Entity* scene_get_root(void);
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_Source* sound_sources_list = NULL;
static int* empty_indices = NULL;
int sound_init(void)
bool sound_init(void)
{
int success = 0;
sound_sources_list = array_new(struct Sound_Source);
empty_indices = array_new(int);
bool success = false;
sound_state.device = alcOpenDevice(NULL);
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(alListenerfv(AL_ORIENTATION, orientation))
success = 1;
success = true;
return success;
}
@ -71,12 +67,12 @@ void sound_listener_set(int listener_entity)
if(sound_state.listener_entity != -1)
{
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;
struct Entity* entity = entity_get(listener_entity);
entity->is_listener = 1;
entity->is_listener = true;
sound_listener_update();
}
@ -84,14 +80,13 @@ void sound_listener_update(void)
{
if(sound_state.listener_entity == -1) return;
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_up = {0.f, 1.f, 0.f};
vec3 abs_forward = {0.f, 0.f, -1.f};
transform_get_absolute_pos(transform, &abs_pos);
transform_get_absolute_up(transform, &abs_up);
transform_get_absolute_forward(transform, &abs_forward);
transform_get_absolute_pos(&entity->transform, &abs_pos);
transform_get_absolute_up(&entity->transform, &abs_up);
transform_get_absolute_forward(&entity->transform, &abs_forward);
float orientation[] =
{
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))
}
void sound_source_remove(int index)
void sound_source_destroy(struct Sound_Source* source)
{
assert(index > -1 && index < array_len(sound_sources_list));
struct Sound_Source* source = &sound_sources_list[index];
assert(source);
if(!source->active) return;
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))
}
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_source_handle = 0;
source->active = 0;
array_push(empty_indices, index, int);
source->active = false;
}
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);
alcDestroyContext(sound_state.context);
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;
struct Sound_Source* new_source = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_source = &sound_sources_list[index];
}
assert(source);
source->active = true;
al_check(alGenSources(1, &source->al_source_handle))
al_check(alGenBuffers(1, &source->al_buffer_handle))
sound_source_volume_set(source, 1.f);
if(transform)
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
sound_source_relative_set(new_source, 1);
return index;
sound_source_relative_set(source, 1);
}
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_up = {0.f, 1.f, 0.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))
}
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;
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;
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;
}
int mono = wav_spec.channels == 1 ? 1 : 0;
bool mono = wav_spec.channels == 1 ? true : false;
int format = -1;
if(mono)
{
@ -277,10 +245,12 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name)
else
{
/* 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;
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;
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)
@ -295,12 +265,6 @@ void sound_source_load_wav(struct Sound_Source* source, const char* file_name)
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_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)) }

@ -9,15 +9,10 @@
#define al_check(expr) expr;
#endif
struct Sound_Source
{
int entity;
uint al_source_handle;
uint al_buffer_handle;
int active;
};
struct Sound_Source;
struct Transform;
int sound_init(void);
bool sound_init(void);
void sound_cleanup(void);
void sound_volume_set(float volume);
void sound_error_check(const char* file, unsigned int line, const char* expression);
@ -26,15 +21,14 @@ void sound_listener_set(int entity);
int sound_listener_get(void);
void sound_listener_update(void);
struct Sound_Source* sound_source_get(int index);
int sound_source_create(int entity);
void sound_source_remove(int index);
void sound_source_update(struct Sound_Source* source);
void sound_source_create(struct Sound_Source* source, struct Transform* transform);
void sound_source_destroy(struct Sound_Source* source);
void sound_source_update(struct Sound_Source* source, struct Transform* transform);
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_load_wav(struct Sound_Source* source, const char* file_name);
void sound_source_loop_set(struct Sound_Source* source, int loop);
void sound_source_relative_set(struct Sound_Source* source, int relative);
void sound_source_loop_set(struct Sound_Source* source, bool loop);
void sound_source_relative_set(struct Sound_Source* source, bool relative);
void sound_source_play(struct Sound_Source* source);
void sound_source_pause(struct Sound_Source* source);
void sound_source_rewind(struct Sound_Source* source);

@ -380,7 +380,7 @@ int texture_create(const char* name,
int type,
const void* data)
{
assert(name && texture_unit > -1 && texture_unit <= TU_SHADOWMAP4);
assert(texture_unit > -1 && texture_unit <= TU_SHADOWMAP4);
int index = -1;
uint handle = 0;
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);
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->ref_count = 1;
new_tex->texture_unit = texture_unit;

@ -5,46 +5,16 @@
#include "utils.h"
#include <assert.h>
static struct Transform* transform_list;
static int* empty_indices;
void transform_init(void)
{
transform_list = array_new(struct Transform);
empty_indices = array_new(int);
}
void transform_cleanup(void)
void transform_create(struct Transform* transform, int parent_entity)
{
array_free(transform_list);
array_free(empty_indices);
}
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;
assert(transform);
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 = parent_entity;
transform->children = array_new(int);
transform_update_transmat(transform);
}
void transform_translate(struct Transform* transform, vec3* amount, enum Transform_Space space)
@ -57,13 +27,17 @@ void transform_translate(struct Transform* transform, vec3* amount, enum Transfo
}
else if(space == TS_PARENT)
{
struct Entity* parent = entity_get_parent(transform->node);
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM);
struct Entity* parent = entity_get_parent(transform->parent);
if(parent)
{
struct Transform* parent_tran = &parent->transform;
quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount);
}
}
vec3_add(&transform->position, &transform->position, &translation_amount);
transform_update_transmat(transform);
}
void transform_rotate(struct Transform* transform,
vec3* axis,
float angle,
@ -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, &scale);
struct Entity* entity = entity_get(transform->node);
if(entity) /* Only update if transform is attached to an entity */
{
struct Entity* parent = entity_get(entity->parent);
struct Entity* parent = entity_get(transform->parent);
if(parent)
{
struct Transform* parent_tran = entity_component_get(parent, C_TRANSFORM);
struct Transform* parent_tran = &parent->transform;
mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat);
}
/* Update all children */
int children = array_len(entity->children);
int children = array_len(transform->children);
if(children > 0)
{
for(int i = 0; i < children; i++)
{
struct Entity* child = entity_get(entity->children[i]);
struct Transform* child_tran = entity_component_get(child, C_TRANSFORM);
struct Entity* child = entity_get(transform->children[i]);
struct Transform* child_tran = &child->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));
return &transform_list[index];
}
assert(transform);
int children = array_len(transform->children);
if(children > 0)
{
for(int i = 0; i < children; i++)
{
struct Entity* child = entity_get(transform->children[i]);
child->marked_for_deletion = true;
}
}
void transform_remove(int index)
{
assert(index > -1 && index < array_len(transform_list));
transform_list[index].node = -1;
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)
@ -204,11 +184,10 @@ void transform_set_position(struct Transform* transform, vec3* new_position)
void transform_get_absolute_pos(struct Transform* transform, vec3* res)
{
struct Entity* entity = entity_get(transform->node);
struct Entity* parent = entity_get(entity->parent);
struct Entity* parent = entity_get(transform->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);
}
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)
{
struct Entity* entity = entity_get(transform->node);
struct Entity* parent = entity_get(entity->parent);
struct Entity* parent = entity_get(transform->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);
}
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)
{
struct Entity* entity = entity_get(transform->node);
struct Entity* parent = entity_get(entity->parent);
struct Entity* parent = entity_get(transform->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);
}
quat_mul(res, res, &transform->rotation);

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

Loading…
Cancel
Save