Implemented base and derived bounding boxes to enable picking all entity types in editor. Implemented ray mask when querying the scene

dev
Shariq Shah 6 years ago
parent b144e76367
commit bc47664c3d
  1. 53
      src/game/editor.c
  2. 49
      src/game/entity.c
  3. 17
      src/game/entity.h
  4. 6
      src/game/player.c
  5. 2
      src/game/renderer.c
  6. 152
      src/game/scene.c
  7. 20
      src/game/scene.h
  8. 35
      src/game/transform.c
  9. 1
      src/game/transform.h
  10. 10
      todo.txt

@ -172,7 +172,7 @@ void editor_init_camera(struct Editor* editor, struct Hashmap* cvars)
{
struct Camera* editor_camera = &game_state_get()->scene->cameras[CAM_EDITOR];
entity_rename(editor_camera, "Editor_Camera");
editor_camera->base.flags |= EF_ACTIVE | EF_TRANSIENT;
editor_camera->base.flags |= EF_ACTIVE | EF_TRANSIENT | EF_IGNORE_RAYCAST;
editor_camera->clear_color.x = 0.3f;
editor_camera->clear_color.y = 0.6f;
editor_camera->clear_color.z = 0.9f;
@ -250,7 +250,7 @@ void editor_render(struct Editor* editor, struct Camera * active_camera)
/* Draw bounding box for selected entity */
static vec3 vertices[24];
bv_bounding_box_vertices_get_line_visualization(&editor->selected_entity->transform.bounding_box, vertices);
bv_bounding_box_vertices_get_line_visualization(&editor->selected_entity->derived_bounding_box, vertices);
for(int i = 0; i <= 22; i += 2)
im_line(vertices[i], vertices[i + 1], (vec3) { 0.f, 0.f, 0.f }, (quat) { 0.f, 0.f, 0.f, 1.f }, editor->cursor_entity_color, 3);
@ -876,7 +876,7 @@ void editor_on_mousebutton_release(const struct Event* event)
struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y);
struct Scene* scene = game_state_get()->scene;
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray);
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray, ERM_ALL);
if(intersected_entity)
{
if(intersected_entity != editor->selected_entity)
@ -954,7 +954,7 @@ void editor_on_mousebutton_press(const struct Event* event)
int mouse_x = 0, mouse_y = 0;
platform_mouse_position_get(&mouse_x, &mouse_y);
struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y);
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray);
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray, ERM_ALL);
bool start_rotation = true;
if(intersected_entity)
@ -1159,21 +1159,7 @@ void editor_on_mousemotion(const struct Event* event)
struct Scene* scene = game_state->scene;
struct Camera* editor_camera = &scene->cameras[CAM_EDITOR];
struct Ray ray = camera_screen_coord_to_ray(editor_camera, event->mousemotion.x, event->mousemotion.y);
//struct Raycast_Result ray_result;
//scene_ray_intersect(scene, &ray, &ray_result);
//if(ray_result.num_entities_intersected > 0)
//{
// struct Entity* intersected_entity = ray_result.entities_intersected[0];
// if(intersected_entity && intersected_entity != editor->hovered_entity)
// editor->hovered_entity = intersected_entity;
//}
//else
//{
// if(editor->hovered_entity)
// editor->hovered_entity = NULL;
//}
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray);
struct Entity* intersected_entity = scene_ray_intersect_closest(scene, &ray, ERM_ALL);
if(intersected_entity)
{
if(intersected_entity != editor->hovered_entity)
@ -1877,6 +1863,35 @@ void editor_window_property_inspector(struct nk_context* context, struct Editor*
entity->transform.scale = abs_scale;
transform_update_transmat(entity);
}
if(nk_tree_push(context, NK_TREE_TAB, "Bounding Box", NK_MINIMIZED))
{
nk_layout_row_dynamic(context, row_height, 1);
nk_label(context, "Base", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_CENTERED);
nk_label(context, "Min", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_CENTERED);
if(editor_widget_v3(context, &entity->bounding_box.min, "#X", "#Y", "#Z", -FLT_MAX, FLT_MAX, 0.5f, 0.5f, row_height)) entity_update_derived_bounding_box(entity);
nk_layout_row_dynamic(context, row_height, 1);
nk_label(context, "Max", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_CENTERED);
if(editor_widget_v3(context, &entity->bounding_box.max, "#X", "#Y", "#Z", -FLT_MAX, FLT_MAX, 0.5f, 0.5f, row_height)) entity_update_derived_bounding_box(entity);
struct Bounding_Box* derived_box = &entity->derived_bounding_box;
nk_layout_row_dynamic(context, row_height, 1);
nk_label(context, "Derived", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_CENTERED);
nk_layout_row_dynamic(context, row_height, 2);
nk_label(context, "Min", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_LEFT);
nk_labelf(context, NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_RIGHT, "%.1f %.1f %.1f", derived_box->min.x, derived_box->min.y, derived_box->min.z);
nk_label(context, "Max", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_LEFT);
nk_labelf(context, NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_RIGHT, "%.1f %.1f %.1f", derived_box->max.x, derived_box->max.y, derived_box->max.z);
nk_layout_row_dynamic(context, row_height, 1);
if(nk_button_label(context, "Reset to Default"))
entity_bounding_box_reset(entity, true);
nk_tree_pop(context);
}
}
/* Light */

