Phase 1 of Code Refactoring/Simplification complete. Moving towards fixed scene sizes and upfront allocation

dev
Shariq Shah 7 years ago
parent dae9c6d0ef
commit a28c5bbda7
  1. 20
      README.md
  2. 9
      src/game/sound.c
  3. 29
      src/libsymmetry/bounding_volumes.c
  4. 6
      src/libsymmetry/bounding_volumes.h
  5. 45
      src/libsymmetry/camera.c
  6. 14
      src/libsymmetry/camera.h
  7. 364
      src/libsymmetry/editor.c
  8. 1046
      src/libsymmetry/entity.c
  9. 82
      src/libsymmetry/entity.h
  10. 132
      src/libsymmetry/game.c
  11. 12
      src/libsymmetry/game.h
  12. 4
      src/libsymmetry/im_render.c
  13. 4
      src/libsymmetry/im_render.h
  14. 45
      src/libsymmetry/light.c
  15. 10
      src/libsymmetry/light.h
  16. 398
      src/libsymmetry/material.c
  17. 70
      src/libsymmetry/material.h
  18. 92
      src/libsymmetry/model.c
  19. 10
      src/libsymmetry/model.h
  20. 360
      src/libsymmetry/renderer.c
  21. 32
      src/libsymmetry/renderer.h
  22. 530
      src/libsymmetry/scene.c
  23. 82
      src/libsymmetry/scene.h
  24. 54
      src/libsymmetry/transform.c
  25. 2
      src/libsymmetry/transform.h

@ -155,7 +155,26 @@
- ## TODO - ## TODO
- Re-Implement player logic
- Re-Implement saving/loading scene to/from files
- Bring back functionality and complete overhaul
- Break-up entity into base and derived entities
- Move/Modify logic as necessary
- Scene should contain fixed size lists of entites according to their types for example, separate lists of Lights, Static_Meshes,
AI entities, Particles etc
- Entity post-update logic would move to scene as well, after update scene iterates through each specific list and does whatever
is necessary
- All this would enable us to hold valid poiniters to other entites, I suspect that would result in some other changes as well
- Make materials/uniforms simpler. No need for generic materials defined in text
- Possibly embed material into model somehow to make it easier to set material uniforms like colour etc
- Create new system inside game_state to handle non-spatial sounds for music/ui etc
- Setup scene such that player and editor camera are always added to every scene
- Try to remove as much unnecessary global state as possible for example move textures/shaders/framebuffers or create a resource
system and move textures/shaders/sounds/geometry etc to that and framebuffer/shaders to renderer
- Work on (yet another)entity refactor before moving on to serialization - Work on (yet another)entity refactor before moving on to serialization
- Implement cross-hatching shader
- Update README's TODO section to reflect the current state of things and the things that are actually left to do
- Implement collision/physics data serialization, read and write. - Implement collision/physics data serialization, read and write.
- Physics forces/torque etc - Physics forces/torque etc
- Implement physics debug visualizations for other primitives and tri mesh shapes - Implement physics debug visualizations for other primitives and tri mesh shapes
@ -373,3 +392,4 @@
* Implemented immediate mode renderer that can draw arbitrary points, lines and triangles * Implemented immediate mode renderer that can draw arbitrary points, lines and triangles
* Converted IM_Vertex array to only be used as temporary storage for vertices between begin and end calls * Converted IM_Vertex array to only be used as temporary storage for vertices between begin and end calls
* Implemented Debug physics mesh drawing for box and sphere primitives * Implemented Debug physics mesh drawing for box and sphere primitives
* Completed Phase 1 of codebase refactoring

@ -199,9 +199,6 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type)
struct Sound_Source_Buffer* source = NULL; struct Sound_Source_Buffer* source = NULL;
long size = 0L;
char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size);
//See if we've already loaded this file //See if we've already loaded this file
if(hashmap_value_exists(sound_sources, filename)) if(hashmap_value_exists(sound_sources, filename))
{ {
@ -209,6 +206,9 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type)
return source; return source;
} }
long size = 0L;
char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size);
source = malloc(sizeof(*source)); source = malloc(sizeof(*source));
if(!source) if(!source)
{ {
@ -245,10 +245,11 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type)
source->type = ST_WAV_STREAM; source->type = ST_WAV_STREAM;
} }
break; break;
default: log_error("sound:source_create", "Invalid source type %d", type); return 0; default: log_error("sound:source_create", "Invalid source type %d", type); break;
} }
hashmap_ptr_set(sound_sources, filename, (void*)source); hashmap_ptr_set(sound_sources, filename, (void*)source);
if(memory) free(memory);
return source; return source;
} }

@ -1,12 +1,9 @@
#include "bounding_volumes.h" #include "bounding_volumes.h"
#include "entity.h"
#include "transform.h"
#include <math.h> #include <math.h>
int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Entity* entity) int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale)
{ {
struct Transform* transform = &entity->transform;
vec3 min, max, size, center, half_ext, half_size; vec3 min, max, size, center, half_ext, half_size;
vec3_fill(&min, 0.f, 0.f, 0.f); vec3_fill(&min, 0.f, 0.f, 0.f);
vec3_fill(&max, 0.f, 0.f, 0.f); vec3_fill(&max, 0.f, 0.f, 0.f);
@ -15,10 +12,10 @@ int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Ent
vec3_fill(&half_ext, 0.f, 0.f, 0.f); vec3_fill(&half_ext, 0.f, 0.f, 0.f);
vec3_fill(&half_size, 0.f, 0.f, 0.f); vec3_fill(&half_size, 0.f, 0.f, 0.f);
vec3_add(&min, &box->min, &transform->position); vec3_add(&min, &box->min, box_abs_position);
vec3_mul(&min, &min, &transform->scale); vec3_mul(&min, &min, box_abs_scale);
vec3_add(&max, &box->max, &transform->position); vec3_add(&max, &box->max, box_abs_position);
vec3_mul(&min, &min, &transform->scale); vec3_mul(&min, &min, box_abs_scale);
vec3_sub(&size, &max, &min); vec3_sub(&size, &max, &min);
vec3_add(&center, &max, &min); vec3_add(&center, &max, &min);
vec3_scale(&center, &center, 0.5f); vec3_scale(&center, &center, 0.5f);
@ -37,22 +34,18 @@ int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Ent
return IT_INSIDE; return IT_INSIDE;
} }
int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Entity* entity) int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, vec3* sphere_abs_pos, vec3* sphere_abs_scale)
{ {
int intersect_type = IT_INSIDE; int intersect_type = IT_INSIDE;
vec3 center, abs_pos, abs_scale; vec3 center;
float radius = sphere->radius; float radius = sphere->radius;
vec3_fill(&center, 0.f, 0.f, 0.f); vec3_fill(&center, 0.f, 0.f, 0.f);
vec3_fill(&abs_pos, 0.f, 0.f, 0.f);
vec3_fill(&abs_scale, 0.f, 0.f, 0.f);
transform_get_absolute_position(entity, &abs_pos); float max_scale_dimension = fabsf(sphere_abs_scale->x);
transform_get_absolute_scale(entity, &abs_scale); if(fabsf(sphere_abs_scale->y) > max_scale_dimension) max_scale_dimension = fabsf(sphere_abs_scale->y);
float max_scale_dimension = fabsf(abs_scale.x); if(fabsf(sphere_abs_scale->z) > max_scale_dimension) max_scale_dimension = fabsf(sphere_abs_scale->z);
if(fabsf(abs_scale.y) > max_scale_dimension) max_scale_dimension = fabsf(abs_scale.y);
if(fabsf(abs_scale.z) > max_scale_dimension) max_scale_dimension = fabsf(abs_scale.z);
radius *= max_scale_dimension; radius *= max_scale_dimension;
vec3_add(&center, &sphere->center, &abs_pos); vec3_add(&center, &sphere->center, sphere_abs_pos);
//vec3_mul(&center, &center, &transform->scale); //vec3_mul(&center, &center, &transform->scale);
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)

@ -4,8 +4,6 @@
#include "../common/linmath.h" #include "../common/linmath.h"
#include "../common/num_types.h" #include "../common/num_types.h"
struct Entity;
struct Bounding_Box struct Bounding_Box
{ {
vec3 min; vec3 min;
@ -36,8 +34,8 @@ enum Frustum_Planes
FP_NUM_PLANES FP_NUM_PLANES
}; };
int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, struct Entity* entity); int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale);
int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Entity* entity); int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, struct Transform* transform);
bool bv_intersect_frustum_point(vec4* frustum, const vec3* point); bool bv_intersect_frustum_point(vec4* frustum, const vec3* point);
#endif #endif

@ -19,9 +19,8 @@
static void update_frustum(struct Camera* camera); static void update_frustum(struct Camera* camera);
void camera_destroy(struct Entity* entity) void camera_reset(struct Camera* camera)
{ {
struct Camera* camera = &entity->camera;
if(camera->fbo != -1) framebuffer_remove(camera->fbo); if(camera->fbo != -1) framebuffer_remove(camera->fbo);
if(camera->render_tex != -1) texture_remove(camera->render_tex); if(camera->render_tex != -1) texture_remove(camera->render_tex);
if(camera->depth_tex != -1) texture_remove(camera->depth_tex); if(camera->depth_tex != -1) texture_remove(camera->depth_tex);
@ -36,9 +35,8 @@ void camera_destroy(struct Entity* entity)
vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0); vec4_fill(&camera->clear_color, 0.f, 1.f, 0.f, 1.0);
} }
void camera_create(struct Entity* entity, int width, int height) void camera_init(struct Camera* camera, int width, int height)
{ {
struct Camera* camera = &entity->camera;
camera->fbo = -1; camera->fbo = -1;
camera->render_tex = -1; camera->render_tex = -1;
camera->depth_tex = -1; camera->depth_tex = -1;
@ -55,35 +53,32 @@ void camera_create(struct Entity* entity, int width, int height)
mat4_identity(&camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
for(int i = 0; i < FP_NUM_PLANES; i++) for(int i = 0; i < FP_NUM_PLANES; i++)
vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f); vec4_fill(&camera->frustum[i], 0.f, 0.f, 0.f, 0.f);
camera_update_view(entity); camera_update_view(camera);
camera_update_proj(entity); camera_update_proj(camera);
vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f); vec4_fill(&camera->clear_color, 1.f, 1.f, 1.f, 1.f);
} }
void camera_update_view_proj(struct Entity* entity) void camera_update_view_proj(struct Camera* camera)
{ {
struct Camera* camera = &entity->camera;
mat4_identity(&camera->view_proj_mat); mat4_identity(&camera->view_proj_mat);
mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat); mat4_mul(&camera->view_proj_mat, &camera->proj_mat, &camera->view_mat);
update_frustum(camera); update_frustum(camera);
} }
void camera_update_view(struct Entity* entity) void camera_update_view(struct Camera* camera)
{ {
struct Camera* camera = &entity->camera;
vec3 lookat = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f};
vec3 up = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f};
vec3 position = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(entity, &lookat); transform_get_absolute_lookat(&camera->base, &lookat);
transform_get_absolute_up(entity, &up); transform_get_absolute_up(&camera->base, &up);
transform_get_absolute_position(entity, &position); transform_get_absolute_position(&camera->base, &position);
mat4_lookat(&camera->view_mat, &position, &lookat, &up); mat4_lookat(&camera->view_mat, &position, &lookat, &up);
camera_update_view_proj(entity); camera_update_view_proj(&camera->base);
} }
void camera_update_proj(struct Entity* entity) void camera_update_proj(struct Camera* camera)
{ {
struct Camera* camera = &entity->camera;
if(!camera->ortho) if(!camera->ortho)
{ {
mat4_perspective(&camera->proj_mat, mat4_perspective(&camera->proj_mat,
@ -105,10 +100,10 @@ void camera_update_proj(struct Entity* entity)
camera->nearz, camera->nearz,
camera->farz); camera->farz);
} }
camera_update_view_proj(entity); camera_update_view_proj(camera);
} }
void camera_attach_fbo(struct Entity* entity, void camera_attach_fbo(struct Camera* camera,
int width, int width,
int height, int height,
bool has_depth, bool has_depth,
@ -116,7 +111,6 @@ void camera_attach_fbo(struct Entity* entity,
bool resizeable) bool resizeable)
{ {
assert(width > 0 && height > 0); assert(width > 0 && height > 0);
struct Camera* camera = &entity->camera;
if(camera->fbo != -1) if(camera->fbo != -1)
{ {
log_error("camera:attach_fbo", "Camera already has fbo attached!"); log_error("camera:attach_fbo", "Camera already has fbo attached!");
@ -207,16 +201,3 @@ static void update_frustum(struct Camera* camera)
vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length)); vec4_scale(&camera->frustum[i], &camera->frustum[i], (1.f / length));
} }
} }
/* 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); */
/* } */
/* } */

