Added flag to allow entities to ignore raycasts and fixed flickering when hovering over entities in editor

dev
Shariq Shah 6 years ago
parent c874dcf598
commit 115873b586
  1. 8
      src/common/linmath.c
  2. 31
      src/game/bounding_volumes.c
  3. 3
      src/game/bounding_volumes.h
  4. 17
      src/game/editor.c
  5. 3
      src/game/entity.h
  6. 3
      src/game/renderer.c
  7. 115
      src/game/scene.c
  8. 5
      todo.txt

@ -79,11 +79,11 @@ void vec3_add(vec3* res, const vec3* v1, const vec3* v3)
res->z = v1->z + v3->z; res->z = v1->z + v3->z;
} }
void vec3_sub(vec3* res, const vec3* v1, const vec3* v3) void vec3_sub(vec3* res, const vec3* v1, const vec3* v2)
{ {
res->x = v1->x - v3->x; res->x = v1->x - v2->x;
res->y = v1->y - v3->y; res->y = v1->y - v2->y;
res->z = v1->z - v3->z; res->z = v1->z - v2->z;
} }
void vec3_assign(vec3* res, const vec3* val) void vec3_assign(vec3* res, const vec3* val)

@ -82,21 +82,24 @@ bool bv_intersect_frustum_point(vec4* frustum, const vec3* point)
return success; return success;
} }
bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray) int bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, vec3* sphere_abs_scale, struct Ray* ray)
{ {
int intersection_type = IT_OUTSIDE;
vec3 center = {0.f}; vec3 center = {0.f, 0.f, 0.f};
vec3_add(&center, &sphere->center, sphere_abs_position); vec3_add(&center, &sphere->center, sphere_abs_position);
float squared_radius = sphere->radius * sphere->radius; float radius = sphere->radius * sphere_abs_scale->x;
//float squared_radius = sphere->radius * sphere->radius;
float squared_radius = radius * radius;
vec3 centered_origin; vec3 centered_origin;
vec3_sub(&centered_origin, &ray->origin, &center); vec3_sub(&centered_origin, &ray->origin, &center);
//vec3_sub(&centered_origin, &center, &ray->origin);
float centered_origin_len_sqrd = vec3_len(&centered_origin); float centered_origin_len_sqrd = vec3_len(&centered_origin);
centered_origin_len_sqrd *= centered_origin_len_sqrd; centered_origin_len_sqrd *= centered_origin_len_sqrd;
//Check if ray originates inside the sphere //Check if ray originates inside the sphere
if(centered_origin_len_sqrd <= squared_radius) if(centered_origin_len_sqrd <= squared_radius)
return true; return IT_INSIDE;
// Calculate the intersection by quatratic equation' // Calculate the intersection by quatratic equation'
float a = vec3_dot(&ray->direction, &ray->direction); float a = vec3_dot(&ray->direction, &ray->direction);
@ -106,24 +109,24 @@ bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_po
//No solution //No solution
if(d < 0.f) if(d < 0.f)
return false; return IT_OUTSIDE;
//Get the near solution //Get the near solution
float d_sqrt = sqrtf(d); float d_sqrt = sqrtf(d);
float dist = (-b - d_sqrt) / (2.f * a); float dist = (-b - d_sqrt) / (2.f * a);
if(dist >= 0.f) if(dist >= 0.f)
return true; return IT_INTERSECT;
else else
return true; return IT_OUTSIDE;
//float tca = vec3_dot(&centered_origin, &ray->direction); //float tca = vec3_dot(&centered_origin, &ray->direction);
//if(tca < 0.0) return false; //if(tca < 0.0) return IT_OUTSIDE;
//float L_dot = vec3_dot(&centered_origin, &centered_origin); //float L_dot = vec3_dot(&centered_origin, &centered_origin);
//float d2 = L_dot - (tca); //float d2 = L_dot - (tca * tca);
//float radius_sqr = sphere->radius * sphere->radius; //float radius_sqr = radius * radius;
//if (d2 > radius_sqr) return false; //if (d2 > radius_sqr) return IT_OUTSIDE;
//float thc = sqrtf(radius_sqr - d2); //float thc = sqrtf(radius_sqr - d2);
//float t0 = tca - thc; //float t0 = tca - thc;
//float t1 = tca + thc; //float t1 = tca + thc;
@ -138,10 +141,10 @@ bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_po
//if(t0 < 0) //if(t0 < 0)
//{ //{
// t0 = t1; // t0 = t1;
// if(t0 < 0) return false; // if(t0 < 0) return IT_OUTSIDE;
//} //}
//return true; //return IT_INTERSECT;
} }
float bv_distance_ray_plane(struct Ray* ray, Plane* plane) float bv_distance_ray_plane(struct Ray* ray, Plane* plane)

