diff options
Diffstat (limited to 'src/geometry')
| -rw-r--r-- | src/geometry/broad_phase_qbvh.rs | 88 | ||||
| -rw-r--r-- | src/geometry/collider_set.rs | 1 | ||||
| -rw-r--r-- | src/geometry/mod.rs | 6 |
3 files changed, 94 insertions, 1 deletions
diff --git a/src/geometry/broad_phase_qbvh.rs b/src/geometry/broad_phase_qbvh.rs new file mode 100644 index 0000000..22ca562 --- /dev/null +++ b/src/geometry/broad_phase_qbvh.rs @@ -0,0 +1,88 @@ +use crate::geometry::{BroadPhasePairEvent, ColliderHandle, ColliderPair, ColliderSet}; +use parry::bounding_volume::BoundingVolume; +use parry::math::Real; +use parry::partitioning::Qbvh; +use parry::partitioning::QbvhUpdateWorkspace; +use parry::query::visitors::BoundingVolumeIntersectionsSimultaneousVisitor; + +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +#[derive(Clone)] +pub struct BroadPhase { + qbvh: Qbvh<ColliderHandle>, + stack: Vec<(u32, u32)>, + #[cfg_attr(feature = "serde-serialize", serde(skip))] + workspace: QbvhUpdateWorkspace, +} + +impl Default for BroadPhase { + fn default() -> Self { + Self::new() + } +} + +impl BroadPhase { + pub fn new() -> Self { + Self { + qbvh: Qbvh::new(), + stack: vec![], + workspace: QbvhUpdateWorkspace::default(), + } + } + + #[allow(dead_code)] // This broad-phase is just experimental right now. + pub fn update( + &mut self, + prediction_distance: Real, + colliders: &ColliderSet, + modified_colliders: &[ColliderHandle], + removed_colliders: &[ColliderHandle], + events: &mut Vec<BroadPhasePairEvent>, + ) { + let margin = 0.01; + + if modified_colliders.is_empty() { + return; + } + + // Visitor to find collision pairs. + let mut visitor = BoundingVolumeIntersectionsSimultaneousVisitor::new( + |co1: &ColliderHandle, co2: &ColliderHandle| { + events.push(BroadPhasePairEvent::AddPair(ColliderPair::new(*co1, *co2))); + true + }, + ); + + let full_rebuild = self.qbvh.raw_nodes().is_empty(); + + if full_rebuild { + self.qbvh.clear_and_rebuild( + colliders.iter().map(|(handle, collider)| { + ( + handle, + collider.compute_aabb().loosened(prediction_distance / 2.0), + ) + }), + margin, + ); + self.qbvh + .traverse_bvtt_with_stack(&self.qbvh, &mut visitor, &mut self.stack); + } else { + for modified in modified_colliders { + self.qbvh.pre_update_or_insert(*modified); + } + + for removed in removed_colliders { + self.qbvh.remove(*removed); + } + + let _ = self.qbvh.refit(margin, &mut self.workspace, |handle| { + colliders[*handle] + .compute_aabb() + .loosened(prediction_distance / 2.0) + }); + self.qbvh + .traverse_modified_bvtt_with_stack(&self.qbvh, &mut visitor, &mut self.stack); + self.qbvh.rebalance(margin, &mut self.workspace); + } + } +} diff --git a/src/geometry/collider_set.rs b/src/geometry/collider_set.rs index 1069f1b..4bc2a03 100644 --- a/src/geometry/collider_set.rs +++ b/src/geometry/collider_set.rs @@ -285,6 +285,7 @@ impl ColliderSet { // Just a very long name instead of `.get_mut` to make sure // this is really the method we wanted to use instead of `get_mut_internal`. + #[allow(dead_code)] pub(crate) fn get_mut_internal_with_modification_tracking( &mut self, handle: ColliderHandle, diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index 4f3ada8..a91c4b9 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -1,6 +1,9 @@ //! Structures related to geometry: colliders, shapes, etc. -pub use self::broad_phase_multi_sap::{BroadPhase, BroadPhasePairEvent, ColliderPair}; +pub use self::broad_phase_multi_sap::{BroadPhasePairEvent, ColliderPair}; + +pub use self::broad_phase_multi_sap::BroadPhase; +// pub use self::broad_phase_qbvh::BroadPhase; pub use self::collider_components::*; pub use self::contact_pair::{ ContactData, ContactManifoldData, ContactPair, IntersectionPair, SolverContact, SolverFlags, @@ -199,5 +202,6 @@ mod interaction_graph; mod interaction_groups; mod narrow_phase; +mod broad_phase_qbvh; mod collider; mod collider_set; |