@ -3,14 +3,14 @@
#include "../common/num_types.h" #include "../common/num_types.h"
struct Entity; struct Camera;
void camera_destroy(struct Entity* entity); void camera_reset(struct Camera* camera);
void camera_create(struct Entity* entity, int width, int height); void camera_init(struct Camera* camera, int width, int height);
void camera_update_view_proj(struct Entity* entity); void camera_update_view_proj(struct Camera* camera);
void camera_update_view(struct Entity* entity); void camera_update_view(struct Camera* camera);
void camera_update_proj(struct Entity* entity); void camera_update_proj(struct Camera* camera);
void camera_attach_fbo(struct Entity* entity, void camera_attach_fbo(struct Camera* camera,
int width, int width,
int height, int height,
bool has_depth, bool has_depth,

@ -201,7 +201,7 @@ void editor_update(float dt)
/* Entities List */ /* Entities List */
if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED)) if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED))
{ {
nk_layout_row_dynamic(context, 250, 1); /*nk_layout_row_dynamic(context, 250, 1);
if(nk_group_begin(context, "Entity Name", NK_WINDOW_SCROLL_AUTO_HIDE)) if(nk_group_begin(context, "Entity Name", NK_WINDOW_SCROLL_AUTO_HIDE))
{ {
struct Entity* entity_list = entity_get_all(); struct Entity* entity_list = entity_get_all();
@ -228,7 +228,7 @@ void editor_update(float dt)
} }
} }
nk_group_end(context); nk_group_end(context);
} }*/
nk_tree_pop(context); nk_tree_pop(context);
} }
@ -264,186 +264,186 @@ void editor_update(float dt)
if(nk_group_begin(context, "Editor Right", NK_WINDOW_NO_SCROLLBAR)) if(nk_group_begin(context, "Editor Right", NK_WINDOW_NO_SCROLLBAR))
{ {
/* Entity Inspector */ /* Entity Inspector */
if(nk_tree_push(context, NK_TREE_TAB, "Inspector", NK_MAXIMIZED)) //if(nk_tree_push(context, NK_TREE_TAB, "Inspector", NK_MAXIMIZED))
{ //{
const int row_height = 18; // const int row_height = 18;
if(editor_state.selected_entity_id != -1) // if(editor_state.selected_entity_id != -1)
{ // {
struct Entity* entity = entity_get(editor_state.selected_entity_id); // struct Entity* entity = entity_get(editor_state.selected_entity_id);
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT); // nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT);
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id); // nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id);
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity)); // nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity));
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
struct Entity* parent_ent = entity_get(entity->transform.parent); // struct Entity* parent_ent = entity_get(entity->transform.parent);
nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT); // nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT);
/* Transform */ // /* Transform */
{ // {
nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED); // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED);
vec3 abs_pos = {0.f, 0.f, 0.f}; // vec3 abs_pos = {0.f, 0.f, 0.f};
transform_get_absolute_position(entity, &abs_pos); // transform_get_absolute_position(entity, &abs_pos);
if(editor_widget_v3(context, &abs_pos, "Px", "Py", "Pz", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos); // if(editor_widget_v3(context, &abs_pos, "Px", "Py", "Pz", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos);
nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED); // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED);
quat abs_rot = {0.f, 0.f, 0.f, 1.f}; // quat abs_rot = {0.f, 0.f, 0.f, 1.f};
transform_get_absolute_rot(entity, &abs_rot); // transform_get_absolute_rot(entity, &abs_rot);
vec3 rot_angles = {0.f, 0.f, 0.f}; // vec3 rot_angles = {0.f, 0.f, 0.f};
rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot)); // rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot));
rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot)); // rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot));
rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot)); // rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot));
vec3 curr_rot = {rot_angles.x, rot_angles.y, rot_angles.z}; // vec3 curr_rot = {rot_angles.x, rot_angles.y, rot_angles.z};
nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rx", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f); // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rx", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f);
nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Ry", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f); // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Ry", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f);
nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rz", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f); // nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "Rz", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f);
vec3 delta = {0.f, 0.f, 0.f}; // vec3 delta = {0.f, 0.f, 0.f};
vec3_sub(&delta, &rot_angles, &curr_rot); // vec3_sub(&delta, &rot_angles, &curr_rot);
vec3 AXIS_X = {1.f, 0.f, 0.f}; // vec3 AXIS_X = {1.f, 0.f, 0.f};
vec3 AXIS_Y = {0.f, 1.f, 0.f}; // vec3 AXIS_Y = {0.f, 1.f, 0.f};
vec3 AXIS_Z = {0.f, 0.f, 1.f}; // vec3 AXIS_Z = {0.f, 0.f, 1.f};
const float epsilon = 0.0001f; // const float epsilon = 0.0001f;
if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD); // if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD);
if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD); // if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD);
if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD); // if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD);
nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED); // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED);
vec3 abs_scale = {0.f, 0.f, 0.f}; // vec3 abs_scale = {0.f, 0.f, 0.f};
transform_get_absolute_scale(entity, &abs_scale); // transform_get_absolute_scale(entity, &abs_scale);
if(editor_widget_v3(context, &abs_scale, "SX", "SY", "SZ", 0.1f, FLT_MAX, 1.f, 0.1f, row_height)) // if(editor_widget_v3(context, &abs_scale, "SX", "SY", "SZ", 0.1f, FLT_MAX, 1.f, 0.1f, row_height))
{ // {
entity->transform.scale = abs_scale; // entity->transform.scale = abs_scale;
transform_update_transmat(entity); // transform_update_transmat(entity);
} // }
} // }
/* Light */ // /* Light */
if(entity->type == ET_LIGHT) // if(entity->type == ET_LIGHT)
{ // {
if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED)) // if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED))
{ // {
struct Light* light = &entity->light; // struct Light* light = &entity->light;
if(light->type > LT_POINT) // if(light->type > LT_POINT)
{ // {
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED); // nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED);
} // }
else // else
{ // {
static const char* light_types[] = {"Spot", "Directional", "Point"}; // static const char* light_types[] = {"Spot", "Directional", "Point"};
float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX); // float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX);
//
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT); // nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT);
nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height)); // nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height));
//
nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED); // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED);
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
editor_widget_color_combov3(context, &light->color, 200, 300); // editor_widget_color_combov3(context, &light->color, 200, 300);
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f); // nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f);
if(light->type != LT_DIR) // if(light->type != LT_DIR)
{ // {
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f)); // light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f));
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f)); // light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f));
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1); // nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1);
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f); // nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f);
} // }
} // }
nk_tree_pop(context); // nk_tree_pop(context);
} // }
} // }
/* Camera */ // /* Camera */
if(entity->type == ET_CAMERA) // if(entity->type == ET_CAMERA)
{ // {
if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) // if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED))
{ // {
bool update = false; // bool update = false;
struct Camera* camera = &entity->camera; // struct Camera* camera = &entity->camera;
//
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); // nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE);
bool ortho = nk_checkbox_label(context, "", &camera->ortho); // bool ortho = nk_checkbox_label(context, "", &camera->ortho);
if(ortho != camera->ortho) // if(ortho != camera->ortho)
{ // {
update = true; // update = true;
} // }
//
if(!camera->ortho) // if(!camera->ortho)
{ // {
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); // float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f);
if(new_fov != camera->fov) // if(new_fov != camera->fov)
{ // {
camera->fov = new_fov; // camera->fov = new_fov;
update = true; // update = true;
} // }
nk_layout_row_dynamic(context, row_height, 2); // nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); // nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio);
} // }
nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); // nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED);
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
editor_widget_color_combov4(context, &camera->clear_color, 200, 300); // editor_widget_color_combov4(context, &camera->clear_color, 200, 300);
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f); // float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f);
if(new_zoom != camera->zoom) // if(new_zoom != camera->zoom)
{ // {
camera->zoom = new_zoom; // camera->zoom = new_zoom;
update = true; // update = true;
} // }
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); // float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f);
if(new_near_z != camera->nearz) // if(new_near_z != camera->nearz)
{ // {
camera->nearz = new_near_z; // camera->nearz = new_near_z;
update = true; // update = true;
} // }
//
nk_layout_row_dynamic(context, row_height, 1); // nk_layout_row_dynamic(context, row_height, 1);
float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); // float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f);
if(new_far_z != camera->farz) // if(new_far_z != camera->farz)
{ // {
camera->farz = new_far_z; // camera->farz = new_far_z;
update = true; // update = true;
} // }
if(update) // if(update)
{ // {
camera_update_view(entity); // camera_update_view(entity);
camera_update_proj(entity); // camera_update_proj(entity);
} // }
nk_tree_pop(context); // nk_tree_pop(context);
} // }
} // }
} // }
else // else
{ // {
nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED); // nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED);
} // }
nk_tree_pop(context); // nk_tree_pop(context);
} //}
//
nk_group_end(context); nk_group_end(context);
} }
} }

File diff suppressed because it is too large Load Diff

@ -4,10 +4,13 @@
#include "../common/linmath.h" #include "../common/linmath.h"
#include "../common/num_types.h" #include "../common/num_types.h"
#include "../common/common.h" #include "../common/common.h"
#include "material.h"
#define MAX_ENTITY_NAME_LEN 128 #define MAX_ENTITY_NAME_LEN 128
#define MAX_SOUND_SOURCE_BUFFERS 5 #define MAX_SOUND_SOURCE_BUFFERS 5
struct Entity;
struct Material_Param; struct Material_Param;
struct Parser_Object; struct Parser_Object;
@ -16,11 +19,12 @@ typedef void (*Collision_CB)(struct Entity* this_entity, struct Entity* other_en
enum Entity_Type enum Entity_Type
{ {
ET_NONE, ET_NONE,
ET_DEFAULT,
ET_PLAYER, ET_PLAYER,
ET_ROOT, ET_ROOT,
ET_CAMERA, ET_CAMERA,
ET_LIGHT, ET_LIGHT,
ET_STATIC_MESH, ET_STATIC_MODEL,
ET_SOUND_SOURCE, ET_SOUND_SOURCE,
ET_MAX ET_MAX
}; };
@ -34,42 +38,61 @@ enum LightType
LT_MAX LT_MAX
}; };
enum Camera_Type
{
CT_EDITOR = 0,
CT_GAME,
CT_MAX
};
struct Transform struct Transform
{ {
vec3 position; vec3 position;
vec3 scale; vec3 scale;
quat rotation; quat rotation;
mat4 trans_mat; mat4 trans_mat;
int parent;
int* children;
bool is_modified; bool is_modified;
bool sync_physics; bool sync_physics;
struct Entity* parent;
struct Entity** children;
};
struct Entity
{
int id;
int type;
char name[MAX_ENTITY_NAME_LEN];
bool marked_for_deletion;
bool active;
bool editor_selected;
struct Transform transform;
}; };
struct Model struct Model
{ {
int geometry_index; int geometry_index;
int material; struct Material* material;
struct Material_Param* material_params; struct Variant material_params[MMP_MAX];
}; };
struct Sound_Source struct Sound_Source
{ {
struct Entity base;
int type; int type;
bool playing; bool playing;
bool loop; bool loop;
char* source_filename;
uint source_instance; uint source_instance;
float min_distance; float min_distance;
float max_distance; float max_distance;
float rolloff_factor; float rolloff_factor;
float volume; float volume;
int attenuation_type; int attenuation_type;
struct Sound_Source_Buffer* source; struct Sound_Source_Buffer* source_buffer; // Handle to the file from which the sound is loaded and played
}; };
struct Camera struct Camera
{ {
struct Entity base;
mat4 proj_mat; mat4 proj_mat;
mat4 view_mat; mat4 view_mat;
mat4 view_proj_mat; mat4 view_proj_mat;
@ -89,6 +112,7 @@ struct Camera
struct Light struct Light
{ {
struct Entity base;
float outer_angle; float outer_angle;
float inner_angle; float inner_angle;
float falloff; float falloff;
@ -110,52 +134,28 @@ struct Collision
Collision_CB on_collision; Collision_CB on_collision;
}; };
struct Entity struct Static_Mesh
{ {
int id; struct Entity base;
int type; struct Model model;
char name[MAX_ENTITY_NAME_LEN];
bool is_listener; /* TODO: Replace all booleans with flags */
bool marked_for_deletion;
bool renderable;
bool has_collision;
int editor_selected;
struct Transform transform;
struct Collision collision; struct Collision collision;
};
union struct Player
{
struct
{ {
struct Model model; struct Entity base;
int health;
} Player;
struct Model model;
struct Camera camera;
struct Light light;
struct Sound_Source sound_source;
};
}; };
void entity_init(void); void entity_init(struct Entity* entity, const char* name, struct Entity* parent);
void entity_cleanup(void); void entity_reset(struct Entity* entity, int id);
void entity_remove(int index);
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);
bool entity_save(struct Entity* entity, const char* filename, int directory_type); bool entity_save(struct Entity* entity, const char* filename, int directory_type);
bool entity_load(const char* filename, int directory_type); bool entity_load(const char* filename, int directory_type);
bool entity_write(struct Entity* entity, struct Parser_Object* object); bool entity_write(struct Entity* entity, struct Parser_Object* object);
struct Entity* entity_read(struct Parser_Object* object); struct Entity* entity_read(struct Parser_Object* object);
const char* entity_type_name_get(struct Entity* entity); const char* entity_type_name_get(struct Entity* entity);
void entity_apply_sound_params(struct Entity* entity); // Convenience function to sync the data set in entity's sound_source with the actual sound source's instance
void entity_rigidbody_on_move(Rigidbody body); void entity_rigidbody_on_move(Rigidbody body);
void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B); void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B);
void entity_rigidbody_set(struct Entity* entity, Rigidbody body); void entity_rigidbody_set(struct Entity* entity, struct Collision* collision, Rigidbody body);
void entity_collision_shape_set(struct Entity* entity, Collision_Shape shape); // Only used for collision shapes like plane which can't have a rigidbody attached to collision shape void entity_collision_shape_set(struct Entity* entity, struct Collision* collision, Collision_Shape shape); // Only used for collision shapes like plane which can't have a rigidbody attached to collision shape
#endif #endif