@ -24,6 +24,7 @@
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#include <float.h>
#define MAX_ENTITY_PROP_NAME_LEN 128
#define MAX_ENTITY_PROP_LEN 256
@ -38,19 +39,65 @@ void entity_init(struct Entity* entity, const char* name, struct Entity* parent)
entity->type = ET_DEFAULT;
entity->archetype_index = -1;
entity->flags = EF_ACTIVE;
entity_bounding_box_reset(entity, false);
entity->derived_bounding_box.min = (vec3){ -0.5f, -0.5f, -0.5f };
entity->derived_bounding_box.max = (vec3){ 0.5f, 0.5f, 0.5f };
transform_init(entity, parent);
}
void entity_reset(struct Entity * entity, int id)
void entity_reset(struct Entity* entity, int id)
{
assert(entity);
entity->id = id;
entity->type = ET_DEFAULT;
entity->archetype_index = -1;
entity->flags = EF_NONE;
entity_bounding_box_reset(entity, false);
entity->derived_bounding_box.min = (vec3){ -0.5f, -0.5f, -0.5f };
entity->derived_bounding_box.max = (vec3){ 0.5f, 0.5f, 0.5f };
memset(entity->name, '\0', MAX_ENTITY_NAME_LEN);
}
void entity_update_derived_bounding_box(struct Entity* entity)
{
struct Bounding_Box* derived_box = &entity->derived_bounding_box;
vec3_fill(&derived_box->min, FLT_MAX, FLT_MAX, FLT_MAX);
vec3_fill(&derived_box->max, -FLT_MAX, -FLT_MAX, -FLT_MAX);
vec3 box_vertices[8];
bv_bounding_box_vertices_get(&entity->bounding_box, box_vertices);
for(int i = 0; i < 8; i++)
{
vec3 transformed_vertex = { 0.f, 0.f, 0.f };
vec3_mul_mat4(&transformed_vertex, &box_vertices[i], &entity->transform.trans_mat);
if(transformed_vertex.x < derived_box->min.x) derived_box->min.x = transformed_vertex.x;
if(transformed_vertex.y < derived_box->min.y) derived_box->min.y = transformed_vertex.y;
if(transformed_vertex.z < derived_box->min.z) derived_box->min.z = transformed_vertex.z;
if(transformed_vertex.x > derived_box->max.x) derived_box->max.x = transformed_vertex.x;
if(transformed_vertex.y > derived_box->max.y) derived_box->max.y = transformed_vertex.y;
if(transformed_vertex.z > derived_box->max.z) derived_box->max.z = transformed_vertex.z;
}
}
void entity_bounding_box_reset(struct Entity* entity, bool update_derived)
{
if(entity->type == ET_STATIC_MESH)
{
struct Static_Mesh* mesh = (struct Static_Mesh*)entity;
struct Geometry* geom = geom_get(mesh->model.geometry_index);
vec3_assign(&entity->bounding_box.min, &geom->bounding_box.min);
vec3_assign(&entity->bounding_box.max, &geom->bounding_box.max);
}
else
{
vec3_fill(&entity->bounding_box.min, -0.5f, -0.5f, -0.5f);
vec3_fill(&entity->bounding_box.max, 0.5f, 0.5f, 0.5f);
}
if(update_derived) entity_update_derived_bounding_box(entity);
}
bool entity_write(struct Entity* entity, struct Parser_Object* object, bool write_transform)
{
if(!object)

@ -58,6 +58,18 @@ enum Entity_Flags
EF_IGNORE_RAYCAST = 1 << 6
};
enum Entity_Ray_Mask
{
ERM_NONE = 0,
ERM_DEFAULT = 1 << 0,
ERM_PLAYER = 1 << 1,
ERM_CAMERA = 1 << 2,
ERM_LIGHT = 1 << 3,
ERM_STATIC_MESH = 1 << 4,
ERM_SOUND_SOURCE = 1 << 5,
ERM_ALL = ERM_DEFAULT | ERM_PLAYER | ERM_CAMERA | ERM_LIGHT | ERM_STATIC_MESH | ERM_SOUND_SOURCE
};
struct Transform
{
vec3 position;
@ -66,7 +78,6 @@ struct Transform
mat4 trans_mat;
bool is_modified;
bool sync_physics;
struct Bounding_Box bounding_box;
struct Entity* parent;
struct Entity** children;
};
@ -78,6 +89,8 @@ struct Entity
int archetype_index;
uchar flags;
char name[MAX_ENTITY_NAME_LEN];
struct Bounding_Box bounding_box;
struct Bounding_Box derived_bounding_box;
struct Transform transform;
};
@ -176,5 +189,7 @@ void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B)
void entity_rigidbody_set(struct Entity* entity, struct Collision* collision, Rigidbody body);
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
void entity_rename(struct Entity* entity, const char* new_name);
void entity_update_derived_bounding_box(struct Entity* entity);
void entity_bounding_box_reset(struct Entity* entity, bool update_derived);
#endif

