From ca3a5ac6ec9fe6dc2e1d1e8a75e4d666e0030e50 Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Mon, 30 Dec 2019 18:34:08 +1100 Subject: [PATCH] Implemented ray-boundingbox intersection test --- src/game/bounding_volumes.c | 53 +++++++++++++++++++++++++++++++++++++ src/game/bounding_volumes.h | 1 + src/game/im_render.c | 2 +- src/game/scene.c | 34 +++++++++++++++++++++++- src/game/scene.h | 3 ++- todo.txt | 17 ++++-------- 6 files changed, 95 insertions(+), 15 deletions(-) diff --git a/src/game/bounding_volumes.c b/src/game/bounding_volumes.c index 7742b4d..2466138 100755 --- a/src/game/bounding_volumes.c +++ b/src/game/bounding_volumes.c @@ -246,3 +246,56 @@ void bv_bounding_box_vertices_get_line_visualization(struct Bounding_Box* boundi vec3_fill(&out_vertices[22], bounding_box->max.x, bounding_box->max.y, bounding_box->min.z); vec3_fill(&out_vertices[23], bounding_box->max.x, bounding_box->max.y, bounding_box->max.z); } + +int bv_intersect_bounding_box_ray(struct Bounding_Box* box, struct Ray* ray) +{ + float tmin = (box->min.x - ray->origin.x) / ray->direction.x; + float tmax = (box->max.x - ray->origin.x) / ray->direction.x; + + if(tmin > tmax) + { + float temp = tmin; + tmin = tmax; + tmax = temp; + } + + float tymin = (box->min.y - ray->origin.y) / ray->direction.y; + float tymax = (box->max.y - ray->origin.y) / ray->direction.y; + + if(tymin > tymax) + { + float temp = tymin; + tymin = tymax; + tymax = temp; + } + + if((tmin > tymax) || (tymin > tmax)) + return IT_OUTSIDE; + + if(tymin > tmin) + tmin = tymin; + + if(tymax < tmax) + tmax = tymax; + + float tzmin = (box->min.z - ray->origin.z) / ray->direction.z; + float tzmax = (box->max.z - ray->origin.z) / ray->direction.z; + + if(tzmin > tzmax) + { + float temp = tzmin; + tzmin = tzmax; + tzmax = temp; + } + + if((tmin > tzmax) || (tzmin > tmax)) + return IT_OUTSIDE; + + if(tzmin > tmin) + tmin = tzmin; + + if(tzmax < tmax) + tmax = tzmax; + + return IT_INTERSECT; +} diff --git a/src/game/bounding_volumes.h b/src/game/bounding_volumes.h index 3858507..393e622 100755 --- a/src/game/bounding_volumes.h +++ b/src/game/bounding_volumes.h @@ -53,6 +53,7 @@ int bv_intersect_frustum_box(vec4* frustum, struct Bounding_Box* box, vec3* bo 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); +int bv_intersect_bounding_box_ray(struct Bounding_Box* box, 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); void bv_bounding_box_vertices_get(struct Bounding_Box* box, vec3 out_vertices[8]); diff --git a/src/game/im_render.c b/src/game/im_render.c index 61aa976..9c8d4bd 100755 --- a/src/game/im_render.c +++ b/src/game/im_render.c @@ -240,7 +240,7 @@ void im_render(struct Camera* active_viewer) if(IM_State.curr_geom == -1) return; - /* Sort by draw order, geometries with lower draw order get drawn first */ + /* If there are more than one geometries, sort by draw order. Geometries with lower draw order get drawn first */ if(IM_State.curr_geom + 1 > 1) qsort(IM_State.geometries, IM_State.curr_geom + 1, sizeof(struct IM_Geom), &im_sort_func); diff --git a/src/game/scene.c b/src/game/scene.c index 0a559fa..36bd547 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -24,6 +24,7 @@ static void scene_write_entity_entry(struct Scene* scene, struct Entity* entity, struct Parser* parser); static void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser* parser); +static int scene_sort_by_distance_from_active_viewer_func(const void* e1, const void* e2); void scene_init(struct Scene* scene) { @@ -820,12 +821,43 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re transform_get_absolute_scale(mesh, &abs_scale); struct Geometry* geometry = geom_get(mesh->model.geometry_index); - if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, &abs_scale, ray) == IT_INTERSECT) + //if(bv_intersect_sphere_ray(&geometry->bounding_sphere, &abs_pos, &abs_scale, ray) == IT_INTERSECT) + if(bv_intersect_bounding_box_ray(&mesh->base.transform.bounding_box, ray) == IT_INTERSECT) { out_results->entities_intersected[out_results->num_entities_intersected] = &mesh->base; out_results->num_entities_intersected++; } } + + if(out_results->num_entities_intersected > 1) + qsort(out_results->entities_intersected, out_results->num_entities_intersected, sizeof(struct Entity*), &scene_sort_by_distance_from_active_viewer_func); +} + +int scene_sort_by_distance_from_active_viewer_func(const void* e1, const void* e2) +{ + const struct Entity* entity1 = *(struct Entity**)e1; + const struct Entity* entity2 = *(struct Entity**)e2; + struct Scene* scene = game_state_get()->scene; + struct Camera* camera = &scene->cameras[scene->active_camera_index]; + float d1 = scene_entity_distance(scene, entity1, camera); + float d2 = scene_entity_distance(scene, entity2, camera); + if(d1 < d2) + return -1; + else if(d1 == d2) + return 0; + else + return 1; +} + +float scene_entity_distance(struct Scene* scene, struct Entity* entity1, struct Entity* entity2) +{ + vec3 abs_pos1 = { 0.f, 0.f, 0.f }; + vec3 abs_pos2 = { 0.f, 0.f, 0.f }; + transform_get_absolute_position(entity1, &abs_pos1); + transform_get_absolute_position(entity2, &abs_pos2); + vec3 distance_vector = { 0.f, 0.f, 0.f }; + vec3_sub(&distance_vector, &abs_pos1, &abs_pos2); + return vec3_len(&distance_vector); } int scene_entity_archetype_add(struct Scene* scene, const char* filename) diff --git a/src/game/scene.h b/src/game/scene.h index d4bf6f0..3e47681 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -60,7 +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); +void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results); +float scene_entity_distance(struct Scene* scene, struct Entity* entity1, struct Entity* entity2); // //void scene_init(void); diff --git a/todo.txt b/todo.txt index 6b2c8bd..ebc7e2d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,7 @@ Todo: - - Implement ray-bounding box picking and determine whether that is enough for our needs or do we need to implement OBB + - Determine whether we should enable or disble picking when a tool is active within an editor + - Implement checking if point is inside a bounding box and use that to determine whether a ray is originating inside a bounding box when checking for ray-boundingbox intersection + - Fix issue 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 - 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 @@ -71,7 +73,6 @@ Todo: - Refactor input sub-system to be the same as other sub-systems embedded in game state. - Figure out a way to reduce of remove snprintf calls from render code - - Re-Implement saving/loading scene to/from files - Implement storing console's scroll location and restore it when console is toggled - Implement collision/physics data serialization, read and write. - Physics forces/torque etc @@ -83,32 +84,23 @@ Todo: - Implement Game States - Store Materials in new format supported by parser - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - - Fix bugs with sound sources not updating - Add creating distributable build and uploading to itch.io account support to GENie under windows and linux. - Remove hardcoded numerical values from sscanf and other format strings. ? Recalculated bounding boxes for rotated meshes ? Wrap malloc and free calls in custom functions to track usage ? File extension checking for asset loading ? Only allocate hashmap bucket when required - - Mapping actions to keybindings, for example map action "Jump" to Space key etc ? Add marking or queuing up custom meshes for debug render with particular transform and color for rendering bounding spheres for example ? Interleaved vbos for meshes and changes to blender exporter accordingly - Enumerate and save all the uniform and attribute positions in shader when it is added and cache them in shader object? ? Better handling incase assets folder is not found - - Write entity to/from file - - Ogg format loading and playback - Implement HiDPI support - - Sound streaming - - Implment missing sound source properties (inner/outer cone, getting sound source data) - Shadow maps - Print processor stats and machine capabilites RAM etc on every run to log. - Do input maps really need to be queried by thier string names? - - Write default config/keybindings etc to file if none are found in preferences dir - - Multisampled textures and framebuffers - Validate necessary assets at game launch - Gamma correctness - Log and debug/stats output in gui - - Textual/Binary format for data serialization and persistance - Array based string type comptible with cstring(char*) - Reduce fps on window focus loss or minimization - ??? @@ -400,4 +392,5 @@ Done: or scale for selected entity * Save transformation information when saving entity archetypes * Implement bounding box visualization - * Fixed rotation gizmo for scaled meshes \ No newline at end of file + * 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 \ No newline at end of file