@ -76,13 +76,12 @@ bool game_init(struct Window* window, struct Platform_Api* platform_api)
else else
{ {
game_state->window = window; game_state->window = window;
game_state->player_node = -1; game_state->player_node = NULL;
game_state->player_pitch_node = -1; game_state->player_pitch_node = NULL;
game_state->is_initialized = false; game_state->is_initialized = false;
} game_state->renderer = malloc(sizeof(*game_state->renderer));
game_state->scene = malloc(sizeof(*game_state->scene));
/* TODO: Decouple systems' init/cleanup from game, they should exist and run even if there's no "game" */
/* Init systems */
log_file_handle_set(platform->log.file_handle_get()); log_file_handle_set(platform->log.file_handle_get());
if(!gl_load_extentions()) if(!gl_load_extentions())
{ {
@ -93,21 +92,22 @@ bool game_init(struct Window* window, struct Platform_Api* platform_api)
{ {
log_message("Loaded GL extentions"); log_message("Loaded GL extentions");
} }
input_init(); input_init();
shader_init(); shader_init();
texture_init(); texture_init();
framebuffer_init(); framebuffer_init();
geom_init(); geom_init();
editor_init(); editor_init();
renderer_init();
light_init();
material_init();
entity_init();
platform->physics.init(); platform->physics.init();
platform->physics.gravity_set(0.f, -9.8f, 0.f); platform->physics.gravity_set(0.f, -9.8f, 0.f);
platform->physics.body_set_moved_callback(entity_rigidbody_on_move); platform->physics.body_set_moved_callback(entity_rigidbody_on_move);
platform->physics.body_set_collision_callback(entity_rigidbody_on_collision); platform->physics.body_set_collision_callback(entity_rigidbody_on_collision);
scene_init();
scene_init(game_state->scene);
renderer_init(game_state->renderer);
}
/* Debug scene setup */ /* Debug scene setup */
scene_setup(); scene_setup();
@ -239,49 +239,48 @@ void scene_setup(void)
// scene_save("test_scene.symtres", DIRT_INSTALL); // scene_save("test_scene.symtres", DIRT_INSTALL);
if(scene_load("test_scene.symtres", DIRT_INSTALL)) // if(scene_load("test_scene.symtres", DIRT_INSTALL))
{ // {
log_message("Scene loaded!"); // log_message("Scene loaded!");
struct Entity* player = entity_find("player"); // struct Entity* player = entity_find("player");
game_state->player_node = player->id; // game_state->player_node = player->id;
struct Entity* suz = entity_find("Model_Entity"); //struct Entity* suz = entity_find("Model_Entity");
suz_id = suz->id; //suz_id = suz->id;
/*struct Camera* camera = &player->camera; // /*struct Camera* camera = &player->camera;
camera->ortho = true; // camera->ortho = true;
camera->farz = 500.f; // camera->farz = 500.f;
camera->nearz = -500.f; // camera->nearz = -500.f;
camera_update_proj(player);*/ // camera_update_proj(player);*/
} // }
platform->physics.cs_plane_create(0, 1, 0, 0); //platform->physics.cs_plane_create(0, 1, 0, 0);
//Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5); ////Rigidbody box = platform->physics.body_box_create(2.5, 2.5, 2.5);
Rigidbody box = platform->physics.body_sphere_create(3.5); //Rigidbody box = platform->physics.body_sphere_create(3.5);
/*platform->physics.body_position_set(box, 0.f, 50.f, 0.f); ///*platform->physics.body_position_set(box, 0.f, 50.f, 0.f);
platform->physics.body_mass_set(box, 10.f);*/ //platform->physics.body_mass_set(box, 10.f);*/
/*platform->physics.body_data_set(box, (void*)suz_id);*/ ///*platform->physics.body_data_set(box, (void*)suz_id);*/
//platform->physics.body_force_add(box, -100.f, 0.f, 0.f); ////platform->physics.body_force_add(box, -100.f, 0.f, 0.f);
struct Entity* suz = entity_find("Model_Entity"); //struct Entity* suz = entity_find("Model_Entity");
entity_rigidbody_set(suz, box); //entity_rigidbody_set(suz, box);
suz->collision.on_collision = &on_collision_test; //suz->collision.on_collision = &on_collision_test;
Rigidbody sphere = platform->physics.body_sphere_create(3.5f); //Rigidbody sphere = platform->physics.body_sphere_create(3.5f);
struct Entity* sphere_ent = entity_find("Sphere_Ent"); //struct Entity* sphere_ent = entity_find("Sphere_Ent");
entity_rigidbody_set(sphere_ent, sphere); //entity_rigidbody_set(sphere_ent, sphere);
//Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0); ////Collision_Shape plane = platform->physics.cs_plane_create(0, 1, 0, 0);
Rigidbody ground_box = platform->physics.body_box_create(10, 5, 10); //Rigidbody ground_box = platform->physics.body_box_create(10, 5, 10);
platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f); //platform->physics.body_position_set(ground_box, 0.f, 0.f, 0.f);
/*platform->physics.body_kinematic_set(ground_box);*/ ///*platform->physics.body_kinematic_set(ground_box);*/
struct Entity* ground = entity_find("Ground"); //struct Entity* ground = entity_find("Ground");
//entity_collision_shape_set(ground, plane); ////entity_collision_shape_set(ground, plane);
entity_rigidbody_set(ground, ground_box); //entity_rigidbody_set(ground, ground_box);
} }
void debug(float dt) void debug(float dt)
{ {
//struct Entity* entity = entity_get(player_node); //struct Entity* entity = entity_get(player_node);
struct Entity* player_entity = entity_get(game_state->player_node);
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;
@ -334,25 +333,25 @@ void debug(float dt)
if(turn_left_right != 0.f) if(turn_left_right != 0.f)
{ {
transform_rotate(player_entity, &rot_axis_left_right, -turn_left_right, TS_WORLD); /*transform_rotate(player_entity, &rot_axis_left_right, -turn_left_right, TS_WORLD);
vec3 up = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f};
vec3 forward = {0.f, 0.f, 0.f}; vec3 forward = {0.f, 0.f, 0.f};
vec3 lookat = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f};
transform_get_up(player_entity, &up); transform_get_up(player_entity, &up);
transform_get_forward(player_entity, &forward); transform_get_forward(player_entity, &forward);
transform_get_lookat(player_entity, &lookat); transform_get_lookat(player_entity, &lookat);*/
/* log_message("Up : %s", tostr_vec3(&up)); */ /* log_message("Up : %s", tostr_vec3(&up)); */
/* log_message("FR : %s", tostr_vec3(&forward)); */ /* log_message("FR : %s", tostr_vec3(&forward)); */
} }
if(turn_up_down != 0.f) if(turn_up_down != 0.f)
{ {
transform_rotate(player_entity, &rot_axis_up_down, turn_up_down, TS_LOCAL); /*transform_rotate(player_entity, &rot_axis_up_down, turn_up_down, TS_LOCAL);
vec3 up = {0.f, 0.f, 0.f}; vec3 up = {0.f, 0.f, 0.f};
vec3 forward = {0.f, 0.f, 0.f}; vec3 forward = {0.f, 0.f, 0.f};
vec3 lookat = {0.f, 0.f, 0.f}; vec3 lookat = {0.f, 0.f, 0.f};
transform_get_up(player_entity, &up); transform_get_up(player_entity, &up);
transform_get_forward(player_entity, &forward); transform_get_forward(player_entity, &forward);
transform_get_lookat(player_entity, &lookat); transform_get_lookat(player_entity, &lookat);*/
/* log_message("Up : %s", tostr_vec3(&up)); */ /* log_message("Up : %s", tostr_vec3(&up)); */
/* log_message("FR : %s", tostr_vec3(&forward)); */ /* log_message("FR : %s", tostr_vec3(&forward)); */
} }
@ -369,20 +368,20 @@ void debug(float dt)
vec3_scale(&offset, &offset, dt); vec3_scale(&offset, &offset, dt);
if(offset.x != 0 || offset.y != 0 || offset.z != 0) if(offset.x != 0 || offset.y != 0 || offset.z != 0)
{ {
transform_translate(player_entity, &offset, TS_LOCAL); //transform_translate(player_entity, &offset, TS_LOCAL);
//log_message("Position : %s", tostr_vec3(&transform->position)); //log_message("Position : %s", tostr_vec3(&transform->position));
} }
if(input_is_key_pressed(KEY_SPACE)) if(input_is_key_pressed(KEY_SPACE))
{ {
struct Entity* model = scene_find("Light_Ent"); struct Entity* model = scene_find(game_state->scene, "Light_Ent");
vec3 x_axis = {0, 1, 0}; vec3 x_axis = {0, 1, 0};
transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD);
} }
if(input_is_key_pressed(KEY_M)) if(input_is_key_pressed(KEY_M))
{ {
struct Entity* model = scene_find("Model_Entity"); struct Entity* model = scene_find(game_state->scene, "Model_Entity");
//vec3 y_axis = {0, 0, 1}; //vec3 y_axis = {0, 0, 1};
//transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL); //transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_LOCAL);
vec3 amount = {0, 0, -5 * dt}; vec3 amount = {0, 0, -5 * dt};
@ -391,7 +390,7 @@ void debug(float dt)
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(game_state->scene, "Model_Entity");
/* vec3 y_axis = {0, 0, 1}; */ /* vec3 y_axis = {0, 0, 1}; */
/* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */ /* transform_rotate(mod_tran, &y_axis, 25.f * dt, TS_WORLD); */
vec3 amount = {0, 0, 5 * dt}; vec3 amount = {0, 0, 5 * dt};
@ -404,7 +403,7 @@ void debug(float dt)
vec3 amount = {0, 0, -5 * dt}; vec3 amount = {0, 0, -5 * dt};
transform_translate(model, &amount, TS_LOCAL);*/ transform_translate(model, &amount, TS_LOCAL);*/
struct Sprite_Batch* batch = get_batch(); struct Sprite_Batch* batch = game_state->renderer->sprite_batch;
sprite_batch_begin(batch); sprite_batch_begin(batch);
static struct Sprite sprite; static struct Sprite sprite;
@ -437,7 +436,7 @@ void debug(float dt)
//Raycast test //Raycast test
if(input_is_key_pressed(KEY_R)) if(input_is_key_pressed(KEY_R))
{ {
Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true); /*Collision_Shape ray = platform->physics.cs_ray_create(20.f, true, true);
vec3 position = {0.f, 0.f, 0.f}; vec3 position = {0.f, 0.f, 0.f};
vec3 direction = {0.f, 0.f, 0.f}; vec3 direction = {0.f, 0.f, 0.f};
transform_get_absolute_forward(player_entity, &direction); transform_get_absolute_forward(player_entity, &direction);
@ -452,7 +451,7 @@ void debug(float dt)
{ {
log_message("Ray didn't hit anything!"); log_message("Ray didn't hit anything!");
} }
platform->physics.cs_remove(ray); platform->physics.cs_remove(ray);*/
} }
// Immediate geometry test // Immediate geometry test
@ -556,7 +555,7 @@ bool run(void)
platform->physics.step(delta_time); platform->physics.step(delta_time);
render(); render();
platform->window.swap_buffers(game_state->window); platform->window.swap_buffers(game_state->window);
entity_post_update(); scene_post_update(game_state->scene);
platform->sound.update_3d(); platform->sound.update_3d();
} }
return true; return true;
@ -1788,8 +1787,7 @@ void debug_gui(float dt)
void render(void) void render(void)
{ {
struct Entity* viewer = entity_get(game_state->player_node); renderer_draw(game_state->renderer, game_state->scene);
renderer_draw(viewer);
} }
void game_cleanup(void) void game_cleanup(void)
@ -1799,16 +1797,16 @@ void game_cleanup(void)
if(game_state->is_initialized) if(game_state->is_initialized)
{ {
editor_cleanup(); editor_cleanup();
scene_cleanup(); scene_destroy(game_state->scene);
entity_cleanup();
material_cleanup();
light_cleanup();
input_cleanup(); input_cleanup();
renderer_cleanup(); renderer_cleanup(game_state->renderer);
geom_cleanup(); geom_cleanup();
framebuffer_cleanup(); framebuffer_cleanup();
texture_cleanup(); texture_cleanup();
shader_cleanup(); shader_cleanup();
free(game_state->scene);
free(game_state->renderer);
} }
free(game_state); free(game_state);
game_state = NULL; game_state = NULL;

@ -11,13 +11,19 @@
struct Window; struct Window;
struct Platform_Api; struct Platform_Api;
struct Renderer;
struct Scene;
struct Entity;
struct Player;
struct Game_State struct Game_State
{ {
struct Window* window;
int player_node;
int player_pitch_node;
bool is_initialized; bool is_initialized;
struct Window* window;
struct Player* player_node;
struct Entity* player_pitch_node;
struct Renderer* renderer;
struct Scene* scene;
}; };

@ -155,7 +155,7 @@ void im_end(void)
memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES); memset(&IM_State.vertices[0], 0, sizeof(struct IM_Vertex) * MAX_IM_VERTICES);
} }
void im_render(struct Entity* active_viewer) void im_render(struct Camera* active_viewer)
{ {
if(IM_State.curr_geom == -1) if(IM_State.curr_geom == -1)
return; return;
@ -182,7 +182,7 @@ void im_render(struct Entity* active_viewer)
mat4_mul(&mvp, &mvp, &rotation); mat4_mul(&mvp, &mvp, &rotation);
mat4_mul(&mvp, &mvp, &scale); mat4_mul(&mvp, &mvp, &scale);
mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &mvp); mat4_mul(&mvp, &active_viewer->view_proj_mat, &mvp);
shader_set_uniform_mat4(IM_State.im_shader, "mvp", &mvp); shader_set_uniform_mat4(IM_State.im_shader, "mvp", &mvp);
shader_set_uniform_vec4(IM_State.im_shader, "geom_color", &geom->color); shader_set_uniform_vec4(IM_State.im_shader, "geom_color", &geom->color);

@ -34,7 +34,7 @@ struct IM_Geom
int draw_mode; int draw_mode;
}; };
struct Entity; struct Camera;
void im_init(void); void im_init(void);
void im_cleanup(void); void im_cleanup(void);
@ -43,6 +43,6 @@ void im_pos(float x, float y, float z);
void im_box(float x, float y, float z, vec3 position, quat rotation, vec4 color, int draw_mode); void im_box(float x, float y, float z, vec3 position, quat rotation, vec4 color, int draw_mode);
void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode); void im_sphere(float radius, vec3 position, quat rotation, vec4 color, int draw_mode);
void im_end(void); void im_end(void);
void im_render(struct Entity* active_viewer); void im_render(struct Camera* active_viewer);
#endif #endif

@ -4,23 +4,8 @@
#include <assert.h> #include <assert.h>
static int* light_list = NULL; void light_init(struct Light* light, int light_type)
void light_init(void)
{ {
light_list = array_new(int);
}
void light_cleanup(void)
{
array_free(light_list);
light_list = NULL;
}
void light_create(struct Entity* entity, int light_type)
{
struct Light* light = &entity->light;
light->valid = true; light->valid = true;
light->cast_shadow = 0; light->cast_shadow = 0;
light->depth_bias = 0.0005f; light->depth_bias = 0.0005f;
@ -32,30 +17,10 @@ void light_create(struct Entity* entity, int light_type)
light->inner_angle = TO_RADIANS(20.f); light->inner_angle = TO_RADIANS(20.f);
light->radius = 20; light->radius = 20;
vec3_fill(&light->color, 1.f, 1.f, 1.f); vec3_fill(&light->color, 1.f, 1.f, 1.f);
light_add(entity);
}
void light_add(struct Entity* entity)
{
assert(entity->type == ET_LIGHT);
int* new_index = array_grow(light_list, int);
*new_index = entity->id;
} }
void light_destroy(struct Entity* entity) void light_reset(struct Light* light)
{
assert(entity && entity->type == ET_LIGHT);
struct Light* light = &entity->light;
int index_to_remove = -1;
for(int i = 0; i < array_len(light_list); i++)
{ {
if(light_list[i] == entity->id)
{
index_to_remove = i;
break;
}
}
if(index_to_remove != -1) array_remove_at(light_list, index_to_remove);
light->valid = false; light->valid = false;
light->cast_shadow = 0; light->cast_shadow = 0;
light->depth_bias = 0.f; light->depth_bias = 0.f;
@ -68,9 +33,3 @@ void light_destroy(struct Entity* entity)
light->radius = 0.f; light->radius = 0.f;
vec3_fill(&light->color, 1.f, 0.f, 1.f); vec3_fill(&light->color, 1.f, 0.f, 1.f);
} }
int* light_get_valid_indices(int* out_count)
{
*out_count = array_len(light_list);
return light_list;
}