@ -141,15 +141,15 @@ void player_update(struct Player* player, struct Scene* scene, float dt)
log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z);
struct Raycast_Result ray_result;
scene_ray_intersect(scene, &ray, &ray_result);
scene_ray_intersect(scene, &ray, &ray_result, ERM_ALL);
}
vec3 mesh_abs = { 0.f, 0.f, 0.f };
transform_get_absolute_position(player->mesh, &mesh_abs);
debug_vars_show_vec3("Player Position", &player->base.transform.position);
debug_vars_show_vec3("Mesh Position", &mesh_abs);
debug_vars_show_vec3("Min", &player->mesh->base.transform.bounding_box.min);
debug_vars_show_vec3("Max", &player->mesh->base.transform.bounding_box.max);
debug_vars_show_vec3("Min", &player->mesh->base.derived_bounding_box.min);
debug_vars_show_vec3("Max", &player->mesh->base.derived_bounding_box.max);
struct Geometry* geom = geom_get(player->mesh->model.geometry_index);
debug_vars_show_vec3("Geom Min", &geom->bounding_box.min);
debug_vars_show_vec3("Geom Max", &geom->bounding_box.max);

@ -257,7 +257,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene)
/* Check if model is in frustum */
int intersection = bv_intersect_frustum_box(&camera->frustum, &mesh->base.transform.bounding_box);
int intersection = bv_intersect_frustum_box(&camera->frustum, &mesh->base.derived_bounding_box);
if(intersection == IT_INSIDE || intersection == IT_INTERSECT)
{
renderer->num_indices += array_len(geometry->indices);

@ -548,9 +548,9 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* na
entity_init(&new_static_mesh->base, name, parent ? parent : &scene->root_entity);
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);
vec3_assign(&new_static_mesh->base.bounding_box.min, &geom_get(new_static_mesh->model.geometry_index)->bounding_box.min);
vec3_assign(&new_static_mesh->base.bounding_box.max, &geom_get(new_static_mesh->model.geometry_index)->bounding_box.max);
entity_update_derived_bounding_box(new_static_mesh);
}
else
{
@ -804,54 +804,144 @@ void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct
transform_parent_set(entity, parent, true);
}
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results)
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results, int ray_mask)
{
assert(out_results);
memset(&out_results[0], '\0', sizeof(struct Entity*) * MAX_RAYCAST_ENTITIES_INTERSECT);
out_results->num_entities_intersected = 0;
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < ET_MAX; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!(mesh->base.flags & EF_ACTIVE) || (mesh->base.flags & EF_IGNORE_RAYCAST)) continue;
vec3 abs_pos = { 0.f, 0.f, 0.f };
vec3 abs_scale = { 1.f, 1.f, 1.f };
transform_get_absolute_position(mesh, &abs_pos);
transform_get_absolute_scale(mesh, &abs_scale);
int max_length = 0;
size_t stride = 0;
struct Entity* entity = NULL;
struct Geometry* geometry = geom_get(mesh->model.geometry_index);
if(bv_intersect_bounding_box_ray(&mesh->base.transform.bounding_box, ray) == IT_INTERSECT)
switch(i)
{
out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base;
case ET_DEFAULT:
if(!(ray_mask & ERM_DEFAULT)) continue;
max_length = MAX_ENTITIES;
entity = &scene->entities[0];
stride = sizeof(struct Entity);
break;
case ET_LIGHT:
if(!(ray_mask & ERM_LIGHT)) continue;
max_length = MAX_LIGHTS;
entity = &scene->lights[0].base;
stride = sizeof(struct Light);
break;
case ET_STATIC_MESH:
if(!(ray_mask & ERM_STATIC_MESH)) continue;
max_length = MAX_STATIC_MESHES;
entity = &scene->static_meshes[0].base;
stride = sizeof(struct Static_Mesh);
break;
case ET_CAMERA:
if(!(ray_mask & ERM_CAMERA)) continue;
max_length = MAX_CAMERAS;
entity = &scene->cameras[0].base;
stride = sizeof(struct Camera);
break;
case ET_SOUND_SOURCE:
if(!(ray_mask & ERM_SOUND_SOURCE)) continue;
max_length = MAX_SOUND_SOURCES;
entity = &scene->sound_sources[0].base;
stride = sizeof(struct Sound_Source);
break;
case ET_PLAYER:
if(!(ray_mask & ERM_PLAYER)) continue;
max_length = 1;
entity = &scene->player;
stride = sizeof(struct Player);
break;
default: continue;
}
size_t count = 0;
while(count < max_length)
{
if(entity->flags & EF_ACTIVE && !(entity->flags & EF_IGNORE_RAYCAST))
{
int result = bv_intersect_bounding_box_ray(&entity->derived_bounding_box, ray);
if(result == IT_INTERSECT || result == IT_INSIDE)
{
out_results->entities_intersected[out_results->num_entities_intersected] = &entity;
out_results->num_entities_intersected++;
}
}
count++;
((char*)entity) += stride;
}
}
}
struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray)
struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray, int ray_mask)
{
struct Entity* closest = NULL;
float current_closest = 0.f;
for(int i = 0; i < MAX_STATIC_MESHES; i++)
for(int i = 0; i < ET_MAX; i++)
{
struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!(mesh->base.flags & EF_ACTIVE) || (mesh->base.flags & EF_IGNORE_RAYCAST)) continue;
vec3 abs_pos = { 0.f, 0.f, 0.f };
vec3 abs_scale = { 1.f, 1.f, 1.f };
transform_get_absolute_position(mesh, &abs_pos);
transform_get_absolute_scale(mesh, &abs_scale);
int max_length = 0;
size_t stride = 0;
struct Entity* entity = NULL;
switch(i)
{
case ET_DEFAULT:
if(!(ray_mask & ERM_DEFAULT)) continue;
max_length = MAX_ENTITIES;
entity = &scene->entities[0];
stride = sizeof(struct Entity);
break;
case ET_LIGHT:
if(!(ray_mask & ERM_LIGHT)) continue;
max_length = MAX_LIGHTS;
entity = &scene->lights[0].base;
stride = sizeof(struct Light);
break;
case ET_STATIC_MESH:
if(!(ray_mask & ERM_STATIC_MESH)) continue;
max_length = MAX_STATIC_MESHES;
entity = &scene->static_meshes[0].base;
stride = sizeof(struct Static_Mesh);
break;
case ET_CAMERA:
if(!(ray_mask & ERM_CAMERA)) continue;
max_length = MAX_CAMERAS;
entity = &scene->cameras[0].base;
stride = sizeof(struct Camera);
break;
case ET_SOUND_SOURCE:
if(!(ray_mask & ERM_SOUND_SOURCE)) continue;
max_length = MAX_SOUND_SOURCES;
entity = &scene->sound_sources[0].base;
stride = sizeof(struct Sound_Source);
break;
case ET_PLAYER:
if(!(ray_mask & ERM_PLAYER)) continue;
max_length = 1;
entity = &scene->player;
stride = sizeof(struct Player);
break;
default: continue;
}
struct Geometry* geometry = geom_get(mesh->model.geometry_index);
float distance = bv_distance_ray_bounding_box(ray, &mesh->base.transform.bounding_box);
size_t count = 0;
while(count < max_length)
{
if(entity->flags & EF_ACTIVE && !(entity->flags & EF_IGNORE_RAYCAST))
{
float distance = bv_distance_ray_bounding_box(ray, &entity->derived_bounding_box);
if(distance != INFINITY && distance >= 0.f)
{
bool assign = false;
if(closest == NULL)
assign = true;
else if(distance > current_closest &&
bv_intersect_bounding_box_ray(&mesh->base.transform.bounding_box, ray) == IT_INSIDE &&
bv_intersect_bounding_boxes(&mesh->base.transform.bounding_box, &closest->transform.bounding_box) != IT_INSIDE)
else if(distance > current_closest&&
bv_intersect_bounding_box_ray(&entity->derived_bounding_box, ray) == IT_INSIDE &&
bv_intersect_bounding_boxes(&entity->derived_bounding_box, &closest->derived_bounding_box) != IT_INSIDE)
assign = true;
else if(distance < current_closest)
assign = true;
@ -859,10 +949,16 @@ struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray)
if(assign)
{
current_closest = distance;
closest = &mesh->base;
closest = entity;
}
}
}
count++;
((char*)entity) += stride;
}
}
return closest;
}

