From 18d7d36b63c0e0dc932ab892d16fb0311993b3f8 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Wed, 1 Feb 2023 12:37:52 +0000 Subject: [PATCH] Eliminate collision checks between geometry in rendering BVH. Later logic using the `pairable_mask` would catch cases preventing pairing callbacks between geometry. However the collision checks were still taking place, wasting performance. Here we utilize the `tree_mask` feature of BVH to totally eliminate unnecessary collision checks between geometry. --- servers/visual/visual_server_scene.cpp | 8 ++++---- servers/visual/visual_server_scene.h | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 7ff8614ab1e..7a412e80ada 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -184,8 +184,8 @@ VisualServerScene::SpatialPartitionID VisualServerScene::SpatialPartitioningScen p_userdata->bvh_pairable_mask = p_pairable_mask; p_userdata->bvh_pairable_type = p_pairable_type; - uint32_t tree_id = p_pairable ? 1 : 0; - uint32_t tree_collision_mask = 3; + uint32_t tree_collision_mask = 0; + uint32_t tree_id = find_tree_id_and_collision_mask(p_pairable, tree_collision_mask); return _bvh.create(p_userdata, p_userdata->visible, tree_id, tree_collision_mask, p_aabb, p_subindex) + 1; } @@ -227,8 +227,8 @@ void VisualServerScene::SpatialPartitioningScene_BVH::set_pairable(Instance *p_i p_instance->bvh_pairable_mask = p_pairable_mask; p_instance->bvh_pairable_type = p_pairable_type; - uint32_t tree_id = p_pairable ? 1 : 0; - uint32_t tree_collision_mask = 3; + uint32_t tree_collision_mask = 0; + uint32_t tree_id = find_tree_id_and_collision_mask(p_pairable, tree_collision_mask); _bvh.set_tree(handle - 1, tree_id, tree_collision_mask); } diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 4eb4ef9e00a..ca203cc5a7b 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -135,7 +135,7 @@ public: class SpatialPartitioningScene { public: - virtual SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1) = 0; + virtual SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t pairable_mask) = 0; virtual void erase(SpatialPartitionID p_handle) = 0; virtual void move(SpatialPartitionID p_handle, const AABB &p_aabb) = 0; virtual void activate(SpatialPartitionID p_handle, const AABB &p_aabb) {} @@ -168,7 +168,7 @@ public: Octree_CL _octree; public: - SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1); + SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t pairable_mask); void erase(SpatialPartitionID p_handle); void move(SpatialPartitionID p_handle, const AABB &p_aabb); void set_pairable(Instance *p_instance, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask); @@ -231,10 +231,25 @@ public: BVH_Manager, UserCullTestFunction> _bvh; Instance *_dummy_cull_object; + uint32_t find_tree_id_and_collision_mask(bool p_pairable, uint32_t &r_tree_collision_mask) const { + // "pairable" (lights etc) can pair with geometry (non pairable) or other pairables. + // Geometry never pairs with other geometry, so we can eliminate geometry - geometry collision checks. + + // Additionally, when lights are made invisible their p_pairable_mask is set to zero to stop their collisions. + // We could potentially choose `tree_collision_mask` based on whether p_pairable_mask is zero, + // in order to catch invisible lights, but in practice these instances will already have been deactivated within + // the BVH so this step is unnecessary. So we can keep the simpler logic of geometry collides with pairable, + // pairable collides with everything. + r_tree_collision_mask = !p_pairable ? 2 : 3; + + // Returns tree_id. + return p_pairable ? 1 : 0; + } + public: SpatialPartitioningScene_BVH(); ~SpatialPartitioningScene_BVH(); - SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t p_pairable_mask = 1); + SpatialPartitionID create(Instance *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask); void erase(SpatialPartitionID p_handle); void move(SpatialPartitionID p_handle, const AABB &p_aabb); void activate(SpatialPartitionID p_handle, const AABB &p_aabb);