@ -3,13 +3,7 @@
#define MAX_SHADOWMAPS 4 #define MAX_SHADOWMAPS 4
struct Entity; void light_init(struct Light* light);
void light_reset(struct Light* light);
void light_init(void);
void light_cleanup(void);
void light_destroy(struct Entity* entity);
void light_create(struct Entity* entity, int light_type);
void light_add(struct Entity* entity);
int* light_get_valid_indices(int* out_count);
#endif #endif

@ -12,312 +12,156 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
static struct Material* material_list; bool material_init(struct Material* material, int material_type)
static int* empty_indices; {
assert(material && material_type > -1 && material_type < MAT_MAX);
material->type = material_type;
memset(material->registered_models, 0, sizeof(struct Model*) * MAX_MATERIAL_REGISTERED_MODELS);
memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX);
memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX);
void material_init(void) switch(material_type)
{ {
material_list = array_new(struct Material); case MAT_BLINN:
empty_indices = array_new(int); {
material->lit = true;
/* TODO: implement reading material definitions from files */ material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag");
/* Simple unshaded material */
struct Material* unshaded_mat = array_grow(material_list, struct Material); material->pipeline_params[MPP_INV_MODEL_MAT].type = UT_MAT4;
unshaded_mat->name = str_new("Unshaded"); material->pipeline_params[MPP_INV_MODEL_MAT].location = shader_get_uniform_location(material->shader, "inv_model_mat");
unshaded_mat->shader = shader_create("unshaded.vert", "unshaded.frag");
unshaded_mat->registered_models = array_new(int); material->pipeline_params[MPP_VIEW_MAT].type = UT_MAT4;
unshaded_mat->model_params = array_new(struct Uniform); material->pipeline_params[MPP_VIEW_MAT].location = shader_get_uniform_location(material->shader, "view_mat");
unshaded_mat->pipeline_params = array_new(struct Uniform);
unshaded_mat->active = 1; material->pipeline_params[MPP_CAM_POS].type = UT_VEC3;
unshaded_mat->lit = 0; material->pipeline_params[MPP_CAM_POS].location = shader_get_uniform_location(material->shader, "camera_pos");
/* Pipeline params/uniforms */
struct Uniform* uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("mvp");
uniform->type = UT_MAT4;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("model_mat");
uniform->type = UT_MAT4;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.mode");
uniform->type = UT_INT;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.density");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.start_dist");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.max_dist");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.color");
uniform->type = UT_VEC3;
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
/* Material params */
uniform = array_grow(unshaded_mat->model_params, struct Uniform);
uniform->name = str_new("diffuse_color");
uniform->type = UT_VEC4;
vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f);
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
uniform = array_grow(unshaded_mat->model_params, struct Uniform);
uniform->name = str_new("diffuse_texture");
uniform->type = UT_TEX;
uniform->d_int = texture_find("default.tga");
uniform->location = shader_get_uniform_location(unshaded_mat->shader, uniform->name);
/* Simple blinn_phong material */
struct Material* blinn_phong_mat = array_grow(material_list, struct Material);
blinn_phong_mat->name = str_new("Blinn_Phong");
blinn_phong_mat->shader = shader_create("blinn_phong.vert", "blinn_phong.frag");
blinn_phong_mat->registered_models = array_new(int);
blinn_phong_mat->model_params = array_new(struct Uniform);
blinn_phong_mat->pipeline_params = array_new(struct Uniform);
blinn_phong_mat->active = 1;
blinn_phong_mat->lit = 1;
/* Pipeline params/uniforms */
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("mvp");
uniform->type = UT_MAT4;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("model_mat");
uniform->type = UT_MAT4;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
/* uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform); */
/* uniform->name = str_new("view_mat"); */
/* uniform->type = UT_MAT4; */
/* uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name); */
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("inv_model_mat");
uniform->type = UT_MAT4;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.mode");
uniform->type = UT_INT;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.density");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.start_dist");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.max_dist");
uniform->type = UT_FLOAT;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("fog.color");
uniform->type = UT_VEC3;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->pipeline_params, struct Uniform);
uniform->name = str_new("ambient_light");
uniform->type = UT_VEC3;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
/* Material params */
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
uniform->name = str_new("diffuse_color");
uniform->type = UT_VEC4;
vec4_fill(&uniform->d_vec4, 1.0f, 1.0f, 1.0f, 1.0f);
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
uniform->name = str_new("diffuse_texture");
uniform->type = UT_TEX;
uniform->d_int = texture_find("default.tga");
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
uniform->name = str_new("specular");
uniform->type = UT_FLOAT;
uniform->d_float = 1.f;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
uniform->name = str_new("diffuse");
uniform->type = UT_FLOAT;
uniform->d_float = 1.f;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
uniform = array_grow(blinn_phong_mat->model_params, struct Uniform);
uniform->name = str_new("specular_strength");
uniform->type = UT_FLOAT;
uniform->d_float = 50.f;
uniform->location = shader_get_uniform_location(blinn_phong_mat->shader, uniform->name);
}
struct Material* material_get_all_materials(void) material->pipeline_params[MPP_TOTAL_LIGHTS].type = UT_INT;
material->pipeline_params[MPP_TOTAL_LIGHTS].location = shader_get_uniform_location(material->shader, "total_active_lights");
material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX;
material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture");
material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4;
material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color");
material->model_params[MMP_DIFFUSE].type = UT_FLOAT;
material->model_params[MMP_DIFFUSE].location = shader_get_uniform_location(material->shader, "diffuse");
material->model_params[MMP_SPECULAR].type = UT_FLOAT;
material->model_params[MMP_SPECULAR].location = shader_get_uniform_location(material->shader, "specular");
material->model_params[MMP_SPECULAR_STRENGTH].type = UT_FLOAT;
material->model_params[MMP_SPECULAR_STRENGTH].location = shader_get_uniform_location(material->shader, "specular");
}
break;
case MAT_UNSHADED:
{ {
return material_list; material->lit = false;
material->shader = shader_create("unshaded.vert", "unshaded.frag");
material->model_params[MMP_DIFFUSE_TEX].type = UT_TEX;
material->model_params[MMP_DIFFUSE_TEX].location = shader_get_uniform_location(material->shader, "diffuse_texture");
material->model_params[MMP_DIFFUSE_COL].type = UT_VEC4;
material->model_params[MMP_DIFFUSE_COL].location = shader_get_uniform_location(material->shader, "diffuse_color");
};
break;
default:
log_error("material:init", "Invalid material type");
return false;
} }
void material_cleanup(void) // Setup common pipeline parameters
{ material->pipeline_params[MPP_FOG_MODE].type = UT_INT;
for(int i = 0; i < array_len(material_list); i++) material->pipeline_params[MPP_FOG_MODE].location = shader_get_uniform_location(material->shader, "fog.mode");
material_remove(i);
array_free(empty_indices); material->pipeline_params[MPP_FOG_DENSITY].type = UT_FLOAT;
array_free(material_list); material->pipeline_params[MPP_FOG_DENSITY].location = shader_get_uniform_location(material->shader, "fog.density");
material->pipeline_params[MPP_FOG_START_DIST].type = UT_FLOAT;
material->pipeline_params[MPP_FOG_START_DIST].location = shader_get_uniform_location(material->shader, "fog.start_dist");
material->pipeline_params[MPP_FOG_MAX_DIST].type = UT_FLOAT;
material->pipeline_params[MPP_FOG_MAX_DIST].location = shader_get_uniform_location(material->shader, "fog.max_dist");
material->pipeline_params[MPP_FOG_COLOR].type = UT_VEC3;
material->pipeline_params[MPP_FOG_COLOR].location = shader_get_uniform_location(material->shader, "fog.color");
material->pipeline_params[MPP_MVP].type = UT_MAT4;
material->pipeline_params[MPP_MVP].location = shader_get_uniform_location(material->shader, "mvp");
material->pipeline_params[MPP_MODEL_MAT].type = UT_MAT4;
material->pipeline_params[MPP_MODEL_MAT].location = shader_get_uniform_location(material->shader, "model_mat");
material->pipeline_params[MPP_AMBIENT_LIGHT].type = UT_VEC3;
material->pipeline_params[MPP_AMBIENT_LIGHT].location = shader_get_uniform_location(material->shader, "ambient_light");
return true;
} }
bool material_register_model(struct Entity* entity, const char* material_name) void material_reset(struct Material* material)
{
assert(material_name && entity);
bool success = false;
int index = material_get_index(material_name);
if(index <= -1)
{ {
log_error("material:register_model", "Material '%s' not found", material_name); assert(material);
return success;
material->type = -1;
memset(material->registered_models, 0, sizeof(struct Model*) * MAX_MATERIAL_REGISTERED_MODELS);
memset(material->model_params, 0, sizeof(struct Uniform) * MMP_MAX);
memset(material->pipeline_params, 0, sizeof(struct Uniform) * MPP_MAX);
} }
struct Model* model = &entity->model; bool material_register_model(struct Material* material, struct Model* model)
struct Material* material = &material_list[index];
model->material = index;
model->material_params = array_new(struct Material_Param);
for(int i = 0; i < array_len(material->model_params); i++)
{
/* set up parameters */
struct Uniform* uniform = &material->model_params[i];
struct Material_Param* param = array_grow(model->material_params, struct Material_Param);
param->uniform_index = i;
switch(uniform->type)
{ {
case UT_INT: assert(model && material);
param->value = malloc(sizeof(int));
*((int*)param->value) = uniform->d_int;
break;
case UT_FLOAT:
param->value = malloc(sizeof(float));
*((float*)param->value) = uniform->d_float;
break;
case UT_VEC2:
param->value = malloc(sizeof(vec2));
vec2_assign((vec2*)param->value, &uniform->d_vec2);
break;
case UT_VEC3:
param->value = malloc(sizeof(vec3));
vec3_assign((vec3*)param->value, &uniform->d_vec3);
break;
case UT_VEC4:
param->value = malloc(sizeof(vec4));
vec4_assign((vec4*)param->value, &uniform->d_vec4);
break;
case UT_MAT4:
param->value = malloc(sizeof(mat4));
mat4_identity((mat4*)param->value);
break;
case UT_TEX:
param->value = malloc(sizeof(int));
*((int*)param->value) = texture_create_from_file("default.tga", TU_DIFFUSE);
break;
}
}
array_push(material->registered_models, entity->id, int); for(int i = 0; i < MAX_MATERIAL_REGISTERED_MODELS; i++)
success = true; {
return success; if(!material->registered_models[i])
} {
material->registered_models[i] = model;
void material_unregister_model(struct Entity* entity) // Set default values for instance parameters
switch(material->type)
{ {
assert(entity); case MAT_BLINN:
struct Model* model = &entity->model;
struct Material* material = &material_list[model->material];
/* Remove textures, if any */
for(int i = 0; i < array_len(model->material_params); i++)
{ {
struct Material_Param* param = &model->material_params[i]; variant_assign_vec4f(&model->material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f);
struct Uniform* uniform = &material->model_params[param->uniform_index]; variant_assign_float(&model->material_params[MMP_DIFFUSE], 1.f);
if(uniform->type == UT_TEX) variant_assign_int(&model->material_params[MMP_DIFFUSE_TEX], texture_find("default.tga"));
texture_remove(*(int*)param->value); variant_assign_float(&model->material_params[MMP_SPECULAR], 1.f);
variant_assign_float(&model->material_params[MMP_SPECULAR_STRENGTH], 50.f);
} }
/* Remove model index from material registry*/ break;
for(int i = 0; i < array_len(material->registered_models); i++) case MAT_UNSHADED:
{
if(material->registered_models[i] == entity->id)
{ {
array_remove_at(material->registered_models, i); variant_assign_vec4f(&model->material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f);
variant_assign_int(&model->material_params[MMP_DIFFUSE_TEX], texture_find("default.tga"));
}
break;
default:
log_error("material:register_model", "Invalid material type");
break; break;
} }
return true;
} }
} }
struct Material* material_find(const char* material_name) return false;
{
struct Material* material = NULL;
int index = material_get_index(material_name);
if(index > -1) material = &material_list[index];
return material;
} }
int material_get_index(const char* material_name) void material_unregister_model(struct Material* material, struct Model* model)
{
int index = -1;
for(int i = 0; i < array_len(material_list); i++)
{ {
if(!material_list[i].name) continue; assert(model && material);
if(strcmp(material_name, material_list[i].name) == 0) for(int i = 0; i < MAX_MATERIAL_REGISTERED_MODELS; i++)
{
if(material->registered_models[i] == model)
{ {
index = i; material->registered_models[i] = NULL;
for(int i = 0; i < MMP_MAX; i++)
variant_free(&model->material_params[i]);
break; break;
} }
} }
return index;
}
struct Material* material_get(int index)
{
struct Material* material = NULL;
if(index > -1 && index < array_len(material_list))
material = &material_list[index];
return material;
}
void material_remove(int index)
{
assert(index > -1 && index < array_len(material_list));
struct Material* material = &material_list[index];
if(!material->active)
return;
material->active = 0;
array_free(material->registered_models);
for(int i = 0; i < array_len(material->model_params); i++)
free(material->model_params[i].name);
array_free(material->model_params);
for(int i = 0; i < array_len(material->pipeline_params); i++)
free(material->pipeline_params[i].name);
array_free(material->pipeline_params);
log_message("Removed material '%s'", material->name);
free(material->name);
array_push(empty_indices, index, int);
} }