@ -60,24 +60,8 @@ void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent
int scene_entity_archetype_add(struct Scene* scene, const char* filename);
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results);
struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray);
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results, int ray_mask);
struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray, int ray_mask);
float scene_entity_distance(struct Scene* scene, struct Entity* entity1, struct Entity* entity2);
//
//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

@ -18,8 +18,6 @@ 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)
@ -27,37 +25,6 @@ void transform_init(struct Entity* entity, struct Entity* parent)
transform_update_transmat(entity);
}
void transform_update_bounding_box(struct Entity* entity)
{
struct Bounding_Box* box = &entity->transform.bounding_box;
vec3_fill(&box->min, FLT_MAX, FLT_MAX, FLT_MAX);
vec3_fill(&box->max, -FLT_MAX, -FLT_MAX, -FLT_MAX);
vec3 box_vertices[8];
if(entity->type == ET_STATIC_MESH)
{
struct Static_Mesh* mesh = (struct Static_Mesh*)entity;
struct Geometry* geometry = geom_get(mesh->model.geometry_index);
bv_bounding_box_vertices_get(&geometry->bounding_box, box_vertices);
}
else
{
bv_bounding_box_vertices_get(box, box_vertices);
}
for(int i = 0; i < 8; i++)
{
vec3 transformed_vertex = { 0.f, 0.f, 0.f };
vec3_mul_mat4(&transformed_vertex, &box_vertices[i], &entity->transform.trans_mat);
if(transformed_vertex.x < box->min.x) box->min.x = transformed_vertex.x;
if(transformed_vertex.y < box->min.y) box->min.y = transformed_vertex.y;
if(transformed_vertex.z < box->min.z) box->min.z = transformed_vertex.z;
if(transformed_vertex.x > box->max.x) box->max.x = transformed_vertex.x;
if(transformed_vertex.y > box->max.y) box->max.y = transformed_vertex.y;
if(transformed_vertex.z > box->max.z) box->max.z = transformed_vertex.z;
}
}
void transform_child_add(struct Entity* parent, struct Entity* child, bool update_transmat)
{
struct Transform* parent_transform = &parent->transform;
@ -262,7 +229,7 @@ void transform_update_transmat(struct Entity* entity)
mat4_mul(&transform->trans_mat, &parent_tran->trans_mat, &transform->trans_mat);
}
transform_update_bounding_box(entity);
entity_update_derived_bounding_box(entity);
/* Update all children */
int children = array_len(transform->children);

