From 29717c2887b2db39faf9c25053730b661dc5da2b Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 13:23:00 +0100 Subject: Externalize the proximity code (renamed intersection). --- src/geometry/interaction_graph.rs | 13 ++ src/geometry/mod.rs | 29 +-- src/geometry/narrow_phase.rs | 203 ++++++++++---------- .../ball_ball_proximity_detector.rs | 68 ------- .../ball_convex_proximity_detector.rs | 42 ---- .../ball_polygon_proximity_detector.rs | 1 - .../cuboid_cuboid_proximity_detector.rs | 78 -------- .../cuboid_polygon_proximity_detector.rs | 1 - .../cuboid_triangle_proximity_detector.rs | 90 --------- src/geometry/proximity_detector/mod.rs | 30 --- .../polygon_polygon_proximity_detector.rs | 57 ------ .../proximity_detector/proximity_detector.rs | 212 --------------------- .../proximity_detector/proximity_dispatcher.rs | 136 ------------- .../trimesh_shape_proximity_detector.rs | 135 ------------- .../voxels_shape_proximity_detector.rs | 0 src/geometry/proximity_pair.rs | 43 ----- src/geometry/user_callbacks.rs | 16 +- src/pipeline/collision_pipeline.rs | 2 +- src/pipeline/event_handler.rs | 20 +- src/pipeline/physics_pipeline.rs | 2 +- 20 files changed, 135 insertions(+), 1043 deletions(-) delete mode 100644 src/geometry/proximity_detector/ball_ball_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/ball_convex_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/ball_polygon_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/cuboid_cuboid_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/cuboid_polygon_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/cuboid_triangle_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/mod.rs delete mode 100644 src/geometry/proximity_detector/polygon_polygon_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/proximity_dispatcher.rs delete mode 100644 src/geometry/proximity_detector/trimesh_shape_proximity_detector.rs delete mode 100644 src/geometry/proximity_detector/voxels_shape_proximity_detector.rs delete mode 100644 src/geometry/proximity_pair.rs (limited to 'src') diff --git a/src/geometry/interaction_graph.rs b/src/geometry/interaction_graph.rs index cae8095..54a19ce 100644 --- a/src/geometry/interaction_graph.rs +++ b/src/geometry/interaction_graph.rs @@ -79,6 +79,19 @@ impl InteractionGraph { self.graph.raw_edges().iter().map(move |edge| &edge.weight) } + /// All the interactions on this graph with the corresponding endpoint weights. + pub fn interactions_with_endpoints( + &self, + ) -> impl Iterator { + self.graph.raw_edges().iter().map(move |edge| { + ( + self.graph.raw_nodes()[edge.source().index()].weight, + self.graph.raw_nodes()[edge.target().index()].weight, + &edge.weight, + ) + }) + } + /// The interaction between the two collision objects identified by their graph index. pub fn interaction_pair( &self, diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index 9f32a7f..efb0cd4 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -11,10 +11,7 @@ pub use self::interaction_graph::{ }; pub use self::narrow_phase::NarrowPhase; pub use self::polygon::Polygon; -pub use self::proximity_detector::{DefaultProximityDispatcher, ProximityDispatcher}; -pub use self::proximity_pair::ProximityPair; pub use self::user_callbacks::{ContactPairFilter, PairFilterContext, ProximityPairFilter}; -pub use eagl::query::Proximity; pub use eagl::query::{KinematicsCategory, TrackedContact}; @@ -62,36 +59,24 @@ pub enum ContactEvent { #[derive(Copy, Clone, Debug)] /// Events occurring when two collision objects start or stop being in close proximity, contact, or disjoint. -pub struct ProximityEvent { +pub struct IntersectionEvent { /// The first collider to which the proximity event applies. pub collider1: ColliderHandle, /// The second collider to which the proximity event applies. pub collider2: ColliderHandle, - /// The previous state of proximity between the two collision objects. - pub prev_status: Proximity, - /// The new state of proximity between the two collision objects. - pub new_status: Proximity, + /// Are the two colliders intersecting? + pub intersecting: bool, } -impl ProximityEvent { +impl IntersectionEvent { /// Instantiates a new proximity event. /// /// Panics if `prev_status` is equal to `new_status`. - pub fn new( - collider1: ColliderHandle, - collider2: ColliderHandle, - prev_status: Proximity, - new_status: Proximity, - ) -> Self { - assert_ne!( - prev_status, new_status, - "The previous and new status of a proximity event must not be the same." - ); + pub fn new(collider1: ColliderHandle, collider2: ColliderHandle, intersecting: bool) -> Self { Self { collider1, collider2, - prev_status, - new_status, + intersecting, } } } @@ -117,8 +102,6 @@ mod contact_pair; mod interaction_graph; mod narrow_phase; mod polygon; -mod proximity_detector; -mod proximity_pair; pub(crate) mod sat; //mod z_order; mod interaction_groups; diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index 240ed31..d9a4f31 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -2,26 +2,22 @@ use rayon::prelude::*; use crate::dynamics::RigidBodySet; -use crate::geometry::proximity_detector::{ - DefaultProximityDispatcher, ProximityDetectionContext, ProximityDispatcher, -}; -use eagl::query::{DefaultQueryDispatcher, PersistentQueryDispatcher}; +use eagl::query::{DefaultQueryDispatcher, PersistentQueryDispatcher, QueryDispatcher}; //#[cfg(feature = "simd-is-enabled")] //use crate::geometry::{ // contact_generator::ContactGenerationContextSimd, -// proximity_detector::ProximityDetectionContextSimd, WBall, +// intersection_detector::ProximityDetectionContextSimd, WBall, //}; use crate::geometry::{ BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ContactManifoldData, - ContactPairFilter, PairFilterContext, ProximityEvent, ProximityPair, ProximityPairFilter, - RemovedCollider, SolverFlags, + ContactPairFilter, IntersectionEvent, PairFilterContext, ProximityPairFilter, RemovedCollider, + SolverFlags, }; use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph}; //#[cfg(feature = "simd-is-enabled")] //use crate::math::{SimdReal, SIMD_WIDTH}; use crate::data::pubsub::Subscription; use crate::data::Coarena; -use crate::eagl::query::Proximity; use crate::pipeline::EventHandler; use std::collections::HashMap; //use simba::simd::SimdValue; @@ -30,14 +26,14 @@ use std::collections::HashMap; #[derive(Copy, Clone, Debug, PartialEq, Eq)] struct ColliderGraphIndices { contact_graph_index: ColliderGraphIndex, - proximity_graph_index: ColliderGraphIndex, + intersection_graph_index: ColliderGraphIndex, } impl ColliderGraphIndices { fn invalid() -> Self { Self { contact_graph_index: InteractionGraph::::invalid_graph_index(), - proximity_graph_index: InteractionGraph::::invalid_graph_index(), + intersection_graph_index: InteractionGraph::::invalid_graph_index(), } } } @@ -47,13 +43,13 @@ impl ColliderGraphIndices { #[derive(Clone)] pub struct NarrowPhase { contact_graph: InteractionGraph, - proximity_graph: InteractionGraph, + intersection_graph: InteractionGraph, graph_indices: Coarena, removed_colliders: Option>, // ball_ball: Vec, // Workspace: Vec<*mut ContactPair>, // shape_shape: Vec, // Workspace: Vec<*mut ContactPair>, - // ball_ball_prox: Vec, // Workspace: Vec<*mut ProximityPair>, - // shape_shape_prox: Vec, // Workspace: Vec<*mut ProximityPair>, + // ball_ball_prox: Vec, // Workspace: Vec<*mut bool>, + // shape_shape_prox: Vec, // Workspace: Vec<*mut bool>, } pub(crate) type ContactManifoldIndex = usize; @@ -63,7 +59,7 @@ impl NarrowPhase { pub fn new() -> Self { Self { contact_graph: InteractionGraph::new(), - proximity_graph: InteractionGraph::new(), + intersection_graph: InteractionGraph::new(), graph_indices: Coarena::new(), removed_colliders: None, // ball_ball: Vec::new(), @@ -78,9 +74,9 @@ impl NarrowPhase { &self.contact_graph } - /// The proximity graph containing all proximity pairs and their proximity information. - pub fn proximity_graph(&self) -> &InteractionGraph { - &self.proximity_graph + /// The intersection graph containing all intersection pairs and their intersection information. + pub fn intersection_graph(&self) -> &InteractionGraph { + &self.intersection_graph } /// All the contacts involving the given collider. @@ -92,15 +88,16 @@ impl NarrowPhase { Some(self.contact_graph.interactions_with(id.contact_graph_index)) } - /// All the proximities involving the given collider. - pub fn proximities_with( - &self, + /// All the intersections involving the given collider. + pub fn intersections_with<'a>( + &'a self, collider: ColliderHandle, - ) -> Option> { + ) -> Option + 'a> { let id = self.graph_indices.get(collider)?; Some( - self.proximity_graph - .interactions_with(id.proximity_graph_index), + self.intersection_graph + .interactions_with(id.intersection_graph_index) + .map(|e| (e.0, e.1, *e.2)), ) } @@ -121,21 +118,20 @@ impl NarrowPhase { .map(|c| c.2) } - /// The proximity pair involving two specific colliders. + /// The intersection pair involving two specific colliders. /// - /// If this returns `None`, there is no intersection between the two colliders. - /// If this returns `Some`, then there may be an intersection between the two colliders. Check the - /// value of [`ProximityPair::proximity`] method to see if there is an actual intersection. - pub fn proximity_pair( + /// If this returns `None` or `Some(false)`, then there is no intersection between the two colliders. + /// If this returns `Some(true)`, then there may be an intersection between the two colliders. + pub fn intersection_pair( &self, collider1: ColliderHandle, collider2: ColliderHandle, - ) -> Option<&ProximityPair> { + ) -> Option { let id1 = self.graph_indices.get(collider1)?; let id2 = self.graph_indices.get(collider2)?; - self.proximity_graph - .interaction_pair(id1.proximity_graph_index, id2.proximity_graph_index) - .map(|c| c.2) + self.intersection_graph + .interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index) + .map(|c| *c.2) } /// All the contact pairs maintained by this narrow-phase. @@ -143,9 +139,13 @@ impl NarrowPhase { self.contact_graph.interactions() } - /// All the proximity pairs maintained by this narrow-phase. - pub fn proximity_pairs(&self) -> impl Iterator { - self.proximity_graph.interactions() + /// All the intersection pairs maintained by this narrow-phase. + pub fn intersection_pairs<'a>( + &'a self, + ) -> impl Iterator + 'a { + self.intersection_graph + .interactions_with_endpoints() + .map(|e| (e.0, e.1, *e.2)) } // #[cfg(feature = "parallel")] @@ -164,7 +164,7 @@ impl NarrowPhase { // TODO: avoid these hash-maps. // They are necessary to handle the swap-remove done internally - // by the contact/proximity graphs when a node is removed. + // by the contact/intersection graphs when a node is removed. let mut prox_id_remap = HashMap::new(); let mut contact_id_remap = HashMap::new(); let mut i = 0; @@ -173,17 +173,17 @@ impl NarrowPhase { // NOTE: if the collider does not have any graph indices currently, there is nothing // to remove in the narrow-phase for this collider. if let Some(graph_idx) = self.graph_indices.get(collider.handle) { - let proximity_graph_id = prox_id_remap + let intersection_graph_id = prox_id_remap .get(&collider.handle) .copied() - .unwrap_or(graph_idx.proximity_graph_index); + .unwrap_or(graph_idx.intersection_graph_index); let contact_graph_id = contact_id_remap .get(&collider.handle) .copied() .unwrap_or(graph_idx.contact_graph_index); self.remove_collider( - proximity_graph_id, + intersection_graph_id, contact_graph_id, colliders, bodies, @@ -201,7 +201,7 @@ impl NarrowPhase { pub(crate) fn remove_collider<'a>( &mut self, - proximity_graph_id: ColliderGraphIndex, + intersection_graph_id: ColliderGraphIndex, contact_graph_id: ColliderGraphIndex, colliders: &mut ColliderSet, bodies: &mut RigidBodySet, @@ -221,11 +221,11 @@ impl NarrowPhase { // We have to manage the fact that one other collider will // have its graph index changed because of the node's swap-remove. - if let Some(replacement) = self.proximity_graph.remove_node(proximity_graph_id) { + if let Some(replacement) = self.intersection_graph.remove_node(intersection_graph_id) { if let Some(replacement) = self.graph_indices.get_mut(replacement) { - replacement.proximity_graph_index = proximity_graph_id; + replacement.intersection_graph_index = intersection_graph_id; } else { - prox_id_remap.insert(replacement, proximity_graph_id); + prox_id_remap.insert(replacement, intersection_graph_id); } } @@ -265,35 +265,33 @@ impl NarrowPhase { if co1.is_sensor() || co2.is_sensor() { // NOTE: the collider won't have a graph index as long // as it does not interact with anything. - if !InteractionGraph::::is_graph_index_valid( - gid1.proximity_graph_index, + if !InteractionGraph::::is_graph_index_valid( + gid1.intersection_graph_index, ) { - gid1.proximity_graph_index = - self.proximity_graph.graph.add_node(pair.collider1); + gid1.intersection_graph_index = + self.intersection_graph.graph.add_node(pair.collider1); } - if !InteractionGraph::::is_graph_index_valid( - gid2.proximity_graph_index, + if !InteractionGraph::::is_graph_index_valid( + gid2.intersection_graph_index, ) { - gid2.proximity_graph_index = - self.proximity_graph.graph.add_node(pair.collider2); + gid2.intersection_graph_index = + self.intersection_graph.graph.add_node(pair.collider2); } if self - .proximity_graph + .intersection_graph .graph - .find_edge(gid1.proximity_graph_index, gid2.proximity_graph_index) + .find_edge( + gid1.intersection_graph_index, + gid2.intersection_graph_index, + ) .is_none() { - let dispatcher = DefaultProximityDispatcher; - let generator = dispatcher - .dispatch(co1.shape().shape_type(), co2.shape().shape_type()); - let interaction = - ProximityPair::new(*pair, generator.0, generator.1); - let _ = self.proximity_graph.add_edge( - gid1.proximity_graph_index, - gid2.proximity_graph_index, - interaction, + let _ = self.intersection_graph.add_edge( + gid1.intersection_graph_index, + gid2.intersection_graph_index, + false, ); } } else { @@ -343,22 +341,19 @@ impl NarrowPhase { self.graph_indices.get(pair.collider2), ) { if co1.is_sensor() || co2.is_sensor() { - let prox_pair = self.proximity_graph.remove_edge( - gid1.proximity_graph_index, - gid2.proximity_graph_index, + let was_intersecting = self.intersection_graph.remove_edge( + gid1.intersection_graph_index, + gid2.intersection_graph_index, ); - // Emit a proximity lost event if we had a proximity before removing the edge. - if let Some(prox) = prox_pair { - if prox.proximity != Proximity::Disjoint { - let prox_event = ProximityEvent::new( - pair.collider1, - pair.collider2, - prox.proximity, - Proximity::Disjoint, - ); - events.handle_proximity_event(prox_event) - } + // Emit an intersection lost event if we had an intersection before removing the edge. + if Some(true) == was_intersecting { + let prox_event = IntersectionEvent::new( + pair.collider1, + pair.collider2, + false, + ); + events.handle_intersection_event(prox_event) } } else { let contact_pair = self.contact_graph.remove_edge( @@ -387,7 +382,7 @@ impl NarrowPhase { } } - pub(crate) fn compute_proximities( + pub(crate) fn compute_intersections( &mut self, prediction_distance: f32, bodies: &RigidBodySet, @@ -395,10 +390,12 @@ impl NarrowPhase { pair_filter: Option<&dyn ProximityPairFilter>, events: &dyn EventHandler, ) { - par_iter_mut!(&mut self.proximity_graph.graph.edges).for_each(|edge| { - let pair = &mut edge.weight; - let co1 = &colliders[pair.pair.collider1]; - let co2 = &colliders[pair.pair.collider2]; + let nodes = &self.intersection_graph.graph.nodes; + par_iter_mut!(&mut self.intersection_graph.graph.edges).for_each(|edge| { + let handle1 = nodes[edge.source().index()].weight; + let handle2 = nodes[edge.target().index()].weight; + let co1 = &colliders[handle1]; + let co2 = &colliders[handle2]; // FIXME: avoid lookup into bodies. let rb1 = &bodies[co1.parent]; @@ -408,17 +405,17 @@ impl NarrowPhase { || (rb2.is_sleeping() && rb1.is_static()) || (rb1.is_sleeping() && rb2.is_sleeping()) { - // No need to update this proximity because nothing moved. + // No need to update this intersection because nothing moved. return; } if !co1.collision_groups.test(co2.collision_groups) { - // The proximity is not allowed. + // The intersection is not allowed. return; } if pair_filter.is_none() && !rb1.is_dynamic() && !rb2.is_dynamic() { - // Default filtering rule: no proximity between two non-dynamic bodies. + // Default filtering rule: no intersection between two non-dynamic bodies. return; } @@ -430,34 +427,26 @@ impl NarrowPhase { collider2: co2, }; - if !filter.filter_proximity_pair(&context) { - // No proximity allowed. + if !filter.filter_intersection_pair(&context) { + // No intersection allowed. return; } } - let dispatcher = DefaultProximityDispatcher; - if pair.detector.is_none() { - // We need a redispatch for this detector. - // This can happen, e.g., after restoring a snapshot of the narrow-phase. - let (detector, workspace) = - dispatcher.dispatch(co1.shape().shape_type(), co2.shape().shape_type()); - pair.detector = Some(detector); - pair.detector_workspace = workspace; - } - - let context = ProximityDetectionContext { - dispatcher: &dispatcher, - prediction_distance, - colliders, - pair, - }; + let pos12 = co1.position().inverse() * co2.position(); + let dispatcher = DefaultQueryDispatcher; - context - .pair - .detector - .unwrap() - .detect_proximity(context, events); + if let Ok(intersection) = dispatcher.intersection_test(&pos12, co1.shape(), co2.shape()) + { + if intersection != edge.weight { + edge.weight = intersection; + events.handle_intersection_event(IntersectionEvent::new( + handle1, + handle2, + intersection, + )); + } + } }); } diff --git a/src/geometry/proximity_detector/ball_ball_proximity_detector.rs b/src/geometry/proximity_detector/ball_ball_proximity_detector.rs deleted file mode 100644 index 65c141c..0000000 --- a/src/geometry/proximity_detector/ball_ball_proximity_detector.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::geometry::proximity_detector::PrimitiveProximityDetectionContext; - -use crate::geometry::Proximity; -use crate::math::Point; -#[cfg(feature = "simd-is-enabled")] -use { - crate::geometry::{proximity_detector::PrimitiveProximityDetectionContextSimd, WBall}, - crate::math::{SimdReal, SIMD_WIDTH}, - simba::simd::SimdValue, -}; - -#[cfg(feature = "simd-is-enabled")] -fn ball_distance_simd(ball1: &WBall, ball2: &WBall) -> SimdReal { - let dcenter = ball2.center - ball1.center; - let center_dist = dcenter.magnitude(); - center_dist - ball1.radius - ball2.radius -} - -#[cfg(feature = "simd-is-enabled")] -pub fn detect_proximity_ball_ball_simd( - ctxt: &mut PrimitiveProximityDetectionContextSimd, -) -> [Proximity; SIMD_WIDTH] { - let pos_ba = ctxt.positions2.inverse() * ctxt.positions1; - let radii_a = - SimdReal::from(array![|ii| ctxt.shapes1[ii].as_ball().unwrap().radius; SIMD_WIDTH]); - let radii_b = - SimdReal::from(array![|ii| ctxt.shapes2[ii].as_ball().unwrap().radius; SIMD_WIDTH]); - - let wball_a = WBall::new(Point::origin(), radii_a); - let wball_b = WBall::new(pos_ba.inverse_transform_point(&Point::origin()), radii_b); - let distances = ball_distance_simd(&wball_a, &wball_b); - let mut proximities = [Proximity::Disjoint; SIMD_WIDTH]; - - for i in 0..SIMD_WIDTH { - // FIXME: compare the dist before computing the proximity. - let dist = distances.extract(i); - if dist > ctxt.prediction_distance { - proximities[i] = Proximity::Disjoint; - } else if dist > 0.0 { - proximities[i] = Proximity::WithinMargin; - } else { - proximities[i] = Proximity::Intersecting - } - } - - proximities -} - -pub fn detect_proximity_ball_ball(ctxt: &mut PrimitiveProximityDetectionContext) -> Proximity { - let pos_ba = ctxt.position2.inverse() * ctxt.position1; - let radius_a = ctxt.shape1.as_ball().unwrap().radius; - let radius_b = ctxt.shape2.as_ball().unwrap().radius; - - let center_a = Point::origin(); - let center_b = pos_ba.inverse_transform_point(&Point::origin()); - - let dcenter = center_b - center_a; - let center_dist = dcenter.magnitude(); - let dist = center_dist - radius_a - radius_b; - - if dist > ctxt.prediction_distance { - Proximity::Disjoint - } else if dist > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } -} diff --git a/src/geometry/proximity_detector/ball_convex_proximity_detector.rs b/src/geometry/proximity_detector/ball_convex_proximity_detector.rs deleted file mode 100644 index 19ead5c..0000000 --- a/src/geometry/proximity_detector/ball_convex_proximity_detector.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::geometry::proximity_detector::PrimitiveProximityDetectionContext; -use crate::geometry::{Ball, Proximity}; -use crate::math::Isometry; -use eagl::query::PointQuery; - -pub fn detect_proximity_ball_convex(ctxt: &mut PrimitiveProximityDetectionContext) -> Proximity { - if let Some(ball1) = ctxt.shape1.as_ball() { - do_detect_proximity(ctxt.shape2, ball1, &ctxt) - } else if let Some(ball2) = ctxt.shape2.as_ball() { - do_detect_proximity(ctxt.shape1, ball2, &ctxt) - } else { - panic!("Invalid shape types provide.") - } -} - -fn do_detect_proximity( - point_query1: &P, - ball2: &Ball, - ctxt: &PrimitiveProximityDetectionContext, -) -> Proximity { - let local_p2_1 = ctxt - .position1 - .inverse_transform_point(&ctxt.position2.translation.vector.into()); - - let proj = point_query1.project_local_point(&local_p2_1, cfg!(feature = "dim3")); - let dpos = local_p2_1 - proj.local_point; - let dist = dpos.norm(); - - if proj.is_inside { - return Proximity::Intersecting; - } - - if dist <= ball2.radius + ctxt.prediction_distance { - if dist <= ball2.radius { - Proximity::Intersecting - } else { - Proximity::WithinMargin - } - } else { - Proximity::Disjoint - } -} diff --git a/src/geometry/proximity_detector/ball_polygon_proximity_detector.rs b/src/geometry/proximity_detector/ball_polygon_proximity_detector.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/geometry/proximity_detector/ball_polygon_proximity_detector.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/geometry/proximity_detector/cuboid_cuboid_proximity_detector.rs b/src/geometry/proximity_detector/cuboid_cuboid_proximity_detector.rs deleted file mode 100644 index b43f53d..0000000 --- a/src/geometry/proximity_detector/cuboid_cuboid_proximity_detector.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::geometry::proximity_detector::PrimitiveProximityDetectionContext; -use crate::geometry::Proximity; -use crate::math::Isometry; -use eagl::query::sat; -use eagl::shape::Cuboid; - -pub fn detect_proximity_cuboid_cuboid(ctxt: &mut PrimitiveProximityDetectionContext) -> Proximity { - if let (Some(cube1), Some(cube2)) = (ctxt.shape1.as_cuboid(), ctxt.shape2.as_cuboid()) { - detect_proximity( - ctxt.prediction_distance, - cube1, - ctxt.position1, - cube2, - ctxt.position2, - ) - } else { - unreachable!() - } -} - -pub fn detect_proximity<'a>( - prediction_distance: f32, - cube1: &'a Cuboid, - pos1: &'a Isometry, - cube2: &'a Cuboid, - pos2: &'a Isometry, -) -> Proximity { - let pos12 = pos1.inverse() * pos2; - let pos21 = pos12.inverse(); - - /* - * - * Point-Face - * - */ - let sep1 = sat::cuboid_cuboid_find_local_separating_normal_oneway(cube1, cube2, &pos12).0; - if sep1 > prediction_distance { - return Proximity::Disjoint; - } - - let sep2 = sat::cuboid_cuboid_find_local_separating_normal_oneway(cube2, cube1, &pos21).0; - if sep2 > prediction_distance { - return Proximity::Disjoint; - } - - /* - * - * Edge-Edge cases - * - */ - #[cfg(feature = "dim2")] - let sep3 = -f32::MAX; // This case does not exist in 2D. - #[cfg(feature = "dim3")] - let sep3 = sat::cuboid_cuboid_find_local_separating_edge_twoway(cube1, cube2, &pos12).0; - if sep3 > prediction_distance { - return Proximity::Disjoint; - } - - if sep2 > sep1 && sep2 > sep3 { - if sep2 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } else if sep3 > sep1 { - if sep3 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } else { - if sep1 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } -} diff --git a/src/geometry/proximity_detector/cuboid_polygon_proximity_detector.rs b/src/geometry/proximity_detector/cuboid_polygon_proximity_detector.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/geometry/proximity_detector/cuboid_polygon_proximity_detector.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/geometry/proximity_detector/cuboid_triangle_proximity_detector.rs b/src/geometry/proximity_detector/cuboid_triangle_proximity_detector.rs deleted file mode 100644 index 5ac12a8..0000000 --- a/src/geometry/proximity_detector/cuboid_triangle_proximity_detector.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::geometry::proximity_detector::PrimitiveProximityDetectionContext; -use crate::geometry::{Cuboid, Proximity, Triangle}; -use crate::math::Isometry; -use eagl::query::sat; - -pub fn detect_proximity_cuboid_triangle( - ctxt: &mut PrimitiveProximityDetectionContext, -) -> Proximity { - if let (Some(cube1), Some(triangle2)) = (ctxt.shape1.as_cuboid(), ctxt.shape2.as_triangle()) { - detect_proximity( - ctxt.prediction_distance, - cube1, - ctxt.position1, - triangle2, - ctxt.position2, - ) - } else if let (Some(triangle1), Some(cube2)) = - (ctxt.shape1.as_triangle(), ctxt.shape2.as_cuboid()) - { - detect_proximity( - ctxt.prediction_distance, - cube2, - ctxt.position2, - triangle1, - ctxt.position1, - ) - } else { - panic!("Invalid shape types") - } -} - -pub fn detect_proximity<'a>( - prediction_distance: f32, - cube1: &'a Cuboid, - pos1: &'a Isometry, - triangle2: &'a Triangle, - pos2: &'a Isometry, -) -> Proximity { - let pos12 = pos1.inverse() * pos2; - let pos21 = pos12.inverse(); - - /* - * - * Point-Face cases. - * - */ - let sep1 = - sat::cuboid_support_map_find_local_separating_normal_oneway(cube1, triangle2, &pos12).0; - if sep1 > prediction_distance { - return Proximity::Disjoint; - } - - let sep2 = sat::triangle_cuboid_find_local_separating_normal_oneway(triangle2, cube1, &pos21).0; - if sep2 > prediction_distance { - return Proximity::Disjoint; - } - - /* - * - * Edge-Edge cases. - * - */ - #[cfg(feature = "dim2")] - let sep3 = -f32::MAX; // This case does not exist in 2D. - #[cfg(feature = "dim3")] - let sep3 = sat::cuboid_triangle_find_local_separating_edge_twoway(cube1, triangle2, &pos12).0; - if sep3 > prediction_distance { - return Proximity::Disjoint; - } - - if sep2 > sep1 && sep2 > sep3 { - if sep2 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } else if sep3 > sep1 { - if sep3 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } else { - if sep1 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } -} diff --git a/src/geometry/proximity_detector/mod.rs b/src/geometry/proximity_detector/mod.rs deleted file mode 100644 index fc904da..0000000 --- a/src/geometry/proximity_detector/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -pub use self::ball_ball_proximity_detector::detect_proximity_ball_ball; -#[cfg(feature = "simd-is-enabled")] -pub use self::ball_ball_proximity_detector::detect_proximity_ball_ball_simd; -pub use self::ball_convex_proximity_detector::detect_proximity_ball_convex; -pub use self::cuboid_cuboid_proximity_detector::detect_proximity_cuboid_cuboid; -pub use self::cuboid_triangle_proximity_detector::detect_proximity_cuboid_triangle; -pub use self::polygon_polygon_proximity_detector::detect_proximity_polygon_polygon; -pub use self::proximity_detector::{ - PrimitiveProximityDetectionContext, PrimitiveProximityDetector, ProximityDetectionContext, - ProximityDetector, ProximityPhase, -}; -#[cfg(feature = "simd-is-enabled")] -pub use self::proximity_detector::{ - PrimitiveProximityDetectionContextSimd, ProximityDetectionContextSimd, -}; -pub use self::proximity_dispatcher::{DefaultProximityDispatcher, ProximityDispatcher}; -pub use self::trimesh_shape_proximity_detector::{ - detect_proximity_trimesh_shape, TriMeshShapeProximityDetectorWorkspace, -}; - -mod ball_ball_proximity_detector; -mod ball_convex_proximity_detector; -mod ball_polygon_proximity_detector; -mod cuboid_cuboid_proximity_detector; -mod cuboid_polygon_proximity_detector; -mod cuboid_triangle_proximity_detector; -mod polygon_polygon_proximity_detector; -mod proximity_detector; -mod proximity_dispatcher; -mod trimesh_shape_proximity_detector; diff --git a/src/geometry/proximity_detector/polygon_polygon_proximity_detector.rs b/src/geometry/proximity_detector/polygon_polygon_proximity_detector.rs deleted file mode 100644 index 12a8e45..0000000 --- a/src/geometry/proximity_detector/polygon_polygon_proximity_detector.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![allow(dead_code)] - -use crate::geometry::proximity_detector::PrimitiveProximityDetectionContext; -use crate::geometry::{sat, Polygon, Proximity}; -use crate::math::Isometry; - -pub fn detect_proximity_polygon_polygon( - _ctxt: &mut PrimitiveProximityDetectionContext, -) -> Proximity { - unimplemented!() - // if let (Some(polygon1), Some(polygon2)) = (ctxt.shape1.as_polygon(), ctxt.shape2.as_polygon()) { - // detect_proximity( - // ctxt.prediction_distance, - // polygon1, - // &ctxt.position1, - // polygon2, - // &ctxt.position2, - // ) - // } else { - // unreachable!() - // } -} - -fn detect_proximity<'a>( - prediction_distance: f32, - p1: &'a Polygon, - m1: &'a Isometry, - p2: &'a Polygon, - m2: &'a Isometry, -) -> Proximity { - let m12 = m1.inverse() * m2; - let m21 = m12.inverse(); - - let sep1 = sat::polygon_polygon_compute_separation_features(p1, p2, &m12); - if sep1.0 > prediction_distance { - return Proximity::Disjoint; - } - - let sep2 = sat::polygon_polygon_compute_separation_features(p2, p1, &m21); - if sep2.0 > prediction_distance { - return Proximity::Disjoint; - } - - if sep2.0 > sep1.0 { - if sep2.0 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } else { - if sep1.0 > 0.0 { - Proximity::WithinMargin - } else { - Proximity::Intersecting - } - } -} diff --git a/src/geometry/proximity_detector/proximity_detector.rs b/src/geometry/proximity_detector/proximity_detector.rs deleted file mode 100644 index ea362de..0000000 --- a/src/geometry/proximity_detector/proximity_detector.rs +++ /dev/null @@ -1,212 +0,0 @@ -use crate::geometry::{ - Collider, ColliderSet, Proximity, ProximityDispatcher, ProximityEvent, ProximityPair, Shape, -}; -use crate::math::Isometry; -#[cfg(feature = "simd-is-enabled")] -use crate::math::{SimdReal, SIMD_WIDTH}; -use crate::pipeline::EventHandler; -use std::any::Any; - -#[derive(Copy, Clone)] -pub enum ProximityPhase { - NearPhase(ProximityDetector), - ExactPhase(PrimitiveProximityDetector), -} - -impl ProximityPhase { - #[inline] - pub fn detect_proximity( - self, - mut context: ProximityDetectionContext, - events: &dyn EventHandler, - ) { - let proximity = match self { - Self::NearPhase(gen) => (gen.detect_proximity)(&mut context), - Self::ExactPhase(gen) => { - // Build the primitive context from the non-primitive context and dispatch. - let collider1 = &context.colliders[context.pair.pair.collider1]; - let collider2 = &context.colliders[context.pair.pair.collider2]; - - let mut context2 = PrimitiveProximityDetectionContext { - prediction_distance: context.prediction_distance, - collider1, - collider2, - shape1: collider1.shape(), - shape2: collider2.shape(), - position1: collider1.position(), - position2: collider2.position(), - workspace: context.pair.detector_workspace.as_mut().map(|w| &mut **w), - }; - - (gen.detect_proximity)(&mut context2) - } - }; - - if context.pair.proximity != proximity { - events.handle_proximity_event(ProximityEvent::new( - context.pair.pair.collider1, - context.pair.pair.collider2, - context.pair.proximity, - proximity, - )) - } - - context.pair.proximity = proximity; - } - - #[cfg(feature = "simd-is-enabled")] - #[inline] - pub fn detect_proximity_simd( - self, - mut context: ProximityDetectionContextSimd, - events: &dyn EventHandler, - ) { - let proximities = match self { - Self::NearPhase(gen) => (gen.detect_proximity_simd)(&mut context), - Self::ExactPhase(gen) => { - // Build the primitive context from the non-primitive context and dispatch. - use arrayvec::ArrayVec; - let mut colliders_arr: ArrayVec<[(&Collider, &Collider); SIMD_WIDTH]> = - ArrayVec::new(); - let mut workspace_arr: ArrayVec< - [Option<&mut (dyn Any + Send + Sync)>; SIMD_WIDTH], - > = ArrayVec::new(); - - for pair in context.pairs.iter_mut() { - let collider1 = &context.colliders[pair.pair.collider1]; - let collider2 = &context.colliders[pair.pair.collider2]; - colliders_arr.push((collider1, collider2)); - workspace_arr.push(pair.detector_workspace.as_mut().map(|w| &mut **w)); - } - - let max_index = colliders_arr.len() - 1; - let colliders1 = array![|ii| colliders_arr[ii.min(max_index)].0; SIMD_WIDTH]; - let colliders2 = array![|ii| colliders_arr[ii.min(max_index)].1; SIMD_WIDTH]; - - let mut context2 = PrimitiveProximityDetectionContextSimd { - prediction_distance: context.prediction_distance, - colliders1, - colliders2, - shapes1: array![|ii| colliders1[ii].shape(); SIMD_WIDTH], - shapes2: array![|ii| colliders2[ii].shape(); SIMD_WIDTH], - positions1: &Isometry::from( - array![|ii| *colliders1[ii].position(); SIMD_WIDTH], - ), - positions2: &Isometry::from( - array![|ii| *colliders2[ii].position(); SIMD_WIDTH], - ), - workspaces: workspace_arr.as_mut_slice(), - }; - - (gen.detect_proximity_simd)(&mut context2) - } - }; - - for (i, pair) in context.pairs.iter_mut().enumerate() { - if pair.proximity != proximities[i] { - events.handle_proximity_event(ProximityEvent::new( - pair.pair.collider1, - pair.pair.collider2, - pair.proximity, - proximities[i], - )) - } - pair.proximity = proximities[i]; - } - } -} - -pub struct PrimitiveProximityDetectionContext<'a> { - pub prediction_distance: f32, - pub collider1: &'a Collider, - pub collider2: &'a Collider, - pub shape1: &'a dyn Shape, - pub shape2: &'a dyn Shape, - pub position1: &'a Isometry, - pub position2: &'a Isometry, - pub workspace: Option<&'a mut (dyn Any + Send + Sync)>, -} - -#[cfg(feature = "simd-is-enabled")] -pub struct PrimitiveProximityDetectionContextSimd<'a, 'b> { - pub prediction_distance: f32, - pub colliders1: [&'a Collider; SIMD_WIDTH], - pub colliders2: [&'a Collider; SIMD_WIDTH], - pub shapes1: [&'a dyn Shape; SIMD_WIDTH], - pub shapes2: [&'a dyn Shape; SIMD_WIDTH], - pub positions1: &'a Isometry, - pub positions2: &'a Isometry, - pub workspaces: &'a mut [Option<&'b mut (dyn Any + Send + Sync)>], -} - -#[derive(Copy, Clone)] -pub struct PrimitiveProximityDetector { - pub detect_proximity: fn(&mut PrimitiveProximityDetectionContext) -> Proximity, - #[cfg(feature = "simd-is-enabled")] - pub detect_proximity_simd: - fn(&mut PrimitiveProximityDetectionContextSimd) -> [Proximity; SIMD_WIDTH], -} - -impl PrimitiveProximityDetector { - fn unimplemented_fn(_ctxt: &mut PrimitiveProximityDetectionContext) -> Proximity { - Proximity::Disjoint - } - #[cfg(feature = "simd-is-enabled")] - fn unimplemented_simd_fn( - _ctxt: &mut PrimitiveProximityDetectionContextSimd, - ) -> [Proximity; SIMD_WIDTH] { - [Proximity::Disjoint; SIMD_WIDTH] - } -} - -impl Default for PrimitiveProximityDetector { - fn default() -> Self { - Self { - detect_proximity: Self::unimplemented_fn, - #[cfg(feature = "simd-is-enabled")] - detect_proximity_simd: Self::unimplemented_simd_fn, - } - } -} - -pub struct ProximityDetectionContext<'a> { - pub dispatcher: &'a dyn ProximityDispatcher, - pub prediction_distance: f32, - pub colliders: &'a ColliderSet, - pub pair: &'a mut ProximityPair, -} - -#[cfg(feature = "simd-is-enabled")] -pub struct ProximityDetectionContextSimd<'a, 'b> { - pub dispatcher: &'a dyn ProximityDispatcher, - pub prediction_distance: f32, - pub colliders: &'a ColliderSet, - pub pairs: &'a mut [&'b mut ProximityPair], -} - -#[derive(Copy, Clone)] -pub struct ProximityDetector { - pub detect_proximity: fn(&mut ProximityDetectionContext) -> Proximity, - #[cfg(feature = "simd-is-enabled")] - pub detect_proximity_simd: fn(&mut ProximityDetectionContextSimd) -> [Proximity; SIMD_WIDTH], -} - -impl ProximityDetector { - fn unimplemented_fn(_ctxt: &mut ProximityDetectionContext) -> Proximity { - Proximity::Disjoint - } - #[cfg(feature = "simd-is-enabled")] - fn unimplemented_simd_fn(_ctxt: &mut ProximityDetectionContextSimd) -> [Proximity; SIMD_WIDTH] { - [Proximity::Disjoint; SIMD_WIDTH] - } -} - -impl Default for ProximityDetector { - fn default() -> Self { - Self { - detect_proximity: Self::unimplemented_fn, - #[cfg(feature = "simd-is-enabled")] - detect_proximity_simd: Self::unimplemented_simd_fn, - } - } -} diff --git a/src/geometry/proximity_detector/proximity_dispatcher.rs b/src/geometry/proximity_detector/proximity_dispatcher.rs deleted file mode 100644 index 709521e..0000000 --- a/src/geometry/proximity_detector/proximity_dispatcher.rs +++ /dev/null @@ -1,136 +0,0 @@ -use crate::geometry::proximity_detector::{ - PrimitiveProximityDetector, ProximityDetector, ProximityPhase, - TriMeshShapeProximityDetectorWorkspace, -}; -use crate::geometry::ShapeType; -use std::any::Any; - -/// Trait implemented by structures responsible for selecting a collision-detection algorithm -/// for a given pair of shapes. -pub trait ProximityDispatcher { - /// Select the proximity detection algorithm for the given pair of primitive shapes. - fn dispatch_primitives( - &self, - shape1: ShapeType, - shape2: ShapeType, - ) -> ( - PrimitiveProximityDetector, - Option>, - ); - /// Select the proximity detection algorithm for the given pair of non-primitive shapes. - fn dispatch( - &self, - shape1: ShapeType, - shape2: ShapeType, - ) -> (ProximityPhase, Option>); -} - -/// The default proximity dispatcher used by Rapier. -pub struct DefaultProximityDispatcher; - -impl ProximityDispatcher for DefaultProximityDispatcher { - fn dispatch_primitives( - &self, - shape1: ShapeType, - shape2: ShapeType, - ) -> ( - PrimitiveProximityDetector, - Option>, - ) { - match (shape1, shape2) { - (ShapeType::Ball, ShapeType::Ball) => ( - PrimitiveProximityDetector { - #[cfg(feature = "simd-is-enabled")] - detect_proximity_simd: super::detect_proximity_ball_ball_simd, - detect_proximity: super::detect_proximity_ball_ball, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Cuboid, ShapeType::Cuboid) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_cuboid_cuboid, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Polygon, ShapeType::Polygon) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_polygon_polygon, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Triangle, ShapeType::Ball) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_ball_convex, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Ball, ShapeType::Triangle) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_ball_convex, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Cuboid, ShapeType::Ball) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_ball_convex, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Ball, ShapeType::Cuboid) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_ball_convex, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Triangle, ShapeType::Cuboid) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_cuboid_triangle, - ..PrimitiveProximityDetector::default() - }, - None, - ), - (ShapeType::Cuboid, ShapeType::Triangle) => ( - PrimitiveProximityDetector { - detect_proximity: super::detect_proximity_cuboid_triangle, - ..PrimitiveProximityDetector::default() - }, - None, - ), - _ => (PrimitiveProximityDetector::default(), None), - } - } - - fn dispatch( - &self, - shape1: ShapeType, - shape2: ShapeType, - ) -> (ProximityPhase, Option>) { - match (shape1, shape2) { - (ShapeType::TriMesh, _) => ( - ProximityPhase::NearPhase(ProximityDetector { - detect_proximity: super::detect_proximity_trimesh_shape, - ..ProximityDetector::default() - }), - Some(Box::new(TriMeshShapeProximityDetectorWorkspace::new())), - ), - (_, ShapeType::TriMesh) => ( - ProximityPhase::NearPhase(ProximityDetector { - detect_proximity: super::detect_proximity_trimesh_shape, - ..ProximityDetector::default() - }), - Some(Box::new(TriMeshShapeProximityDetectorWorkspace::new())), - ), - _ => { - let (gen, workspace) = self.dispatch_primitives(shape1, shape2); - (ProximityPhase::ExactPhase(gen), workspace) - } - } - } -} diff --git a/src/geometry/proximity_detector/trimesh_shape_proximity_detector.rs b/src/geometry/proximity_detector/trimesh_shape_proximity_detector.rs deleted file mode 100644 index 961de3b..0000000 --- a/src/geometry/proximity_detector/trimesh_shape_proximity_detector.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::eagl::bounding_volume::{BoundingVolume, AABB}; -use crate::geometry::proximity_detector::{ - PrimitiveProximityDetectionContext, ProximityDetectionContext, -}; -use crate::geometry::{Collider, Proximity, ShapeType, TriMesh}; - -pub struct TriMeshShapeProximityDetectorWorkspace { - interferences: Vec, - local_aabb2: AABB, - old_interferences: Vec, -} - -impl TriMeshShapeProximityDetectorWorkspace { - pub fn new() -> Self { - Self { - interferences: Vec::new(), - local_aabb2: AABB::new_invalid(), - old_interferences: Vec::new(), - } - } -} - -pub fn detect_proximity_trimesh_shape(ctxt: &mut ProximityDetectionContext) -> Proximity { - let collider1 = &ctxt.colliders[ctxt.pair.pair.collider1]; - let collider2 = &ctxt.colliders[ctxt.pair.pair.collider2]; - - if let Some(trimesh1) = collider1.shape().as_trimesh() { - do_detect_proximity(trimesh1, collider1, collider2, ctxt) - } else if let Some(trimesh2) = collider2.shape().as_trimesh() { - do_detect_proximity(trimesh2, collider2, collider1, ctxt) - } else { - panic!("Invalid shape types provided.") - } -} - -fn do_detect_proximity( - trimesh1: &TriMesh, - collider1: &Collider, - collider2: &Collider, - ctxt: &mut ProximityDetectionContext, -) -> Proximity { - let workspace: &mut TriMeshShapeProximityDetectorWorkspace = ctxt - .pair - .detector_workspace - .as_mut() - .expect("The TriMeshShapeProximityDetectorWorkspace is missing.") - .downcast_mut() - .expect("Invalid workspace type, expected a TriMeshShapeProximityDetectorWorkspace."); - - /* - * Compute interferences. - */ - let pos12 = collider1.position.inverse() * collider2.position; - // TODO: somehow precompute the AABB and reuse it? - let mut new_local_aabb2 = collider2 - .shape() - .compute_aabb(&pos12) - .loosened(ctxt.prediction_distance); - let same_local_aabb2 = workspace.local_aabb2.contains(&new_local_aabb2); - - if !same_local_aabb2 { - let extra_margin = - (new_local_aabb2.maxs - new_local_aabb2.mins).map(|e| (e / 10.0).min(0.1)); - new_local_aabb2.mins -= extra_margin; - new_local_aabb2.maxs += extra_margin; - - let local_aabb2 = new_local_aabb2; // .loosened(ctxt.prediction_distance * 2.0); // FIXME: what would be the best value? - std::mem::swap( - &mut workspace.old_interferences, - &mut workspace.interferences, - ); - - workspace.interferences.clear(); - trimesh1 - .quadtree() - .intersect_aabb(&local_aabb2, &mut workspace.interferences); - workspace.local_aabb2 = local_aabb2; - } - - /* - * Dispatch to the specific solver by keeping the previous manifold if we already had one. - */ - let new_interferences = &workspace.interferences; - let mut old_inter_it = workspace.old_interferences.drain(..).peekable(); - let mut best_proximity = Proximity::Disjoint; - let shape_type2 = collider2.shape().shape_type(); - - for triangle_id in new_interferences.iter() { - if *triangle_id >= trimesh1.num_triangles() as u32 { - // Because of SIMD padding, the broad-phase may return triangle indices greater - // than the max. - continue; - } - - if !same_local_aabb2 { - loop { - match old_inter_it.peek() { - Some(old_triangle_id) if *old_triangle_id < *triangle_id => { - old_inter_it.next(); - } - _ => break, - } - } - - if old_inter_it.peek() != Some(triangle_id) { - } else { - old_inter_it.next(); - }; - } - - let triangle1 = trimesh1.triangle(*triangle_id); - let (proximity_detector, mut workspace2) = ctxt - .dispatcher - .dispatch_primitives(ShapeType::Triangle, shape_type2); - - let mut ctxt2 = PrimitiveProximityDetectionContext { - prediction_distance: ctxt.prediction_distance, - collider1, - collider2, - shape1: &triangle1, - shape2: collider2.shape(), - position1: collider1.position(), - position2: collider2.position(), - workspace: workspace2.as_mut().map(|w| &mut **w), - }; - - match (proximity_detector.detect_proximity)(&mut ctxt2) { - Proximity::Intersecting => return Proximity::Intersecting, - Proximity::WithinMargin => best_proximity = Proximity::WithinMargin, - Proximity::Disjoint => {} - } - } - - best_proximity -} diff --git a/src/geometry/proximity_detector/voxels_shape_proximity_detector.rs b/src/geometry/proximity_detector/voxels_shape_proximity_detector.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/geometry/proximity_pair.rs b/src/geometry/proximity_pair.rs deleted file mode 100644 index d3e0dc4..0000000 --- a/src/geometry/proximity_pair.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::geometry::proximity_detector::ProximityPhase; -use crate::geometry::{ColliderPair, Proximity}; -use std::any::Any; - -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// The description of the proximity of two colliders. -pub struct ProximityPair { - /// The pair of collider involved. - pub pair: ColliderPair, - /// The state of proximity between the two colliders. - pub proximity: Proximity, - #[cfg_attr(feature = "serde-serialize", serde(skip))] - pub(crate) detector: Option, - #[cfg_attr(feature = "serde-serialize", serde(skip))] - pub(crate) detector_workspace: Option>, -} - -// TODO: use the `derive(Clone)` instead? -impl Clone for ProximityPair { - fn clone(&self) -> Self { - ProximityPair { - pair: self.pair.clone(), - proximity: self.proximity.clone(), - detector: None, - detector_workspace: None, - } - } -} - -impl ProximityPair { - pub(crate) fn new( - pair: ColliderPair, - detector: ProximityPhase, - detector_workspace: Option>, - ) -> Self { - Self { - pair, - proximity: Proximity::Disjoint, - detector: Some(detector), - detector_workspace, - } - } -} diff --git a/src/geometry/user_callbacks.rs b/src/geometry/user_callbacks.rs index ae0119f..629f707 100644 --- a/src/geometry/user_callbacks.rs +++ b/src/geometry/user_callbacks.rs @@ -37,21 +37,21 @@ pub trait ContactPairFilter: Send + Sync { fn filter_contact_pair(&self, context: &PairFilterContext) -> Option; } -/// User-defined filter for potential proximity pairs detected by the broad-phase. +/// User-defined filter for potential intersection pairs detected by the broad-phase. /// /// This can be used to apply custom logic in order to decide whether two colliders -/// should have their proximity computed by the narrow-phase. +/// should have their intersection computed by the narrow-phase. pub trait ProximityPairFilter: Send + Sync { - /// Applies the proximity pair filter. + /// Applies the intersection pair filter. /// - /// Note that using a proximity pair filter will replace the default proximity filtering - /// which consists of preventing proximity computation between two non-dynamic bodies. + /// Note that using an intersection pair filter will replace the default intersection filtering + /// which consists of preventing intersection computation between two non-dynamic bodies. /// /// This filtering method is called after taking into account the colliders collision groups. /// /// If this returns `false`, then the narrow-phase will ignore this pair and - /// not compute any proximity information for it. - /// If this return `true` then the narrow-phase will compute proximity + /// not compute any intersection information for it. + /// If this return `true` then the narrow-phase will compute intersection /// information for this pair. - fn filter_proximity_pair(&self, context: &PairFilterContext) -> bool; + fn filter_intersection_pair(&self, context: &PairFilterContext) -> bool; } diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index 188be27..e80b9e8 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -64,7 +64,7 @@ impl CollisionPipeline { contact_pair_filter, events, ); - narrow_phase.compute_proximities( + narrow_phase.compute_intersections( prediction_distance, bodies, colliders, diff --git a/src/pipeline/event_handler.rs b/src/pipeline/event_handler.rs index 67e4a78..9d7b17a 100644 --- a/src/pipeline/event_handler.rs +++ b/src/pipeline/event_handler.rs @@ -1,14 +1,14 @@ -use crate::geometry::{ContactEvent, ProximityEvent}; +use crate::geometry::{ContactEvent, IntersectionEvent}; use crossbeam::channel::Sender; /// Trait implemented by structures responsible for handling events generated by the physics engine. /// /// Implementors of this trait will typically collect these events for future processing. pub trait EventHandler: Send + Sync { - /// Handle a proximity event. + /// Handle an intersection event. /// - /// A proximity event is emitted when the state of proximity between two colliders changes. - fn handle_proximity_event(&self, event: ProximityEvent); + /// A intersection event is emitted when the state of intersection between two colliders changes. + fn handle_intersection_event(&self, event: IntersectionEvent); /// Handle a contact event. /// /// A contact event is emitted when two collider start or stop touching, independently from the @@ -17,32 +17,32 @@ pub trait EventHandler: Send + Sync { } impl EventHandler for () { - fn handle_proximity_event(&self, _event: ProximityEvent) {} + fn handle_intersection_event(&self, _event: IntersectionEvent) {} fn handle_contact_event(&self, _event: ContactEvent) {} } /// A physics event handler that collects events into a crossbeam channel. pub struct ChannelEventCollector { - proximity_event_sender: Sender, + intersection_event_sender: Sender, contact_event_sender: Sender, } impl ChannelEventCollector { /// Initialize a new physics event handler from crossbeam channel senders. pub fn new( - proximity_event_sender: Sender, + intersection_event_sender: Sender, contact_event_sender: Sender, ) -> Self { Self { - proximity_event_sender, + intersection_event_sender, contact_event_sender, } } } impl EventHandler for ChannelEventCollector { - fn handle_proximity_event(&self, event: ProximityEvent) { - let _ = self.proximity_event_sender.send(event); + fn handle_intersection_event(&self, event: IntersectionEvent) { + let _ = self.intersection_event_sender.send(event); } fn handle_contact_event(&self, event: ContactEvent) { diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index dc4b69f..ccc60e0 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -118,7 +118,7 @@ impl PhysicsPipeline { contact_pair_filter, events, ); - narrow_phase.compute_proximities( + narrow_phase.compute_intersections( integration_parameters.prediction_distance, bodies, colliders, -- cgit