@ -3,49 +3,67 @@
#include "../common/linmath.h" #include "../common/linmath.h"
#include "../common/num_types.h" #include "../common/num_types.h"
#include "../common/variant.h"
struct Entity; struct Model;
#define MAX_UNIFORM_NAME_LEN 64
#define MAX_MATERIAL_REGISTERED_MODELS 1024
struct Uniform struct Uniform
{ {
int location; int location;
char* name;
int type; int type;
union /* Default values */ };
enum Mat_Type
{ {
vec2 d_vec2; MAT_BLINN = 0,
vec3 d_vec3; MAT_UNSHADED,
vec4 d_vec4; MAT_MAX
int d_int;
float d_float;
}; };
enum Mat_Model_Param
{
MMP_DIFFUSE_TEX = 0,
MMP_DIFFUSE_COL,
MMP_DIFFUSE,
MMP_SPECULAR_STRENGTH,
MMP_SPECULAR,
MMP_MAX
}; };
struct Material_Param enum Mat_Pipeline_Param
{ {
int uniform_index; /* Index of the corresponding uniform in the material's model_params */ MPP_MODEL_MAT = 0,
void* value; /* Actual value of the uniform */ MPP_INV_MODEL_MAT,
MPP_VIEW_MAT,
MPP_MVP,
MPP_FOG_MODE,
MPP_FOG_DENSITY,
MPP_FOG_START_DIST,
MPP_FOG_MAX_DIST,
MPP_FOG_COLOR,
MPP_CAM_POS,
MPP_TOTAL_LIGHTS,
MPP_AMBIENT_LIGHT,
MPP_MAX
}; };
struct Material struct Material
{ {
char* name; int type;
int shader; int shader;
int* registered_models; struct Model* registered_models[MAX_MATERIAL_REGISTERED_MODELS];
bool active; bool lit;
bool lit; /* If material uses light information */ struct Uniform model_params[MMP_MAX];
struct Uniform* model_params; /* uniforms related to models */ struct Uniform pipeline_params[MPP_MAX];
struct Uniform* pipeline_params; /* general uniforms like matrices etc */
}; };
struct Material* material_get_all_materials(void); bool material_init(struct Material* material, int material_type);
struct Material* material_find(const char* material_name); void material_reset(struct Material* material);
struct Material* material_get(int index); bool material_register_model(struct Material* material, struct Model* model);
int material_get_index(const char* material_name); void material_unregister_model(struct Material* material, struct Model* model);
void material_init(void);
void material_cleanup(void);
bool material_register_model(struct Entity* entity, const char* material_name);
void material_unregister_model(struct Entity* entity);
void material_remove(int index);
#endif #endif

@ -1,6 +1,8 @@
#include "model.h" #include "model.h"
#include "../common/array.h" #include "../common/array.h"
#include "../common/log.h" #include "../common/log.h"
#include "game.h"
#include "renderer.h"
#include "entity.h" #include "entity.h"
#include "texture.h" #include "texture.h"
#include "material.h" #include "material.h"
@ -11,103 +13,41 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void model_create(struct Entity* entity, const char* geo_name, const char* material_name) void model_init(struct Model* model, const char* geometry_name, int material_type)
{ {
struct Model* model = &entity->model; assert(model && material_type > -1 && material_type < MAT_MAX);
/* if no name is given for geometry, use default */ /* if no name is given for geometry, use default */
int geo_index = geom_create_from_file(geo_name ? geo_name : "default.pamesh"); int geo_index = geom_create_from_file(geometry_name ? geometry_name : "default.pamesh");
if(geo_index == -1) if(geo_index == -1)
{ {
log_error("model:create", "Failed to load model %s", geo_name); log_error("model:init", "Failed to load model %s", geometry_name);
geo_index = geom_create_from_file("default.pamesh"); geo_index = geom_create_from_file("default.pamesh");
if(geo_index == -1) if(geo_index == -1)
{ {
log_error("model:create", "Could not load default model 'default.pamesh' "); log_error("model:init", "Could not load default model 'default.pamesh' ");
return; return;
} }
} }
model->geometry_index = geo_index; model->geometry_index = geo_index;
if(!material_register_model(entity, material_name ? material_name : "Unshaded")) if(!material_register_model(model, material_type))
{ {
log_error("model:create", "Unable to register model with Unshaded material, component not added"); log_error("model:create", "Unable to register model with Unshaded material, component not added");
model_destroy(entity); model_reset(model);
} }
} }
void model_destroy(struct Entity* entity) void model_reset(struct Model* model)
{ {
struct Model* model = &entity->model; assert(model);
geom_remove(model->geometry_index); geom_remove(model->geometry_index);
model->geometry_index = -1; model->geometry_index = -1;
material_unregister_model(entity); struct Renderer* renderer = game_state_get()->renderer;
/* deallocate all params */ if(model->material)
for(int i = 0; i < array_len(model->material_params); i++)
free(model->material_params[i].value);
array_free(model->material_params);
model->material_params = NULL;
model->material = -1;
}
int model_set_material_param(struct Entity* entity, const char* name, void* value)
{
assert(name && value);
struct Model* model = &entity->model;
int success = 0;
struct Material* material = material_get(model->material);
for(int i = 0; i < array_len(model->material_params); i++)
{
struct Material_Param* param = &model->material_params[i];
struct Uniform* uniform = &material->model_params[param->uniform_index];
if(strcmp(uniform->name, name) == 0)
{
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;
default:
log_error("model:set_material_param", "Invalid parameter type");
success = 0;
break;
}
break; /* break for */
}
}
return success;
}
int model_get_material_param(struct Entity* entity, const char* name, void* value_out)
{
assert(name && value_out);
struct Model* model = &entity->model;
int success = 0;
struct Material* material = material_get(model->material);
for(int i = 0; i < array_len(model->material_params); i++)
{ {
struct Material_Param* param = &model->material_params[i]; struct Material* material = &renderer->materials[model->material->type];
struct Uniform* uniform = &material->model_params[param->uniform_index]; material_unregister_model(material, model);
if(strcmp(uniform->name, name) == 0)
{
switch(uniform->type)
{
case UT_INT: *((int*)value_out) = *((int*)param->value); break;
case UT_FLOAT: *((float*)value_out) = *((float*)param->value); break;
case UT_VEC2: vec2_assign((vec2*)value_out, (vec2*)param->value); break;
case UT_VEC3: vec3_assign((vec3*)value_out, (vec3*)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;
}
success = 1;
break;
}
} }
return success;
} }

@ -1,13 +1,9 @@
#ifndef MODEL_H #ifndef MODEL_H
#define MODEL_H #define MODEL_H
#include "../common/linmath.h" struct Model;
struct Entity; void model_init(struct Model* model, const char* geometry_name, int material_type);
void model_reset(struct Model* model);
void model_create(struct Entity* entity, const char* geo_name, const char* material_name);
void model_destroy(struct Entity* entity);
int model_set_material_param(struct Entity* entity, const char* name, void* value);
int model_get_material_param(struct Entity* entity, const char* name, void* value_out);
#endif #endif

