diff --git a/src/game/bounding_volumes.c b/src/game/bounding_volumes.c index e37495f..2728d35 100755 --- a/src/game/bounding_volumes.c +++ b/src/game/bounding_volumes.c @@ -2,6 +2,32 @@ #include +int bv_intersect_frustum_box_(vec4* frustum, struct Bounding_Box* box) +{ + vec3 size, center, half_ext, half_size; + vec3_fill(&size, 0.f, 0.f, 0.f); + vec3_fill(¢er, 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_sub(&size, &box->max, &box->min); + vec3_add(¢er, &box->max, &box->min); + vec3_scale(¢er, ¢er, 0.5f); + vec3_assign(&half_ext, &size); + vec3_scale(&half_size, &size, 0.5f); + for(int i = 0; i < 6; i++) + { + vec3 normal = {frustum[i].x, frustum[i].y, frustum[i].z}; + float distance = frustum[i].w; + float d = vec3_dot(&normal, ¢er); + vec3 abs_normal = {fabsf(normal.x), fabsf(normal.y), fabsf(normal.z)}; + float r = vec3_dot(&half_ext, &abs_normal); + if(d + r < -distance) + return IT_OUTSIDE; + } + return IT_INSIDE; +} + int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale) { vec3 min, max, size, center, half_ext, half_size; diff --git a/src/game/bounding_volumes.h b/src/game/bounding_volumes.h index b9380e6..ed6d5ed 100755 --- a/src/game/bounding_volumes.h +++ b/src/game/bounding_volumes.h @@ -50,6 +50,7 @@ struct Raycast_Result }; int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* box_abs_position, vec3* box_abs_scale); +int bv_intersect_frustum_box_(vec4* frustum, struct Bounding_Box* box); int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, vec3* sphere_abs_pos, vec3* sphere_abs_scale); bool bv_intersect_frustum_point(vec4* frustum, const vec3* point); //bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray); diff --git a/src/game/entity.h b/src/game/entity.h index a059f6f..fdf5fe7 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -5,6 +5,7 @@ #include "../common/num_types.h" #include "../system/physics.h" #include "../system/sound.h" +#include "bounding_volumes.h" #include "material.h" #define MAX_ENTITY_NAME_LEN 128 @@ -59,14 +60,15 @@ enum Entity_Flags struct Transform { - vec3 position; - vec3 scale; - quat rotation; - mat4 trans_mat; - bool is_modified; - bool sync_physics; - struct Entity* parent; - struct Entity** children; + vec3 position; + vec3 scale; + quat rotation; + mat4 trans_mat; + bool is_modified; + bool sync_physics; + struct Bounding_Box bounding_box; + struct Entity* parent; + struct Entity** children; }; struct Entity diff --git a/src/game/geometry.c b/src/game/geometry.c index 9193431..285ad58 100755 --- a/src/game/geometry.c +++ b/src/game/geometry.c @@ -373,14 +373,14 @@ int geom_render_in_frustum(int index, int intersection = bv_intersect_frustum_sphere(frustum, &geometry->bounding_sphere, &abs_pos, &abs_scale); if(intersection == IT_INTERSECT || intersection == IT_INSIDE) { - geom_render(index, draw_mode); - indices_rendered = array_len(geometry->indices); - /* intersection = bv_intersect_frustum_box(frustum, &geometry->bounding_box, entity); */ - /* if(intersection == IT_INTERSECT || intersection == IT_INSIDE) */ - /* { */ - /* geom_render(index, draw_mode); */ - /* rendered = array_len(geometry->indices); */ - /* } */ + //geom_render(index, draw_mode); + //indices_rendered = array_len(geometry->indices); + intersection = bv_intersect_frustum_box(frustum, &geometry->bounding_box, &abs_pos, &abs_scale); + if(intersection == IT_INTERSECT || intersection == IT_INSIDE) + { + geom_render(index, draw_mode); + indices_rendered = array_len(geometry->indices); + } } return indices_rendered; } diff --git a/src/game/renderer.c b/src/game/renderer.c index 20f0947..e699a25 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -267,8 +267,18 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) } else { - renderer->num_indices += array_len(geometry->indices); - renderer->num_rendered++; + //intersection = bv_intersect_frustum_box(&camera->frustum, &geometry->bounding_box, &abs_pos, &abs_scale); + intersection = bv_intersect_frustum_box_(&camera->frustum, &mesh->base.transform.bounding_box); + if(intersection == IT_INSIDE || intersection == IT_INTERSECT) + { + renderer->num_indices += array_len(geometry->indices); + renderer->num_rendered++; + } + else + { + renderer->num_culled++; + continue; + } } /* set material params for the model */ diff --git a/src/game/scene.c b/src/game/scene.c index a224804..0a559fa 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -548,6 +548,8 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* na new_static_mesh->base.type = ET_STATIC_MESH; model_init(&new_static_mesh->model, new_static_mesh, geometry_name, material_type); // TODO: handle creating collision mesh for the model at creation + vec3_assign(&new_static_mesh->base.transform.bounding_box.min, &geom_get(new_static_mesh->model.geometry_index)->bounding_box.min); + vec3_assign(&new_static_mesh->base.transform.bounding_box.max, &geom_get(new_static_mesh->model.geometry_index)->bounding_box.max); } else { diff --git a/src/game/transform.c b/src/game/transform.c index 4834bb3..2a91f46 100755 --- a/src/game/transform.c +++ b/src/game/transform.c @@ -14,6 +14,8 @@ void transform_init(struct Entity* entity, struct Entity* parent) vec3_fill(&transform->scale, 1.f, 1.f, 1.f); quat_identity(&transform->rotation); mat4_identity(&transform->trans_mat); + transform->bounding_box.min = (vec3){ 0.f, 0.f, 0.f }; + transform->bounding_box.max = (vec3){ 1.f, 1.f, 1.f }; transform->children = array_new(struct Entity*); transform->parent = NULL; if(parent) @@ -21,6 +23,33 @@ void transform_init(struct Entity* entity, struct Entity* parent) transform_update_transmat(entity); } +void transform_update_bounding_box(struct Entity* entity) +{ + struct Bounding_Box* bounding_box = &entity->transform.bounding_box; + vec3 transformed_points[8]; + vec3_fill(&transformed_points[0], bounding_box->min.x, bounding_box->min.y, bounding_box->min.z); + vec3_fill(&transformed_points[1], bounding_box->max.x, bounding_box->min.y, bounding_box->min.z); + vec3_fill(&transformed_points[2], bounding_box->min.x, bounding_box->max.y, bounding_box->min.z); + vec3_fill(&transformed_points[3], bounding_box->min.x, bounding_box->min.y, bounding_box->max.z); + + vec3_fill(&transformed_points[4], bounding_box->max.x, bounding_box->max.y, bounding_box->max.z); + vec3_fill(&transformed_points[5], bounding_box->min.x, bounding_box->max.y, bounding_box->max.z); + vec3_fill(&transformed_points[6], bounding_box->max.x, bounding_box->min.y, bounding_box->max.z); + vec3_fill(&transformed_points[7], bounding_box->max.x, bounding_box->max.y, bounding_box->min.z); + + for(int i = 0; i < 8; i++) + { + vec3_mul_mat4(&transformed_points[i], &transformed_points[i], &entity->transform.trans_mat); + if(transformed_points[i].x < bounding_box->min.x) bounding_box->min.x = transformed_points[i].x; + if(transformed_points[i].y < bounding_box->min.y) bounding_box->min.y = transformed_points[i].y; + if(transformed_points[i].z < bounding_box->min.z) bounding_box->min.z = transformed_points[i].z; + + if(transformed_points[i].x > bounding_box->max.x) bounding_box->max.x = transformed_points[i].x; + if(transformed_points[i].y > bounding_box->max.y) bounding_box->max.y = transformed_points[i].y; + if(transformed_points[i].z > bounding_box->max.z) bounding_box->max.z = transformed_points[i].z; + } +} + void transform_child_add(struct Entity* parent, struct Entity* child, bool update_transmat) { struct Transform* parent_transform = &parent->transform; @@ -225,6 +254,8 @@ void transform_update_transmat(struct Entity* entity) mat4_mul(&transform->trans_mat, &parent_tran->trans_mat, &transform->trans_mat); } + transform_update_bounding_box(entity); + /* Update all children */ int children = array_len(transform->children); if(children > 0) diff --git a/src/game/transform.h b/src/game/transform.h index 8b53e72..95f8d0a 100755 --- a/src/game/transform.h +++ b/src/game/transform.h @@ -34,5 +34,6 @@ void transform_child_add(struct Entity* entity, struct Entity* child, bool updat bool transform_child_remove(struct Entity* entity, struct Entity* child); void transform_parent_set(struct Entity* entity, struct Entity* parent, bool update_transmat); void transform_copy(struct Entity* copy_to, struct Entity* copy_from, bool copy_parent); +void transform_update_bounding_box(struct Entity* entity); #endif diff --git a/todo.txt b/todo.txt index 12fc079..870915c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,11 @@ Todo: + - Implement bounding box visualization + - Implement ray-bounding box picking and determine whether that is enough for our needs or do we need to implement OBB - Command to create a placeholder entity of a particular type in a file - Re-write/Overhaul bounding volumes and ray intersection - Reduce the opacity of wireframe around selected entity in editor + - Release mouse when window loses focus and limit fps - Allow picking and selecting other entity types in editor i.e. the ones that don't have meshes - ? Save transformation information when saving entity archetypes ? When saving a scene entity entry, save the changed properties as well, that way when the scene is loaded, we load the base properties from archetype and the ones we changed per entry are saved when we saved the entity this will prevent us from having needless amount of entities with only minor changes from one another ? Split up material declarations into their own separate files. Materials have a base material like Blinn or Unshaded and in the file we save an instance with modified properties. @@ -396,4 +398,5 @@ Done: * Write player camera clear colour when saving scene * Add uv tiling parameter to materials that can be serialized along with entities * Implement resetting complete transform or just rotation, translation - or scale for selected entity \ No newline at end of file + or scale for selected entity + * Save transformation information when saving entity archetypes \ No newline at end of file