@ -52,7 +52,8 @@ 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, vec3* box_abs_position, vec3* box_abs_scale);
int bv_intersect_frustum_sphere(vec4* frustum, struct Bounding_Sphere* sphere, vec3* sphere_abs_pos, vec3* sphere_abs_scale); 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_frustum_point(vec4* frustum, const vec3* point);
bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray); //bool bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, struct Ray* ray);
int bv_intersect_sphere_ray(struct Bounding_Sphere* sphere, vec3* sphere_abs_position, vec3* sphere_abs_scale, struct Ray* ray);
float bv_distance_ray_plane(struct Ray* ray, Plane* plane); float bv_distance_ray_plane(struct Ray* ray, Plane* plane);
#endif #endif

@ -161,7 +161,7 @@ void editor_init(struct Editor* editor)
void editor_init_entities(struct Editor* editor) void editor_init_entities(struct Editor* editor)
{ {
editor->cursor_entity = scene_static_mesh_create(game_state_get()->scene, "EDITOR_SELECTED_ENTITY_WIREFRAME", NULL, "sphere.symbres", MAT_UNSHADED); editor->cursor_entity = scene_static_mesh_create(game_state_get()->scene, "EDITOR_SELECTED_ENTITY_WIREFRAME", NULL, "sphere.symbres", MAT_UNSHADED);
editor->cursor_entity->base.flags |= EF_TRANSIENT | EF_SKIP_RENDER | EF_HIDE_IN_EDITOR_SCENE_HIERARCHY; editor->cursor_entity->base.flags |= EF_TRANSIENT | EF_SKIP_RENDER | EF_HIDE_IN_EDITOR_SCENE_HIERARCHY | EF_IGNORE_RAYCAST;
} }
void editor_init_camera(struct Editor* editor, struct Hashmap* cvars) void editor_init_camera(struct Editor* editor, struct Hashmap* cvars)
@ -989,8 +989,10 @@ void editor_on_mousemotion(const struct Event* event)
if(editor->selected_entity && editor->current_axis < EDITOR_AXIS_XZ) if(editor->selected_entity && editor->current_axis < EDITOR_AXIS_XZ)
{ {
struct Camera* editor_camera = &game_state->scene->cameras[CAM_EDITOR]; struct Camera* editor_camera = &game_state->scene->cameras[CAM_EDITOR];
vec3 position = { 0.f }; vec3 position = { 0.f, 0.f, 0.f };
vec3 scale = {1.f, 1.f, 1.f};
transform_get_absolute_position(editor->selected_entity, &position); transform_get_absolute_position(editor->selected_entity, &position);
transform_get_absolute_scale(editor->selected_entity, &scale);
struct Ray cam_ray; struct Ray cam_ray;
cam_ray = camera_screen_coord_to_ray(editor_camera, event->mousemotion.x, event->mousemotion.y); cam_ray = camera_screen_coord_to_ray(editor_camera, event->mousemotion.x, event->mousemotion.y);
@ -1005,7 +1007,7 @@ void editor_on_mousemotion(const struct Event* event)
//vec3_assign(&gizmo_sphere.center, &position); //vec3_assign(&gizmo_sphere.center, &position);
gizmo_sphere.center = (vec3) { 0.f, 0.f, 0.f }; gizmo_sphere.center = (vec3) { 0.f, 0.f, 0.f };
gizmo_sphere.radius = editor->tool_rotate_arc_radius; gizmo_sphere.radius = editor->tool_rotate_arc_radius;
if(bv_intersect_sphere_ray(&gizmo_sphere, &position, &cam_ray)) if(bv_intersect_sphere_ray(&gizmo_sphere, &position, &scale, &cam_ray) == IT_INTERSECT)
{ {
//Plane ground_plane; //Plane ground_plane;
//plane_init(&ground_plane, &UNIT_X, &position); //plane_init(&ground_plane, &UNIT_X, &position);
@ -1099,17 +1101,8 @@ void editor_on_mousemotion(const struct Event* event)
if(ray_result.num_entities_intersected > 0) if(ray_result.num_entities_intersected > 0)
{ {
struct Entity* intersected_entity = ray_result.entities_intersected[0]; struct Entity* intersected_entity = ray_result.entities_intersected[0];
if(intersected_entity == editor->cursor_entity)
{
if(ray_result.num_entities_intersected > 1)
intersected_entity = ray_result.entities_intersected[1];
else
intersected_entity = NULL;
}
if(intersected_entity && intersected_entity != editor->hovered_entity) if(intersected_entity && intersected_entity != editor->hovered_entity)
editor->hovered_entity = intersected_entity; editor->hovered_entity = intersected_entity;
else if(editor->hovered_entity)
editor->hovered_entity = NULL;
} }
else else
{ {

@ -53,7 +53,8 @@ enum Entity_Flags
EF_MARKED_FOR_DELETION = 1 << 2, EF_MARKED_FOR_DELETION = 1 << 2,
EF_TRANSIENT = 1 << 3, EF_TRANSIENT = 1 << 3,
EF_HIDE_IN_EDITOR_SCENE_HIERARCHY = 1 << 4, EF_HIDE_IN_EDITOR_SCENE_HIERARCHY = 1 << 4,
EF_SKIP_RENDER = 1 << 5 EF_SKIP_RENDER = 1 << 5,
EF_IGNORE_RAYCAST = 1 << 6
}; };
struct Transform struct Transform

@ -350,7 +350,8 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene)
if(!(mesh->base.flags & EF_ACTIVE)) continue; if(!(mesh->base.flags & EF_ACTIVE)) continue;
struct Model* model = &mesh->model; struct Model* model = &mesh->model;
struct Transform* transform = &mesh->base.transform; struct Transform* transform = &mesh->base.transform;
int geometry = model->geometry_index; //int geometry = model->geometry_index;
int geometry = geom_find("sphere.symbres");// ->geometry_index;
mat4_identity(&mvp); mat4_identity(&mvp);
mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp);

@ -802,12 +802,14 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re
for(int i = 0; i < MAX_STATIC_MESHES; i++) for(int i = 0; i < MAX_STATIC_MESHES; i++)
{ {
struct Static_Mesh* mesh = &scene->static_meshes[i]; struct Static_Mesh* mesh = &scene->static_meshes[i];
if(!(mesh->base.flags & EF_ACTIVE)) continue; if(!(mesh->base.flags & EF_ACTIVE) || (mesh->base.flags & EF_IGNORE_RAYCAST)) continue;
vec3 abs_pos = { 0.f }; 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_position(mesh, &abs_pos);
transform_get_absolute_scale(mesh, &abs_scale);
struct Geometry* geometry = geom_get(mesh->model.geometry_index); struct Geometry* geometry = geom_get(mesh->model.geometry_index);
if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, ray)) if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, &abs_scale, ray) == IT_INTERSECT)
{ {
out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base; out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base;
out_results->num_entities_intersected++; out_results->num_entities_intersected++;
@ -815,113 +817,6 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re
} }
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool scene_load_(const char* filename, int directory_type)
{
// FILE* entity_file = platform->file.open(directory_type, filename, "r");
//if(!entity_file)
//{
// log_error("scene:load", "Failed to open scenefile %s for reading", filename);
// return false;
//}
//int count = 0;
//int eof_char = -1;
//while(!feof(entity_file))
//{
// if(eof_char != -1) ungetc(eof_char, entity_file);
// struct Entity* new_entity = NULL;
// new_entity = entity_read(entity_file);
// if(!new_entity)
// {
// log_error("scene:load", "Error reading entity");
// }
// else
// {
// log_message("Loaded %s", new_entity->name);
// count++;
// }
// eof_char = fgetc(entity_file);
// /* To check end of file, we get the next character and before beginning
// loop we check if eof occured, feof only returns true if the last read
// was an eof. If it wasn't eof then we return the character back to the
// stream and carry on. */
//}
//log_message("%d entites loaded from %s", count, filename);
//fclose(entity_file);
return entity_load(filename, directory_type);
}
bool scene_save_(const char* filename, int directory_type)
{
bool success = false;
/*FILE* scene_file = platform->file.open(directory_type, filename, "w");
if(!scene_file)
{
log_error("scene:save", "Failed to create scenefile %s for writing", filename);
return false;
}
struct Parser* parser = parser_new();
if(!parser)
{
log_error("scene:save", "Could not create Parser");
fclose(scene_file);
return false;
}
int* entities_to_write = array_new(int);
array_push(entities_to_write, root_node, int);
bool done = false;
int count = 0;
while(!done)
{
struct Entity* entity = entity_get(entities_to_write[0]);
struct Parser_Object* object = parser_object_new(parser, PO_ENTITY);
if(!object)
{
log_error("scene:save", "Failed to create parser object for %s", entity->name);
continue;
}
if(!entity_write(entity, object))
{
log_error("scene:save", "Failed to write '%s' into parser object", entity->name);
continue;
}
log_message("Entity '%s' written to file", entity->name);
count++;
for(int i = 0; i < array_len(entity->transform.children); i++)
array_push(entities_to_write, entity->transform.children[i], int);
array_remove_at(entities_to_write, 0);
if(array_len(entities_to_write) == 0) done = true;
}
if(parser_write_objects(parser, scene_file, filename))
{
log_message("%d entities written to %s", count, filename);
}
else
{
log_error("scene:save", "Failed to write scene to %s", filename);
success = false;
}
array_free(entities_to_write);
parser_free(parser);
fclose(scene_file);*/
return success;
}
int scene_entity_archetype_add(struct Scene* scene, const char* filename) int scene_entity_archetype_add(struct Scene* scene, const char* filename)
{ {
// check if we have already added this archetype, if we have, return that index // check if we have already added this archetype, if we have, return that index

@ -1,8 +1,6 @@
Todo: Todo:
- Better, more accurate picking
- Add editor undo for transformation operations - Add editor undo for transformation operations
- Add material export for blender exporter? - Add material export for blender exporter?
- Remove flickering from selection in editor
- Fix crash when exiting from fullscreen mode - Fix crash when exiting from fullscreen mode
- Allow renaming scene objects in editor - Allow renaming scene objects in editor
- Check if we still need to rotate by 90 degrees when exporting from blender - Check if we still need to rotate by 90 degrees when exporting from blender
@ -120,6 +118,7 @@ Improvements:
- Allow scaling on all axes at once - Allow scaling on all axes at once
- Improve grid/immediate mode drawing by switching to glDrawElements instead of glDrawArrays. - Improve grid/immediate mode drawing by switching to glDrawElements instead of glDrawArrays.
- Investigate why transparency is not working for materials - Investigate why transparency is not working for materials
- Picking for other entity types like lights etc by specifically ray casting for them or in editor switching to pick-mode that specifies if we're picking lights or meshes etc
Bugs: Bugs:
- Better handling of wav format checking at load time - Better handling of wav format checking at load time
@ -358,3 +357,5 @@ Done:
* Add simple player fps controls * Add simple player fps controls
* Fixed gimbal lock in fps camera by fixing the order of quaternion multiplication when getting absolute rotation * Fixed gimbal lock in fps camera by fixing the order of quaternion multiplication when getting absolute rotation
* Fix hierarchical transforms not working in editor mode * Fix hierarchical transforms not working in editor mode
* Better, slightly accurate picking
* Removed flickering from selection in editor
Loading…
Cancel
Save