@ -22,31 +22,19 @@
#include "im_render.h" #include "im_render.h"
#include "../common/variant.h" #include "../common/variant.h"
#include "../common/common.h" #include "../common/common.h"
#include "scene.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#define MAX_UNIFORM_NAME_LEN 64
/* TODO: Move all this into a struct called renderer state */
static int def_fbo = -1;
static int def_albedo_tex = -1;
static int def_depth_tex = -1;
static int quad_geo = -1;
static int composition_shader = -1;
static int debug_shader = -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;
static struct Sprite_Batch* sprite_batch = NULL;
void on_framebuffer_size_change(int width, int height); void on_framebuffer_size_change(int width, int height);
void renderer_init(void) void renderer_init(struct Renderer* renderer)
{ {
assert(renderer);
glClearColor(0.3f, 0.6f, 0.9f, 1.0f); glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -78,7 +66,7 @@ void renderer_init(void)
array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint); array_push(indices, 0, uint); array_push(indices, 1, uint); array_push(indices, 2, uint);
array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint); array_push(indices, 2, uint); array_push(indices, 3, uint); array_push(indices, 0, uint);
quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL); renderer->quad_geo = geom_create("Quad", vertices, uvs, normals, indices, NULL);
array_free(vertices); array_free(vertices);
array_free(uvs); array_free(uvs);
array_free(normals); array_free(normals);
@ -87,66 +75,70 @@ void renderer_init(void)
int width = -1, height = -1; int width = -1, height = -1;
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height); platform->window.get_size(game_state->window, &width, &height);
def_albedo_tex = texture_create("def_albedo_texture", renderer->def_albedo_tex = texture_create("def_albedo_texture",
TU_DIFFUSE, TU_DIFFUSE,
width, height, width, height,
GL_RGB, GL_RGB,
GL_RGB16F, GL_RGB16F,
GL_FLOAT, GL_FLOAT,
NULL); NULL);
texture_set_param(def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texture_set_param(renderer->def_albedo_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
def_depth_tex = texture_create("def_depth_texture", renderer->def_depth_tex = texture_create("def_depth_texture",
TU_SHADOWMAP4, TU_SHADOWMAP4,
width, height, width, height,
GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F,
GL_FLOAT, GL_FLOAT,
NULL); NULL);
texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture_set_param(def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture_set_param(def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_set_param(def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
texture_set_param(def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); texture_set_param(renderer->def_depth_tex, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
def_fbo = framebuffer_create(width, height, true, false, true); renderer->def_fbo = framebuffer_create(width, height, true, false, true);
framebuffer_texture_set(def_fbo, def_albedo_tex, FA_COLOR_ATTACHMENT0); framebuffer_texture_set(renderer->def_fbo, renderer->def_albedo_tex, FA_COLOR_ATTACHMENT0);
framebuffer_texture_set(def_fbo, def_depth_tex, FA_DEPTH_ATTACHMENT); framebuffer_texture_set(renderer->def_fbo, renderer->def_depth_tex, FA_DEPTH_ATTACHMENT);
composition_shader = shader_create("fbo.vert", "fbo.frag"); renderer->composition_shader = shader_create("fbo.vert", "fbo.frag");
debug_shader = shader_create("debug.vert", "debug.frag"); renderer->debug_shader = shader_create("debug.vert", "debug.frag");
num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT); renderer->num_culled_slot = editor_debugvar_slot_create("Culled Geom", VT_INT);
num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT); renderer->num_rendered_slot = editor_debugvar_slot_create("Rendered Geom", VT_INT);
num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT); renderer->num_indices_slot = editor_debugvar_slot_create("Total Indices", VT_INT);
sprite_batch = malloc(sizeof(*sprite_batch)); renderer->sprite_batch = malloc(sizeof(*renderer->sprite_batch));
if(!sprite_batch) if(!renderer->sprite_batch)
{ {
log_error("renderer:init", "Failed to allocated sprite batch"); log_error("renderer:init", "Failed to allocated sprite batch");
} }
else else
{ {
sprite_batch_create(sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES); sprite_batch_create(renderer->sprite_batch, "sprite_map.tga", "sprite.vert", "sprite.frag", GL_TRIANGLES);
} }
im_init(); im_init();
// Initialize materials
for(int i = 0; i < MAT_MAX; i++)
{
material_init(&renderer->materials[i], i);
}
} }
void renderer_draw(struct Entity* active_viewer) void renderer_draw(struct Renderer* renderer, struct Scene* scene)
{ {
/* Render each camera output into it's framebuffer or to the default framebuffer */ /* Render each camera output into it's framebuffer or to the default framebuffer */
struct Entity* entity_list = entity_get_all(); for(int i = 0; i < MAX_CAMERAS; i++)
for(int i = 0; i < array_len(entity_list); i++)
{ {
struct Entity* viewer = &entity_list[i]; struct Camera* camera = &scene->cameras[i];
if(entity_list[i].type != ET_CAMERA) continue; if(!camera->base.active) continue;
struct Camera* camera = &viewer->camera;
int fbo = camera->fbo == -1 ? def_fbo : camera->fbo; int fbo = camera->fbo == -1 ? renderer->def_fbo : camera->fbo;
framebuffer_bind(fbo); framebuffer_bind(fbo);
{ {
glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo)); glViewport(0, 0, framebuffer_width_get(fbo), framebuffer_height_get(fbo));
@ -160,35 +152,34 @@ void renderer_draw(struct Entity* active_viewer)
glCullFace(GL_BACK); glCullFace(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static mat4 mvp; static mat4 mvp;
struct Material* material_list = material_get_all_materials(); for(int i = 0; i < MAT_MAX; i++)
for(int i = 0; i < array_len(material_list); i++)
{ {
/* for each material, get all the registered models and render them */ /* for each material, get all the registered models and render them */
struct Material* material = &material_list[i]; struct Material* material = &renderer->materials[i];
if(!material->active || array_len(material->registered_models) == 0) if(array_len(material->registered_models) == 0)
continue; continue;
shader_bind(material->shader); GL_CHECK(shader_bind(material->shader));
renderer_check_glerror("model:render_all:shader_bind");
if(material->lit) /* Set light information */ if(material->lit) /* Set light information */
{ {
int valid_light_count = 0;
int* light_index_list = light_get_valid_indices(&valid_light_count);
char uniform_name[MAX_UNIFORM_NAME_LEN]; char uniform_name[MAX_UNIFORM_NAME_LEN];
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
for(int i = 0; i < valid_light_count; i++) int light_count = 0;
for(int i = 0; i < MAX_LIGHTS; i++)
{ {
struct Entity* light_entity = entity_get(light_index_list[i]); struct Light* light = &scene->lights[i]; /* TODO: Cull lights according to camera frustum */
struct Light* light = &light_entity->light; /* TODO: Cull lights according to camera frustum */ if(!light->base.active) continue;
light_count++;
vec3 light_pos = {0, 0, 0}; vec3 light_pos = {0, 0, 0};
transform_get_absolute_position(light_entity, &light_pos); transform_get_absolute_position(&light->base, &light_pos);
if(light->type != LT_POINT) if(light->type != LT_POINT)
{ {
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].direction", light_count);
vec3 light_dir = {0.f, 0.f, 0.f}; vec3 light_dir = {0.f, 0.f, 0.f};
transform_get_absolute_lookat(light_entity, &light_dir); transform_get_absolute_lookat(&light->base, &light_dir);
vec3_norm(&light_dir, &light_dir); vec3_norm(&light_dir, &light_dir);
shader_set_uniform_vec3(material->shader, uniform_name, &light_dir); shader_set_uniform_vec3(material->shader, uniform_name, &light_dir);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
@ -196,171 +187,123 @@ void renderer_draw(struct Entity* active_viewer)
if(light->type != LT_DIR) if(light->type != LT_DIR)
{ {
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].position", light_count);
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_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].outer_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->outer_angle); shader_set_uniform_float(material->shader, uniform_name, light->outer_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].inner_angle", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->inner_angle); shader_set_uniform_float(material->shader, uniform_name, light->inner_angle);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].falloff", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->falloff); shader_set_uniform_float(material->shader, uniform_name, light->falloff);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].radius", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->radius); shader_set_uniform_int(material->shader, uniform_name, light->radius);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
} }
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].color", light_count);
shader_set_uniform_vec3(material->shader, uniform_name, &light->color); shader_set_uniform_vec3(material->shader, uniform_name, &light->color);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].intensity", light_count);
shader_set_uniform_float(material->shader, uniform_name, light->intensity); shader_set_uniform_float(material->shader, uniform_name, light->intensity);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", i); snprintf(uniform_name, MAX_UNIFORM_NAME_LEN, "lights[%d].type", light_count);
shader_set_uniform_int(material->shader, uniform_name, light->type); shader_set_uniform_int(material->shader, uniform_name, light->type);
memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN);
} }
shader_set_uniform_int(material->shader, "total_active_lights", valid_light_count); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_TOTAL_LIGHTS].type, material->pipeline_params[MPP_TOTAL_LIGHTS].location, &light_count));
vec3 camera_pos = {0, 0, 0}; vec3 camera_pos = {0, 0, 0};
transform_get_absolute_position(viewer, &camera_pos); transform_get_absolute_position(&camera->base, &camera_pos);
shader_set_uniform_vec3(material->shader, "camera_pos", &camera_pos); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_CAM_POS].type, material->pipeline_params[MPP_CAM_POS].location, &camera_pos));
} }
/* Set material pipeline uniforms */ /* Set material pipeline uniforms */
static struct Render_Settings render_settings; GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MODE].type, material->pipeline_params[MPP_FOG_MODE].location, &renderer->settings.fog.mode));
renderer_settings_get(&render_settings); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_DENSITY].type, material->pipeline_params[MPP_FOG_DENSITY].location, &renderer->settings.fog.density));
for(int k = 0; k < array_len(material->pipeline_params); k++) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_START_DIST].type, material->pipeline_params[MPP_FOG_START_DIST].location, &renderer->settings.fog.start_dist));
{ GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_MAX_DIST].type, material->pipeline_params[MPP_FOG_MAX_DIST].location, &renderer->settings.fog.max_dist));
struct Uniform* uniform = &material->pipeline_params[k]; GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_FOG_COLOR].type, material->pipeline_params[MPP_FOG_COLOR].location, &renderer->settings.fog.color));
if(strcmp(uniform->name, "view_mat") == 0) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_AMBIENT_LIGHT].type, material->pipeline_params[MPP_AMBIENT_LIGHT].location, &renderer->settings.ambient_light));
{ if(material->lit) GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat));
shader_set_uniform(uniform->type, uniform->location, &viewer->camera.view_mat);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "fog.mode") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.mode);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "fog.density") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.density);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "fog.start_dist") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.start_dist);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "fog.max_dist") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.max_dist);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "fog.color") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.fog.color);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "ambient_light") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &render_settings.ambient_light);
renderer_check_glerror("model:render_all:material_pipeline");
}
}
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 Entity* entity = entity_get(material->registered_models[j]); struct Static_Mesh* mesh = material->registered_models[i];
struct Model* model = &entity->model; struct Geometry* geometry = geom_get(mesh->model.geometry_index);
struct Transform* transform = &entity->transform;
struct Geometry* geometry = geom_get(model->geometry_index);
/* Check if model is in frustum */ /* Check if model is in frustum */
int intersection = bv_intersect_frustum_sphere(viewer->camera.frustum, &geometry->bounding_sphere, entity); vec3 abs_pos, abs_scale;
transform_get_absolute_position(&mesh->base, &abs_pos);
transform_get_absolute_scale(&mesh->base, &abs_scale);
int intersection = bv_intersect_frustum_sphere(&camera->frustum, &geometry->bounding_sphere, &abs_pos, &abs_scale);
if(intersection == IT_OUTSIDE) if(intersection == IT_OUTSIDE)
{ {
num_culled++; renderer->num_culled++;
continue; continue;
} }
else else
{ {
num_indices += array_len(geometry->indices); renderer->num_indices += array_len(geometry->indices);
num_rendered++; renderer->num_rendered++;
} }
/* 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 < MMP_MAX; k++)
{
switch(mesh->model.material_params[i].type)
{ {
struct Material_Param* param = &model->material_params[k]; case VT_INT: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_int)); break;
struct Uniform* uniform = &material->model_params[param->uniform_index]; case VT_FLOAT: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_float)); break;
shader_set_uniform(uniform->type, uniform->location, param->value); case VT_VEC3: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_vec3)); break;
renderer_check_glerror("model:render_all:material_param"); case VT_VEC4: GL_CHECK(shader_set_uniform(material->model_params[i].type, material->model_params[i].location, &mesh->model.material_params[i].val_vec4)); break;
}
} }
/* Set pipeline uniforms that are derived per model */ /* Set pipeline uniforms that are derived per model */
for(int k = 0; k < array_len(material->pipeline_params); k++)
{
/* TODO: change this into something better */
struct Uniform* uniform = &material->pipeline_params[k];
if(strcmp(uniform->name, "mvp") == 0)
{
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &viewer->camera.view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &camera->view_proj_mat, &mesh->base.transform.trans_mat);
shader_set_uniform(uniform->type, uniform->location, &mvp); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_MVP].type, material->pipeline_params[MPP_MVP].location, &mvp));
renderer_check_glerror("model:render_all:material_pipeline");
} if(material->lit)
else if(strcmp(uniform->name, "model_mat") == 0)
{
shader_set_uniform(uniform->type, uniform->location, &transform->trans_mat);
renderer_check_glerror("model:render_all:material_pipeline");
}
else if(strcmp(uniform->name, "inv_model_mat") == 0)
{ {
GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_VIEW_MAT].type, material->pipeline_params[MPP_VIEW_MAT].location, &camera->view_mat));
mat4 inv_mat; mat4 inv_mat;
mat4_identity(&inv_mat); mat4_identity(&inv_mat);
mat4_inverse(&inv_mat, &transform->trans_mat); mat4_inverse(&inv_mat, &mesh->base.transform.trans_mat);
shader_set_uniform(uniform->type, uniform->location, &inv_mat); GL_CHECK(shader_set_uniform(material->pipeline_params[MPP_INV_MODEL_MAT].type, material->pipeline_params[MPP_INV_MODEL_MAT].location, &inv_mat));
renderer_check_glerror("model:render_all:material_pipeline");
}
} }
/* Render the geometry */ /* Render the geometry */
//int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode); //int indices = geom_render_in_frustum(model->geometry_index, &viewer->camera.frustum[0], entity, draw_mode);
//geom_render(model->geometry_index, draw_mode); //geom_render(model->geometry_index, draw_mode);
geom_render(model->geometry_index, GDM_TRIANGLES); geom_render(mesh->model.geometry_index, GDM_TRIANGLES);
for(int k = 0; k < array_len(model->material_params); k++) for(int k = 0; k < MMP_MAX; k++)
{ {
/* unbind textures, if any */ /* unbind textures, if any */
struct Material_Param* param = &model->material_params[k]; if(material->model_params[k].type == UT_TEX)
struct Uniform* uniform = &material->model_params[param->uniform_index]; GL_CHECK(texture_unbind(mesh->model.material_params[k].val_int));
if(uniform->type == UT_TEX)
{
texture_unbind(*(int*)param->value);
renderer_check_glerror("model:render_all:unbind_texture_uniform");
}
} }
} }
shader_unbind(); shader_unbind();
} }
editor_debugvar_slot_set_int(num_rendered_slot, num_rendered); editor_debugvar_slot_set_int(renderer->num_rendered_slot, renderer->num_rendered);
editor_debugvar_slot_set_int(num_culled_slot, num_culled); editor_debugvar_slot_set_int(renderer->num_culled_slot, renderer->num_culled);
editor_debugvar_slot_set_int(num_indices_slot, num_indices); editor_debugvar_slot_set_int(renderer->num_indices_slot, renderer->num_indices);
num_culled = num_rendered = num_indices = 0; renderer->num_culled = renderer->num_rendered = renderer->num_indices = 0;
} }
framebuffer_unbind(); framebuffer_unbind();
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
@ -368,16 +311,16 @@ void renderer_draw(struct Entity* active_viewer)
} }
/* Final Render */ /* Final Render */
struct Camera* active_camera = &scene->cameras[scene->active_camera_index];
int width, height; int width, height;
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
platform->window.get_size(game_state->window, &width, &height); platform->window.get_size(game_state->window, &width, &height);
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(renderer->composition_shader);
struct Camera* active_camera = &active_viewer->camera; int final_render_tex = active_camera->render_tex == -1 ? renderer->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(renderer->quad_geo, GDM_TRIANGLES);
texture_unbind(final_render_tex); texture_unbind(final_render_tex);
shader_unbind(); shader_unbind();
@ -387,20 +330,20 @@ void renderer_draw(struct Entity* active_viewer)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color"); vec4 debug_draw_color = hashmap_vec4_get(cvars, "debug_draw_color");
shader_bind(debug_shader); shader_bind(renderer->debug_shader);
{ {
static mat4 mvp; static mat4 mvp;
shader_set_uniform_vec4(debug_shader, "debug_color", &debug_draw_color); shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &debug_draw_color);
struct Entity* entity_list = entity_get_all(); for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < array_len(entity_list); i++)
{ {
if(!entity_list[i].renderable) continue; struct Static_Mesh* mesh = &scene->static_meshes[i];
struct Model* model = &entity_list[i].model; if(!mesh->base.active) continue;
struct Transform* transform = &entity_list[i].transform; struct Model* model = &mesh->model;
struct Transform* transform = &mesh->base.transform;
int geometry = model->geometry_index; int geometry = model->geometry_index;
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &active_viewer->camera.view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(debug_shader, "mvp", &mvp); shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp);
geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode")); geom_render(geometry, hashmap_int_get(cvars, "debug_draw_mode"));
} }
} }
@ -412,39 +355,38 @@ void renderer_draw(struct Entity* active_viewer)
if(hashmap_bool_get(cvars, "debug_draw_physics")) if(hashmap_bool_get(cvars, "debug_draw_physics"))
{ {
static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f };
struct Entity* entity_list = entity_get_all(); for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < array_len(entity_list); i++)
{ {
if(!entity_list[i].has_collision) continue; struct Static_Mesh* mesh = &scene->static_meshes[i];
struct Entity* entity = &entity_list[i]; if(!mesh->base.active || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue;
//Get collision mesh and it's props then render it //Get collision mesh and it's props then render it
vec3 pos = {0.f}; vec3 pos = {0.f};
quat rot = {0.f, 0.f, 0.f, 1.f }; quat rot = {0.f, 0.f, 0.f, 1.f };
if(entity->collision.rigidbody) if(mesh->collision.rigidbody)
{ {
platform->physics.body_position_get(entity->collision.rigidbody, &pos.x, &pos.y, &pos.z); platform->physics.body_position_get(mesh->collision.rigidbody, &pos.x, &pos.y, &pos.z);
platform->physics.body_rotation_get(entity->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w); platform->physics.body_rotation_get(mesh->collision.rigidbody, &rot.x, &rot.y, &rot.z, &rot.w);
} }
else else
{ {
platform->physics.cs_position_get(entity->collision.collision_shape, &pos.x, &pos.y, &pos.z); platform->physics.cs_position_get(mesh->collision.collision_shape, &pos.x, &pos.y, &pos.z);
platform->physics.cs_rotation_get(entity->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w); platform->physics.cs_rotation_get(mesh->collision.collision_shape, &rot.x, &rot.y, &rot.z, &rot.w);
} }
int collision_shape_type = platform->physics.cs_type_get(entity->collision.collision_shape); int collision_shape_type = platform->physics.cs_type_get(mesh->collision.collision_shape);
switch(collision_shape_type) switch(collision_shape_type)
{ {
case CST_SPHERE: case CST_SPHERE:
{ {
float radius = platform->physics.cs_sphere_radius_get(entity->collision.collision_shape); float radius = platform->physics.cs_sphere_radius_get(mesh->collision.collision_shape);
im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES); im_sphere(radius, pos, rot, physics_draw_color, GDM_TRIANGLES);
} }
break; break;
case CST_BOX: case CST_BOX:
{ {
float x = 0.f, y = 0.f, z = 0.f; float x = 0.f, y = 0.f, z = 0.f;
platform->physics.cs_box_params_get(entity->collision.collision_shape, &x, &y, &z); platform->physics.cs_box_params_get(mesh->collision.collision_shape, &x, &y, &z);
im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES); im_box(x, y, z, pos, rot, physics_draw_color, GDM_TRIANGLES);
}; };
break; break;
@ -454,11 +396,11 @@ void renderer_draw(struct Entity* active_viewer)
} }
//Immediate mode geometry render //Immediate mode geometry render
im_render(active_viewer); im_render(active_camera);
/* Render 2D stuff */ /* Render 2D stuff */
shader_bind(sprite_batch->shader); shader_bind(renderer->sprite_batch->shader);
{ {
static mat4 ortho_mat; static mat4 ortho_mat;
mat4_identity(&ortho_mat); mat4_identity(&ortho_mat);
@ -467,9 +409,9 @@ void renderer_draw(struct Entity* active_viewer)
platform->window.get_size(game_state->window, &width, &height); platform->window.get_size(game_state->window, &width, &height);
mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f); mat4_ortho(&ortho_mat, 0.f, (float)width, (float)height, 0.f, -10.f, 10.f);
shader_set_uniform_mat4(sprite_batch->shader, "mvp", &ortho_mat); shader_set_uniform_mat4(renderer->sprite_batch->shader, "mvp", &ortho_mat);
sprite_batch_render(sprite_batch); sprite_batch_render(renderer->sprite_batch);
} }
shader_unbind(); shader_unbind();
@ -477,28 +419,30 @@ void renderer_draw(struct Entity* active_viewer)
gui_render(NK_ANTI_ALIASING_ON); gui_render(NK_ANTI_ALIASING_ON);
} }
void renderer_cleanup(void) void renderer_cleanup(struct Renderer* renderer)
{
for(int i = 0; i < MAT_MAX; i++)
{ {
material_reset(&renderer->materials[i], i);
}
im_cleanup(); im_cleanup();
sprite_batch_remove(sprite_batch); sprite_batch_remove(renderer->sprite_batch);
free(sprite_batch); free(renderer->sprite_batch);
gui_cleanup(); gui_cleanup();
geom_remove(quad_geo); geom_remove(renderer->quad_geo);
framebuffer_remove(def_fbo); framebuffer_remove(renderer->def_fbo);
texture_remove(def_albedo_tex); texture_remove(renderer->def_albedo_tex);
texture_remove(def_depth_tex); texture_remove(renderer->def_depth_tex);
} }
void on_framebuffer_size_change(int width, int height) void on_framebuffer_size_change(int width, int height)
{ {
struct Entity* entity_list = entity_get_all(); struct Scene* scene = &game_state_get()->scene;
float aspect = (float)width / (float)height; float aspect = (float)width / (float)height;
for(int i = 0; i < array_len(entity_list); i++) for(int i = 0; i < MAX_CAMERAS; i++)
{ {
struct Entity* viewer = &entity_list[i]; struct Camera* viewer = &scene->cameras[i];
if(viewer->type != ET_CAMERA) continue; viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
viewer->camera.aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(viewer); camera_update_proj(viewer);
} }
@ -533,9 +477,9 @@ int renderer_check_glerror(const char* context)
return error; return error;
} }
struct Sprite_Batch * get_batch(void) struct Material * renderer_material_get(int material_type)
{ {
return sprite_batch; return NULL;
} }
void renderer_debug_draw_enabled(bool enabled) void renderer_debug_draw_enabled(bool enabled)