@ -34,6 +34,5 @@ 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

@ -1,8 +1,7 @@
Todo:
- Fix camera frustum creation/update
- Imlpement picking entities of all types in editor
- Save/Load base bounding boxes for entity types other than static mesh
- Determine whether we should enable or disble picking when a tool is active within an editor
? Only show bounding box for hovered entity
? Only show bounding box for hovered entity instead of wireframe mesh
- Fix crash where if an entity is hoverd in editor and deleted, the game crashes because the hovered variable in editor doesn't know that the entity was deleted
? Write entity flags to scene file or when saving entity to file?
? Add scene init/de-init function hashmap that maps a function that should be called when scene is loaded and unloaded. Save this to file for every scene or map functions based on the name of the scene?
@ -139,6 +138,7 @@ Bugs:
- Fix crash if player's mesh is deleted in editor
- Fix camera not rotating if the cursor overlaps any ui element
- Fix hierarchichal transformations in the editor when the entity being transformed is a child entity of another entity
- Fix camera frustum creation/update
Done:
* Input
@ -397,4 +397,6 @@ Done:
* Save transformation information when saving entity archetypes
* Implement bounding box visualization
* Fixed rotation gizmo for scaled meshes
* Implement ray-bounding box picking and determine whether that is enough for our needs or do we need to implement OBB
* Implemented ray-bounding box picking and determine whether that is enough for our needs or do we need to implement OBB
* Implemented base and derived bounding boxes for all entity types
* Imlpemented picking entities of all types in editor
Loading…
Cancel
Save