@ -3,6 +3,9 @@
#include "../common/linmath.h" #include "../common/linmath.h"
#include "../common/num_types.h" #include "../common/num_types.h"
#include "material.h"
struct Sprite_Batch;
enum Fog_Mode enum Fog_Mode
{ {
@ -32,18 +35,25 @@ struct Render_Settings
bool debug_draw_physics; bool debug_draw_physics;
}; };
struct Entity; struct Renderer
struct Sprite_Batch; {
int def_fbo;
int def_albedo_tex;
int def_depth_tex;
int quad_geo;
int composition_shader;
int debug_shader;
int num_culled , num_rendered , num_indices;
int num_culled_slot, num_rendered_slot, num_indices_slot;
struct Sprite_Batch* sprite_batch;
struct Render_Settings settings;
struct Material materials[MAT_MAX];
};
void renderer_settings_get(struct Render_Settings* settings); void renderer_init(struct Renderer* renderer);
void renderer_settings_set(const struct Render_Settings* settings); void renderer_draw(struct Renderer* renderer, struct Scene* scene);
void renderer_init(void); void renderer_cleanup(struct Renderer* renderer);
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_clearcolor_set(float r, float g, float b, float a);
void renderer_debug_draw_enabled(bool enabled); void renderer_debug_draw_enabled(struct Renderer* renderer, bool enabled);
int renderer_check_glerror(const char* context);
struct Sprite_Batch* get_batch(void);
#endif #endif

@ -3,140 +3,530 @@
#include "entity.h" #include "entity.h"
#include "../common/log.h" #include "../common/log.h"
#include "transform.h" #include "transform.h"
#include "camera.h"
#include "../common/common.h" #include "../common/common.h"
#include "../common/parser.h" #include "../common/parser.h"
#include "model.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
static int root_node = -1; void scene_init(struct Scene* scene)
{
assert(scene);
//Initialize the root entity
entity_init(&scene->root_entity, "ROOT_ENTITY", NULL);
scene->root_entity.active = true;
scene->root_entity.id = 0;
scene->root_entity.type = ET_ROOT;
//Initialize player
entity_init(&scene->player, "Player", &scene->root_entity);
scene->player.base.active = true;
scene->player.base.id = 1;
scene->player.base.type = ET_PLAYER;
for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i);
for(int i = 0; i < MAX_LIGHTS; i++) entity_reset(&scene->lights[i], i);
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
entity_reset(&scene->static_meshes[i], i);
struct Static_Mesh* mesh = &scene->static_meshes[i];
mesh->collision.collision_shape = NULL;
mesh->collision.rigidbody = NULL;
mesh->collision.on_collision = NULL;
mesh->model.geometry_index = -1;
mesh->model.material = NULL;
}
for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i);
for(int i = 0; i < MAX_CAMERAS; i++)
{
entity_init(&scene->cameras[i], NULL, &scene->root_entity);
camera_init(&scene->cameras[i], 1024, 768);
scene->cameras[i].base.id = i;
}
scene->active_camera_index = CT_EDITOR;
}
void scene_init(void) bool scene_load(struct Scene* scene, const char* filename, int dir_type);
bool scene_save(struct Scene* scene, const char* filename, int dir_type);
void scene_destroy(struct Scene* scene)
{ {
/* Add root node to scene */ assert(scene);
/*struct Entity* root = entity_create("ROOT", ET_ROOT, -1);
root_node = root->id; */ for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_remove(scene, &scene->entities[i]);
for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]);
for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]);
for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]);
for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]);
entity_reset(&scene->root_entity, 0);
scene->root_entity.active = false;
} }
struct Entity* scene_add_new(const char* name, const int type) void scene_post_update(struct Scene* scene)
{ {
if(root_node == -1) assert(scene);
for(int i = 0; i < MAX_ENTITIES; i++)
{ {
log_warning("No root node in scene"); struct Entity* entity = &scene->entities[i];
struct Entity* root = entity_create("ROOT", ET_ROOT, -1); if(!entity->active) continue;
root_node = root->id;
if(entity->marked_for_deletion)
{
scene_entity_remove(scene, entity);
continue;
} }
return scene_add_as_child(name, type, root_node);
if(entity->transform.is_modified) entity->transform.is_modified = false;
} }
struct Entity* scene_add_as_child(const char* name, const int type, int parent_id) for(int i = 0; i < MAX_CAMERAS; i++)
{
struct Camera* camera = &scene->cameras[i];
if(!camera->base.active) continue;
if(camera->base.marked_for_deletion)
{ {
assert(parent_id > -1); scene_camera_remove(scene, camera);
return entity_create(name, type, parent_id); continue;
} }
void scene_remove(struct Entity* entity) if(camera->base.transform.is_modified)
{ {
assert(entity); camera_update_view(camera);
for(int i = 0; i < array_len(entity->transform.children); i++) camera->base.transform.is_modified = false;
}
}
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
{
struct Sound_Source* sound_source = &scene->sound_sources[i];
if(!sound_source->base.active) continue;
if(sound_source->base.marked_for_deletion)
{
scene_sound_source_remove(scene, sound_source);
continue;
}
if(sound_source->base.transform.is_modified)
{
vec3 abs_pos = {0.f, 0.f, 0.f};
transform_get_absolute_position(&sound_source->base, &abs_pos);
platform->sound.source_instance_update_position(sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z);
sound_source->base.transform.is_modified = false;
}
}
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* static_mesh = &scene->static_meshes[i];
if(!static_mesh->base.active) continue;
if(static_mesh->base.marked_for_deletion)
{
scene_static_mesh_remove(scene, static_mesh);
continue;
}
if(static_mesh->base.transform.is_modified)
{
if(static_mesh->collision.rigidbody && static_mesh->base.transform.sync_physics)
{
quat abs_rot = { 0.f, 0.f, 0.f, 1.f };
vec3 abs_pos = {0.f, 0.f, 0.f};
transform_get_absolute_rot(&static_mesh->base, &abs_rot);
transform_get_absolute_position(&static_mesh->base, &abs_pos);
platform->physics.body_rotation_set(static_mesh->collision.rigidbody, abs_rot.x, abs_rot.y, abs_rot.z, abs_rot.w);
platform->physics.body_position_set(static_mesh->collision.rigidbody, abs_pos.x, abs_pos.y, abs_pos.z);
}
static_mesh->base.transform.sync_physics = false;
static_mesh->base.transform.is_modified = false;
}
}
for(int i = 0; i < MAX_LIGHTS; i++)
{
struct Light* light = &scene->lights[i];
if(!light->base.active) continue;
if(light->base.marked_for_deletion)
{ {
struct Entity* child = entity_get(entity->transform.children[i]); scene_light_remove(scene, light);
scene_remove(child); continue;
}
if(light->base.transform.is_modified) light->base.transform.is_modified = false;
} }
entity_remove(entity->id);
for(int i = 0; i < MAX_ENTITIES; i++)
{
struct Entity* entity = &scene->entities[i];
if(!entity->active) continue;
} }
void scene_reset_parent(struct Entity* entity, struct Entity* new_parent) if(scene->player.base.transform.is_modified)
{ {
assert(entity && new_parent); vec3 abs_pos = {0.f, 0.f, 0.f};
struct Entity* curr_parent = entity_get(entity->transform.parent); vec3 abs_fwd = {0.f, 0.f, -1.f};
if(curr_parent) vec3 abs_up = {0.f, 1.f, 0.f};
transform_get_absolute_position(&scene->player, &abs_pos);
transform_get_absolute_forward(&scene->player, &abs_fwd);
transform_get_absolute_up(&scene->player, &abs_up);
platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z,
abs_fwd.x, abs_fwd.y, abs_fwd.z,
abs_up.x, abs_up.y, abs_up.z);
scene->player.base.transform.is_modified = false;
}
}
struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent)
{ {
/* find the index that the entity is at in the cuurent parent's assert(scene);
children array and remove it from there. Then set the new_parent
as the entity's parent */ struct Entity* new_entity = NULL;
int index = -1; for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < array_len(curr_parent->transform.children); i++)
{ {
if(curr_parent->transform.children[i] == entity->id) struct Entity* entity = &scene->entities[i];
if(!entity->active)
{ {
index = i; new_entity = entity;
break; break;
} }
} }
if(index > -1) if(new_entity)
{ {
array_remove_at(curr_parent->transform.children, index); if(!parent)
entity->transform.parent = new_parent->id; parent = &scene->root_entity;
array_push(new_parent, entity->id, int); entity_init(new_entity, name, parent);
transform_update_transmat(entity);
} }
else else
{ {
log_error("scene:reset_parent", "Entity %s not found in it's parent '%s''s children array"); log_error("scene:entity_create", "Max entity limit reached!");
} }
return new_entity;
}
struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type)
{
assert(scene);
struct Light* new_light = NULL;
for(int i = 0; i < MAX_LIGHTS; i++)
{
struct Light* light = &scene->lights[i];
if(!light->base.active)
{
new_light = light;
break;
}
}
if(new_light)
{
entity_init(&new_light->base, name, parent);
new_light->base.type = ET_LIGHT;
light_init(new_light, light_type);
} }
else else
{ {
log_error("scene:reset_parent", "Cannot change parent of ROOT entity"); log_error("scene:light_create", "Max light limit reached!");
} }
return new_light;
} }
void scene_cleanup(void) struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height)
{ {
struct Entity* entity_list = entity_get_all(); assert(scene);
for(int i = 0; i < array_len(entity_list); i++) struct Camera* new_camera = NULL;
for(int i = 0; i < MAX_CAMERAS; i++)
{ {
if(entity_list[i].id != -1) struct Camera* camera = &scene->cameras[i];
entity_remove(i); if(!camera->base.active)
{
new_camera = camera;
break;
} }
entity_post_update();
} }
struct Entity* scene_find(const char* name) if(new_camera)
{
entity_init(&new_camera->base, name, parent);
new_camera->base.type = ET_CAMERA;
camera_init(new_camera, width, height);
}
else
{ {
return entity_find(name); log_error("scene:camera_create", "Max camera limit reached!");
}
return new_camera;
} }
struct Entity* scene_get_root(void) struct Static_Model* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type)
{
assert(scene);
struct Static_Mesh* new_static_model = NULL;
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
struct Static_Mesh* static_model = &scene->static_meshes[i];
if(!static_model->base.active)
{ {
return entity_get(root_node); new_static_model = static_model;
break;
}
} }
void scene_root_set(struct Entity* entity) if(new_static_model)
{ {
// Only use this function when we know the scene is empty and needs a root node. entity_init(&new_static_model->base, name, parent);
// This is just a temporary way of setting root until we finalize how a scene should work new_static_model->base.type = ET_STATIC_MODEL;
if(root_node == -1) model_init(&new_static_model->model, geometry_name, material_type);
root_node = entity->id; // TODO: handle creating collision mesh for the model at creation
}
else else
log_error("scene:root_set", "Scene already has a root node!"); {
log_error("scene:model_create", "Max model limit reached!");
}
return new_static_model;
} }
struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name) struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play)
{ {
assert(parent); assert(scene && filename);
struct Entity* child = NULL; struct Sound_Source* new_sound_source = NULL;
for(int i = 0; i < array_len(parent->transform.children); i++) for(int i = 0; i < MAX_SOUND_SOURCES; i++)
{ {
struct Entity* curr_child = entity_get(parent->transform.children[i]); struct Sound_Source* sound_source = &scene->static_meshes[i];
if(strcmp(curr_child->name, name) == 0) if(!sound_source->base.active)
{ {
child = curr_child; new_sound_source = sound_source;
break; break;
} }
} }
return child;
if(new_sound_source)
{
entity_init(&new_sound_source->base, name, parent);
new_sound_source->base.type = ET_SOUND_SOURCE;
struct Entity* entity = &new_sound_source->base;
new_sound_source->source_buffer = platform->sound.source_create(filename, type);
if(!new_sound_source->source_buffer)
{
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name);
new_sound_source->source_instance = 0;
return new_sound_source;
} }
struct Entity* scene_get_parent(struct Entity* entity) new_sound_source->source_instance = platform->sound.source_instance_create(new_sound_source->source_buffer, true);
vec3 abs_pos = {0.f, 0.f, 0.f};
vec3 abs_fwd = {0.f, 0.f, -1.f};
vec3 abs_up = {0.f, 1.f, 0.f};
transform_get_absolute_position(entity, &abs_pos);
transform_get_absolute_forward(entity, &abs_fwd);
transform_get_absolute_up(entity, &abs_up);
platform->sound.source_instance_update_position(new_sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z);
new_sound_source->loop = loop;
new_sound_source->min_distance = 0.f;
new_sound_source->max_distance = 10.f;
new_sound_source->playing = play;
new_sound_source->attenuation_type = SA_INVERSE;
new_sound_source->rolloff_factor = 0.95f;
new_sound_source->volume = 1.f;
new_sound_source->type = type;
platform->sound.source_instance_loop_set(new_sound_source->source_instance, new_sound_source->loop);
platform->sound.source_instance_min_max_distance_set(new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance);
platform->sound.source_instance_attenuation_set(new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor);
platform->sound.source_instance_volume_set(new_sound_source->source_instance, new_sound_source->volume);
platform->sound.update_3d();
if(new_sound_source->playing) platform->sound.source_instance_play(new_sound_source->source_instance);
}
else
{
log_error("scene:sound_source_create", "Max sound source limit reached!");
}
return new_sound_source;
}
struct Player* scene_player_get(struct Scene* scene)
{
assert(scene);
return &scene->player;
}
void scene_entity_remove(struct Scene* scene, struct Entity* entity)
{
assert(scene && entity && entity->id >= 0);
if(!entity->active) return;
transform_destroy(entity);
entity->active = false;
entity->editor_selected = false;
entity->marked_for_deletion = false;
memset(entity->name, '\0', MAX_ENTITY_NAME_LEN);
}
void scene_light_remove(struct Scene* scene, struct Light* light)
{
assert(scene && light);
scene_entity_remove(scene, &light->base);
}
void scene_camera_remove(struct Scene* scene, struct Camera* camera)
{
assert(scene && camera);
scene_entity_remove(scene, &camera->base);
}
void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh)
{
assert(scene && mesh);
mesh->collision.on_collision = NULL;
if(mesh->collision.collision_shape) platform->physics.cs_remove(mesh->collision.collision_shape);
if(mesh->collision.rigidbody) platform->physics.body_remove(mesh->collision.rigidbody);
model_reset(&mesh->model);
scene_entity_remove(scene, &mesh->base);
}
void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source)
{
assert(scene && source);
platform->sound.source_instance_destroy(source->source_instance);
source->source_instance = 0;
scene_entity_remove(scene, &source->base);
}
struct Entity* scene_entity_find(struct Scene* scene, const char* name)
{ {
assert(entity); assert(scene && name);
struct Entity* parent = NULL; struct Entity* entity = NULL;
if(entity->transform.parent != -1)
parent = entity_get(entity->transform.parent); for(int i = 0; i < MAX_ENTITIES; i++)
return parent; {
if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0)
{
entity = &scene->entities[i];
break;
}
}
return entity;
}
struct Light* scene_light_find(struct Scene* scene, const char* name)
{
assert(scene && name);
struct Light* light = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
{
if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
light = &scene->lights[i];
break;
}
}
return light;
}
struct Camera* scene_camera_find(struct Scene* scene, const char* name)
{
assert(scene && name);
struct Camera* camera = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
{
if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
camera = &scene->cameras[i];
break;
}
}
return camera;
}
struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name)
{
assert(scene && name);
struct Static_Mesh* static_mesh = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
{
if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
static_mesh = &scene->static_meshes[i];
break;
}
}
return static_mesh;
}
struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name)
{
assert(scene && name);
struct Sound_Source* sound_source = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
{
if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
sound_source = &scene->sound_sources[i];
break;
}
}
return sound_source;
}
void* scene_find(struct Scene* scene, const char* name)
{
void* entity = NULL;
entity = scene_entity_find(scene, name);
if(entity) return entity;
entity = scene_light_find(scene, name);
if(entity) return entity;
entity = scene_camera_find(scene, name);
if(entity) return entity;
entity = scene_static_mesh_find(scene, name);
if(entity) return entity;
return entity;
}
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity)
{
assert(scene && entity);
transform_parent_set(entity, &scene->root_entity, true);
}
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent)
{
assert(scene && entity && parent);
transform_parent_set(entity, parent, true);
} }
bool scene_load(const char* filename, int directory_type) bool scene_load(const char* filename, int directory_type)
@ -179,7 +569,7 @@ bool scene_load(const char* filename, int directory_type)
bool scene_save(const char* filename, int directory_type) bool scene_save(const char* filename, int directory_type)
{ {
bool success = false; bool success = false;
FILE* scene_file = platform->file.open(directory_type, filename, "w"); /*FILE* scene_file = platform->file.open(directory_type, filename, "w");
if(!scene_file) if(!scene_file)
{ {
log_error("scene:save", "Failed to create scenefile %s for writing", filename); log_error("scene:save", "Failed to create scenefile %s for writing", filename);
@ -236,7 +626,7 @@ bool scene_save(const char* filename, int directory_type)
array_free(entities_to_write); array_free(entities_to_write);
parser_free(parser); parser_free(parser);
fclose(scene_file); fclose(scene_file);*/
return success; return success;
} }

@ -1,23 +1,71 @@
#ifndef SCENE_H #ifndef SCENE_H
#define SCENE_H #define SCENE_H
#include "../common/num_types.h" #include "entity.h"
#include "renderer.h"
struct Entity;
#define MAX_ENTITIES 1024
void scene_init(void); #define MAX_LIGHTS 30
void scene_remove(struct Entity* entity); #define MAX_CAMERAS 2
void scene_reset_parent(struct Entity* entity, struct Entity* new_parent); #define MAX_STATIC_MESHES 1024
void scene_cleanup(void); #define MAX_SOUND_SOURCES 128
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 Scene
struct Entity* scene_find(const char* name); {
struct Entity* scene_get_root(void); struct Render_Settings renderer_profile;
void scene_root_set(struct Entity* entity); struct Entity root_entity;
struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); struct Player player;
struct Entity* scene_get_parent(struct Entity* entity); struct Entity entities[MAX_ENTITIES];
bool scene_load(const char* filename, int directory_type); struct Static_Mesh static_meshes[MAX_STATIC_MESHES];
bool scene_save(const char* filename, int directory_type); struct Camera cameras[MAX_CAMERAS];
struct Light lights[MAX_LIGHTS];
struct Sound_Source sound_sources[MAX_SOUND_SOURCES];
int active_camera_index;
};
void scene_init(struct Scene* scene);
bool scene_load(struct Scene* scene, const char* filename, int dir_type);
bool scene_save(struct Scene* scene, const char* filename, int dir_type);
void scene_destroy(struct Scene* scene);
void scene_post_update(struct Scene* scene);
struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct Entity* parent);
struct Light* scene_light_create(struct Scene* scene, const char* name, struct Entity* parent, int light_type);
struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct Entity* parent, int width, int height);
struct Static_Model* scene_static_mesh_create(struct Scene* scene, const char* name, struct Entity* parent, const char* geometry_name, int material_type);
struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play);
struct Player* scene_player_get(struct Scene* scene);
void scene_entity_remove(struct Scene* scene, struct Entity* entity);
void scene_light_remove(struct Scene* scene, struct Light* light);
void scene_camera_remove(struct Scene* scene, struct Camera* camera);
void scene_static_mesh_remove(struct Scene* scene, struct Static_Mesh* mesh);
void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source);
void* scene_find(struct Scene* scene, const char* name); // Looks in all entity type arrays and returns the first one found. Result should be cast back to expected type
struct Entity* scene_entity_find(struct Scene* scene, const char* name);
struct Light* scene_light_find(struct Scene* scene, const char* name);
struct Camera* scene_camera_find(struct Scene* scene, const char* name);
struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name);
struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* name);
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent);
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent
//
//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 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);
//void scene_root_set(struct Entity* entity);
//struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name);
//struct Entity* scene_get_parent(struct Entity* entity);
//bool scene_load(const char* filename, int directory_type);
//bool scene_save(const char* filename, int directory_type);
#endif #endif

@ -5,17 +5,17 @@
#include "../common/utils.h" #include "../common/utils.h"
#include <assert.h> #include <assert.h>
void transform_create(struct Entity* entity, int parent_entity) void transform_init(struct Entity* entity, struct Entity* parent)
{ {
struct Transform* transform = &entity->transform; struct Transform* transform = &entity->transform;
vec3_fill(&transform->position, 0.f, 0.f, 0.f); vec3_fill(&transform->position, 0.f, 0.f, 0.f);
vec3_fill(&transform->scale, 1.f, 1.f, 1.f); vec3_fill(&transform->scale, 1.f, 1.f, 1.f);
quat_identity(&transform->rotation); quat_identity(&transform->rotation);
mat4_identity(&transform->trans_mat); mat4_identity(&transform->trans_mat);
transform->children = array_new(int); transform->children = array_new(struct Entity*);
transform->parent = -1; transform->parent = NULL;
if(parent_entity != -1) if(parent)
transform_parent_set(entity, entity_get(parent_entity), false); transform_parent_set(entity, parent, false);
transform_update_transmat(entity); transform_update_transmat(entity);
} }
@ -26,11 +26,11 @@ void transform_child_add(struct Entity* parent, struct Entity* child, bool updat
/* Check if already added */ /* Check if already added */
for(int i = 0; i < array_len(parent_transform->children); i++) for(int i = 0; i < array_len(parent_transform->children); i++)
if(parent_transform->children[i] == child->id) return; if(parent_transform->children[i] == child) return;
int* new_child_loc = array_grow(parent_transform->children, int); struct Entity** new_child_loc = array_grow(parent_transform->children, struct Entity*);
*new_child_loc = child->id; *new_child_loc = child;
child_transform->parent = parent->id; child_transform->parent = parent;
if(update_transmat) transform_update_transmat(child); if(update_transmat) transform_update_transmat(child);
} }
@ -40,10 +40,10 @@ bool transform_child_remove(struct Entity* parent, struct Entity* child)
struct Transform* parent_transform = &parent->transform; struct Transform* parent_transform = &parent->transform;
for(int i = 0; i < array_len(parent_transform->children); i++) for(int i = 0; i < array_len(parent_transform->children); i++)
{ {
if(parent_transform->children[i] == child->id) if(parent_transform->children[i] == child)
{ {
array_remove_at(parent_transform, i); array_remove_at(parent_transform, i);
child->transform.parent = -1; child->transform.parent = NULL;
success = true; success = true;
return success; return success;
}; };
@ -53,7 +53,7 @@ bool transform_child_remove(struct Entity* parent, struct Entity* child)
void transform_parent_set(struct Entity* child, struct Entity* parent, bool update_transmat) void transform_parent_set(struct Entity* child, struct Entity* parent, bool update_transmat)
{ {
if(child->transform.parent == -1) if(child->transform.parent == NULL)
{ {
transform_child_add(parent, child, false); transform_child_add(parent, child, false);
} }
@ -77,7 +77,7 @@ void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Spa
} }
else if(space == TS_PARENT) else if(space == TS_PARENT)
{ {
struct Entity* parent = entity_get_parent(transform->parent); struct Entity* parent = transform->parent;
if(parent) if(parent)
{ {
struct Transform* parent_tran = &parent->transform; struct Transform* parent_tran = &parent->transform;
@ -189,10 +189,9 @@ void transform_update_transmat(struct Entity* entity)
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* parent = entity_get(transform->parent); if(transform->parent)
if(parent)
{ {
struct Transform* parent_tran = &parent->transform; struct Transform* parent_tran = &transform->parent->transform;
mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat); mat4_mul(&transform->trans_mat, &transform->trans_mat, &parent_tran->trans_mat);
} }
@ -201,13 +200,10 @@ void transform_update_transmat(struct Entity* entity)
if(children > 0) if(children > 0)
{ {
for(int i = 0; i < children; i++) for(int i = 0; i < children; i++)
{ transform_update_transmat(entity->transform.children[i]);
struct Entity* child = entity_get(transform->children[i]);
transform_update_transmat(child);
}
} }
transform->is_modified = true; transform->is_modified = true;
if(entity->has_collision) entity->transform.sync_physics = true; if(entity->type == ET_STATIC_MODEL) entity->transform.sync_physics = true; // Find a better way to handle this
} }
void transform_destroy(struct Entity* entity) void transform_destroy(struct Entity* entity)
@ -218,7 +214,7 @@ void transform_destroy(struct Entity* entity)
{ {
for(int i = 0; i < children; i++) for(int i = 0; i < children; i++)
{ {
struct Entity* child = entity_get(transform->children[i]); struct Entity* child = transform->children[i];
child->marked_for_deletion = true; child->marked_for_deletion = true;
} }
} }
@ -229,7 +225,7 @@ void transform_destroy(struct Entity* entity)
vec3_fill(&transform->scale, 1.f, 1.f, 1.f); vec3_fill(&transform->scale, 1.f, 1.f, 1.f);
quat_identity(&transform->rotation); quat_identity(&transform->rotation);
mat4_identity(&transform->trans_mat); mat4_identity(&transform->trans_mat);
transform->parent = -1; transform->parent = NULL;
transform->is_modified = false; transform->is_modified = false;
} }
@ -244,7 +240,7 @@ void transform_get_absolute_position(struct Entity* entity, vec3* res)
{ {
vec3_assign(res, &entity->transform.position); vec3_assign(res, &entity->transform.position);
bool done = false; bool done = false;
struct Entity* parent = entity_get(entity->transform.parent); struct Entity* parent = entity->transform.parent;
while(!done) while(!done)
{ {
if(!parent) if(!parent)
@ -253,7 +249,7 @@ void transform_get_absolute_position(struct Entity* entity, vec3* res)
break; break;
} }
vec3_add(res, res, &parent->transform.position); vec3_add(res, res, &parent->transform.position);
parent = entity_get(parent->transform.parent); parent = parent->transform.parent;
} }
} }
@ -262,7 +258,7 @@ void transform_get_absolute_scale(struct Entity* entity, vec3* res)
struct Transform* transform = &entity->transform; struct Transform* transform = &entity->transform;
vec3_assign(res, &transform->scale); vec3_assign(res, &transform->scale);
bool done = false; bool done = false;
struct Entity* parent = entity_get(transform->parent); struct Entity* parent = transform->parent;
while(!done) while(!done)
{ {
if(!parent) if(!parent)
@ -271,7 +267,7 @@ void transform_get_absolute_scale(struct Entity* entity, vec3* res)
break; break;
} }
vec3_mul(res, res, &parent->transform.scale); vec3_mul(res, res, &parent->transform.scale);
parent = entity_get(parent->transform.parent); parent = parent->transform.parent;
} }
} }
@ -280,7 +276,7 @@ void transform_get_absolute_rot(struct Entity* entity, quat* res)
{ {
quat_assign(res, &entity->transform.rotation); quat_assign(res, &entity->transform.rotation);
bool done = false; bool done = false;
struct Entity* parent = entity_get(entity->transform.parent); struct Entity* parent = entity->transform.parent;
while(!done) while(!done)
{ {
if(!parent) if(!parent)
@ -289,6 +285,6 @@ void transform_get_absolute_rot(struct Entity* entity, quat* res)
break; break;
} }
quat_mul(res, res, &parent->transform.rotation); quat_mul(res, res, &parent->transform.rotation);
parent = entity_get(parent->transform.parent); parent = parent->transform.parent;
} }
} }

@ -8,7 +8,7 @@ enum Transform_Space { TS_LOCAL, TS_PARENT, TS_WORLD};
struct Entity; struct Entity;
void transform_create(struct Entity* entity, int parent_entity); void transform_init(struct Entity* entity, struct Entity* parent);
void transform_destroy(struct Entity* entity); void transform_destroy(struct Entity* entity);
void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Space space); void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Space space);
void transform_rotate(struct Entity* transform, void transform_rotate(struct Entity* transform,

Loading…
Cancel
Save