From 9bf1321f8f1d2e116f44c2461a53f302c4ef4171 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 8 Dec 2020 17:31:49 +0100 Subject: Outsource the contact manifold, SAT, and some shapes. --- src/pipeline/query_pipeline.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 665fee8..dee4312 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -74,7 +74,7 @@ impl QueryPipeline { for handle in inter { if let Some(collider) = colliders.get(handle) { if collider.collision_groups.test(groups) { - if let Some(inter) = collider.shape().toi_and_normal_with_ray( + if let Some(inter) = collider.shape().cast_ray_and_get_normal( collider.position(), ray, max_toi, @@ -118,7 +118,7 @@ impl QueryPipeline { let collider = &colliders[handle]; if collider.collision_groups.test(groups) { - if let Some(inter) = collider.shape().toi_and_normal_with_ray( + if let Some(inter) = collider.shape().cast_ray_and_get_normal( collider.position(), ray, max_toi, -- cgit From cc6d1b973002b4d366bc81ec6bf9e8240ad7b404 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 14 Dec 2020 15:51:43 +0100 Subject: Outsource the Shape trait, wquadtree, and shape types. --- src/pipeline/query_pipeline.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index dee4312..11fac1c 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -47,7 +47,10 @@ impl QueryPipeline { } } - self.quadtree.update(colliders, self.dilation_factor); + self.quadtree.update( + |handle| colliders[*handle].compute_aabb(), + self.dilation_factor, + ); } /// Find the closest intersection between a ray and a set of collider. -- cgit 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/pipeline/collision_pipeline.rs | 2 +- src/pipeline/event_handler.rs | 20 ++++++++++---------- src/pipeline/physics_pipeline.rs | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/pipeline') 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 From 94c67a0c31e9da373c3aca3560dc9accc3308a7a Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 28 Dec 2020 18:12:33 +0100 Subject: Support compound shapes. --- src/pipeline/query_pipeline.rs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 11fac1c..ea5fe89 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -1,13 +1,15 @@ use crate::dynamics::RigidBodySet; use crate::geometry::{ - Collider, ColliderHandle, ColliderSet, InteractionGroups, Ray, RayIntersection, WQuadtree, + Collider, ColliderHandle, ColliderSet, InteractionGroups, Ray, RayIntersection, SimdQuadTree, }; +use cdl::query::TOI; +use cdl::shape::Shape; /// A pipeline for performing queries on all the colliders of a scene. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[derive(Clone)] pub struct QueryPipeline { - quadtree: WQuadtree, + quadtree: SimdQuadTree, tree_built: bool, dilation_factor: f32, } @@ -22,7 +24,7 @@ impl QueryPipeline { /// Initializes an empty query pipeline. pub fn new() -> Self { Self { - quadtree: WQuadtree::new(), + quadtree: SimdQuadTree::new(), tree_built: false, dilation_factor: 0.01, } @@ -105,7 +107,7 @@ impl QueryPipeline { /// - `callback`: function executed on each collider for which a ray intersection has been found. /// There is no guarantees on the order the results will be yielded. If this callback returns `false`, /// this method will exit early, ignory any further raycast. - pub fn interferences_with_ray<'a>( + pub fn intersections_with_ray<'a>( &self, colliders: &'a ColliderSet, ray: &Ray, @@ -134,4 +136,28 @@ impl QueryPipeline { } } } + + /* + pub fn cast_shape<'a>( + &self, + colliders: &'a ColliderSet, + shape_pos: &Isometry, + shape: &dyn Shape, + max_toi: f32, + groups: InteractionGroups, + ) -> Option<(ColliderHandle, &'a Collider, TOI)> { + unimplemented!() + } + + /// Gets all the colliders with a shape intersecting the given `shape`. + pub fn intersections_with_shape<'a>( + &self, + colliders: &'a ColliderSet, + shape_pos: &Isometry, + shape: &dyn Shape, + groups: InteractionGroups, + mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool, + ) { + } + */ } -- cgit From 967145a9492175be59e8db33299b1687d69d84e2 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 11:16:03 +0100 Subject: Perform contact sorting in the narrow-phase directly. --- src/pipeline/collision_pipeline.rs | 8 +------- src/pipeline/physics_pipeline.rs | 8 +------- src/pipeline/query_pipeline.rs | 2 -- 3 files changed, 2 insertions(+), 16 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index e80b9e8..06c581b 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -64,13 +64,7 @@ impl CollisionPipeline { contact_pair_filter, events, ); - narrow_phase.compute_intersections( - prediction_distance, - bodies, - colliders, - proximity_pair_filter, - events, - ); + narrow_phase.compute_intersections(bodies, colliders, proximity_pair_filter, events); bodies.update_active_set_with_contacts( colliders, diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index ccc60e0..e56f8e0 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -118,13 +118,7 @@ impl PhysicsPipeline { contact_pair_filter, events, ); - narrow_phase.compute_intersections( - integration_parameters.prediction_distance, - bodies, - colliders, - proximity_pair_filter, - events, - ); + narrow_phase.compute_intersections(bodies, colliders, proximity_pair_filter, events); // println!("Compute contact time: {}", instant::now() - t); self.counters.stages.island_construction_time.start(); diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index ea5fe89..9943099 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -2,8 +2,6 @@ use crate::dynamics::RigidBodySet; use crate::geometry::{ Collider, ColliderHandle, ColliderSet, InteractionGroups, Ray, RayIntersection, SimdQuadTree, }; -use cdl::query::TOI; -use cdl::shape::Shape; /// A pipeline for performing queries on all the colliders of a scene. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -- cgit From 7b098606c230256c72b73291c15cbd5fabe02653 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 16:30:38 +0100 Subject: QueryPipeline: add shape casting, point projection, and intersection queries. --- src/pipeline/query_pipeline.rs | 239 ++++++++++++++++++++++++++++++++++------- 1 file changed, 203 insertions(+), 36 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 9943099..1c07a3b 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -1,15 +1,68 @@ +use crate::cdl::motion::RigidMotion; use crate::dynamics::RigidBodySet; use crate::geometry::{ - Collider, ColliderHandle, ColliderSet, InteractionGroups, Ray, RayIntersection, SimdQuadTree, + Collider, ColliderHandle, ColliderSet, InteractionGroups, PointProjection, Ray, + RayIntersection, SimdQuadTree, }; +use crate::math::{Isometry, Point, Real, Vector}; +use cdl::query::details::{ + IntersectionCompositeShapeShapeBestFirstVisitor, + NonlinearTOICompositeShapeShapeBestFirstVisitor, PointCompositeShapeProjBestFirstVisitor, + PointCompositeShapeProjWithFeatureBestFirstVisitor, + RayCompositeShapeToiAndNormalBestFirstVisitor, RayCompositeShapeToiBestFirstVisitor, + TOICompositeShapeShapeBestFirstVisitor, +}; +use cdl::query::{DefaultQueryDispatcher, QueryDispatcher, TOI}; +use cdl::shape::{FeatureId, Shape, TypedSimdCompositeShape}; +use std::sync::Arc; /// A pipeline for performing queries on all the colliders of a scene. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[derive(Clone)] pub struct QueryPipeline { + #[cfg_attr( + feature = "serde-serialize", + serde(skip, default = "crate::geometry::default_query_dispatcher") + )] + query_dispatcher: Arc, quadtree: SimdQuadTree, tree_built: bool, - dilation_factor: f32, + dilation_factor: Real, +} + +struct QueryPipelineAsCompositeShape<'a> { + query_pipeline: &'a QueryPipeline, + colliders: &'a ColliderSet, + groups: InteractionGroups, +} + +impl<'a> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a> { + type PartShape = dyn Shape; + type PartId = ColliderHandle; + + fn map_typed_part_at( + &self, + shape_id: Self::PartId, + mut f: impl FnMut(Option<&Isometry>, &Self::PartShape), + ) { + if let Some(collider) = self.colliders.get(shape_id) { + if collider.collision_groups.test(self.groups) { + f(Some(collider.position()), collider.shape()) + } + } + } + + fn map_untyped_part_at( + &self, + shape_id: Self::PartId, + mut f: impl FnMut(Option<&Isometry>, &Self::PartShape), + ) { + self.map_typed_part_at(shape_id, f); + } + + fn typed_quadtree(&self) -> &SimdQuadTree { + &self.query_pipeline.quadtree + } } impl Default for QueryPipeline { @@ -21,7 +74,27 @@ impl Default for QueryPipeline { impl QueryPipeline { /// Initializes an empty query pipeline. pub fn new() -> Self { + Self::with_query_dispatcher(DefaultQueryDispatcher) + } + + fn as_composite_shape<'a>( + &'a self, + colliders: &'a ColliderSet, + groups: InteractionGroups, + ) -> QueryPipelineAsCompositeShape<'a> { + QueryPipelineAsCompositeShape { + query_pipeline: self, + colliders, + groups, + } + } + + pub fn with_query_dispatcher(d: D) -> Self + where + D: 'static + QueryDispatcher, + { Self { + query_dispatcher: Arc::new(d), quadtree: SimdQuadTree::new(), tree_built: false, dilation_factor: 0.01, @@ -59,40 +132,46 @@ impl QueryPipeline { /// - `position`: the position of this shape. /// - `ray`: the ray to cast. /// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively - /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `f32::MAX` for an unbounded ray. - pub fn cast_ray<'a>( + /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray. + pub fn cast_ray( &self, - colliders: &'a ColliderSet, + colliders: &ColliderSet, ray: &Ray, - max_toi: f32, + max_toi: Real, + solid: bool, groups: InteractionGroups, - ) -> Option<(ColliderHandle, &'a Collider, RayIntersection)> { - // TODO: avoid allocation? - let mut inter = Vec::new(); - self.quadtree.cast_ray(ray, max_toi, &mut inter); + ) -> Option<(ColliderHandle, Real)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = + RayCompositeShapeToiBestFirstVisitor::new(&pipeline_shape, ray, max_toi, solid); - let mut best = f32::MAX; - let mut result = None; + self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) + } - for handle in inter { - if let Some(collider) = colliders.get(handle) { - if collider.collision_groups.test(groups) { - if let Some(inter) = collider.shape().cast_ray_and_get_normal( - collider.position(), - ray, - max_toi, - true, - ) { - if inter.toi < best { - best = inter.toi; - result = Some((handle, collider, inter)); - } - } - } - } - } + /// Find the closest intersection between a ray and a set of collider. + /// + /// # Parameters + /// - `position`: the position of this shape. + /// - `ray`: the ray to cast. + /// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively + /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray. + pub fn cast_ray_and_get_normal( + &self, + colliders: &ColliderSet, + ray: &Ray, + max_toi: Real, + solid: bool, + groups: InteractionGroups, + ) -> Option<(ColliderHandle, RayIntersection)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = RayCompositeShapeToiAndNormalBestFirstVisitor::new( + &pipeline_shape, + ray, + max_toi, + solid, + ); - result + self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) } /// Find the all intersections between a ray and a set of collider and passes them to a callback. @@ -101,7 +180,7 @@ impl QueryPipeline { /// - `position`: the position of this shape. /// - `ray`: the ray to cast. /// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively - /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `f32::MAX` for an unbounded ray. + /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray. /// - `callback`: function executed on each collider for which a ray intersection has been found. /// There is no guarantees on the order the results will be yielded. If this callback returns `false`, /// this method will exit early, ignory any further raycast. @@ -109,7 +188,7 @@ impl QueryPipeline { &self, colliders: &'a ColliderSet, ray: &Ray, - max_toi: f32, + max_toi: Real, groups: InteractionGroups, mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool, ) { @@ -135,18 +214,106 @@ impl QueryPipeline { } } - /* + /// Find up to one collider intersecting the given shape. + fn intersection_with_shape( + &self, + colliders: &ColliderSet, + shape_pos: &Isometry, + shape: &dyn Shape, + groups: InteractionGroups, + ) -> Option { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = IntersectionCompositeShapeShapeBestFirstVisitor::new( + &*self.query_dispatcher, + shape_pos, + &pipeline_shape, + shape, + ); + + self.quadtree + .traverse_best_first(&mut visitor) + .map(|h| (h.1 .0)) + } + + // TODO: intersections_with_point (collect all colliders containing the point). + + /// Projects a point on the scene. + fn project_point( + &self, + colliders: &ColliderSet, + point: &Point, + solid: bool, + groups: InteractionGroups, + ) -> Option<(ColliderHandle, PointProjection)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = + PointCompositeShapeProjBestFirstVisitor::new(&pipeline_shape, point, solid); + + self.quadtree + .traverse_best_first(&mut visitor) + .map(|h| (h.1 .1, h.1 .0)) + } + + /// Projects a point on the scene and get + fn project_point_and_get_feature( + &self, + colliders: &ColliderSet, + point: &Point, + groups: InteractionGroups, + ) -> Option<(ColliderHandle, PointProjection, FeatureId)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = + PointCompositeShapeProjWithFeatureBestFirstVisitor::new(&pipeline_shape, point, false); + self.quadtree + .traverse_best_first(&mut visitor) + .map(|h| (h.1 .1 .0, h.1 .0, h.1 .1 .1)) + } + pub fn cast_shape<'a>( &self, colliders: &'a ColliderSet, shape_pos: &Isometry, + shape_vel: &Vector, shape: &dyn Shape, - max_toi: f32, + max_toi: Real, + target_distance: Real, groups: InteractionGroups, - ) -> Option<(ColliderHandle, &'a Collider, TOI)> { - unimplemented!() + ) -> Option<(ColliderHandle, TOI)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = TOICompositeShapeShapeBestFirstVisitor::new( + &*self.query_dispatcher, + shape_pos, + shape_vel, + &pipeline_shape, + shape, + max_toi, + target_distance, + ); + self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) + } + + pub fn nonlinear_cast_shape( + &self, + colliders: &ColliderSet, + shape_motion: &dyn RigidMotion, + shape: &dyn Shape, + max_toi: Real, + target_distance: Real, + groups: InteractionGroups, + ) -> Option<(ColliderHandle, TOI)> { + let pipeline_shape = self.as_composite_shape(colliders, groups); + let mut visitor = NonlinearTOICompositeShapeShapeBestFirstVisitor::new( + &*self.query_dispatcher, + shape_motion, + &pipeline_shape, + shape, + max_toi, + target_distance, + ); + self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) } + /* /// Gets all the colliders with a shape intersecting the given `shape`. pub fn intersections_with_shape<'a>( &self, -- cgit From a1aa8855f76168d8af14244a54c9f28d15696342 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 18:23:14 +0100 Subject: Query pipeline: add methods to collect all intersections with a point or a shape. --- src/pipeline/query_pipeline.rs | 89 +++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 23 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 1c07a3b..9e20088 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -12,6 +12,9 @@ use cdl::query::details::{ RayCompositeShapeToiAndNormalBestFirstVisitor, RayCompositeShapeToiBestFirstVisitor, TOICompositeShapeShapeBestFirstVisitor, }; +use cdl::query::visitors::{ + BoundingVolumeIntersectionsVisitor, PointIntersectionsVisitor, RayIntersectionsVisitor, +}; use cdl::query::{DefaultQueryDispatcher, QueryDispatcher, TOI}; use cdl::shape::{FeatureId, Shape, TypedSimdCompositeShape}; use std::sync::Arc; @@ -183,35 +186,33 @@ impl QueryPipeline { /// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray. /// - `callback`: function executed on each collider for which a ray intersection has been found. /// There is no guarantees on the order the results will be yielded. If this callback returns `false`, - /// this method will exit early, ignory any further raycast. + /// this method will exit early, ignore any further raycast. pub fn intersections_with_ray<'a>( &self, colliders: &'a ColliderSet, ray: &Ray, max_toi: Real, + solid: bool, groups: InteractionGroups, mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool, ) { - // TODO: avoid allocation? - let mut inter = Vec::new(); - self.quadtree.cast_ray(ray, max_toi, &mut inter); - - for handle in inter { - let collider = &colliders[handle]; - - if collider.collision_groups.test(groups) { - if let Some(inter) = collider.shape().cast_ray_and_get_normal( - collider.position(), - ray, - max_toi, - true, - ) { - if !callback(handle, collider, inter) { - return; + let mut leaf_callback = &mut |handle: &ColliderHandle| { + if let Some(coll) = colliders.get(*handle) { + if coll.collision_groups.test(groups) { + if let Some(hit) = + coll.shape() + .cast_ray_and_get_normal(coll.position(), ray, max_toi, solid) + { + return callback(*handle, coll, hit); } } } - } + + true + }; + + let mut visitor = RayIntersectionsVisitor::new(ray, max_toi, &mut leaf_callback); + self.quadtree.traverse_depth_first(&mut visitor); } /// Find up to one collider intersecting the given shape. @@ -235,8 +236,6 @@ impl QueryPipeline { .map(|h| (h.1 .0)) } - // TODO: intersections_with_point (collect all colliders containing the point). - /// Projects a point on the scene. fn project_point( &self, @@ -254,6 +253,31 @@ impl QueryPipeline { .map(|h| (h.1 .1, h.1 .0)) } + /// Gets all the colliders containing the given point. + pub fn intersections_with_point<'a>( + &self, + colliders: &'a ColliderSet, + point: &Point, + groups: InteractionGroups, + mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool, + ) { + let mut leaf_callback = &mut |handle: &ColliderHandle| { + if let Some(coll) = colliders.get(*handle) { + if coll.collision_groups.test(groups) + && coll.shape().contains_point(coll.position(), point) + { + return callback(*handle, coll); + } + } + + true + }; + + let mut visitor = PointIntersectionsVisitor::new(point, &mut leaf_callback); + + self.quadtree.traverse_depth_first(&mut visitor); + } + /// Projects a point on the scene and get fn project_point_and_get_feature( &self, @@ -313,8 +337,7 @@ impl QueryPipeline { self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) } - /* - /// Gets all the colliders with a shape intersecting the given `shape`. + /// Gets all the colliders containing the given shape. pub fn intersections_with_shape<'a>( &self, colliders: &'a ColliderSet, @@ -323,6 +346,26 @@ impl QueryPipeline { groups: InteractionGroups, mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool, ) { + let dispatcher = &*self.query_dispatcher; + let inv_shape_pos = shape_pos.inverse(); + + let mut leaf_callback = &mut |handle: &ColliderHandle| { + if let Some(coll) = colliders.get(*handle) { + if coll.collision_groups.test(groups) { + let pos12 = inv_shape_pos * coll.position(); + + if dispatcher.intersection_test(&pos12, shape, coll.shape()) == Ok(true) { + return callback(*handle, coll); + } + } + } + + true + }; + + let shape_aabb = shape.compute_aabb(shape_pos); + let mut visitor = BoundingVolumeIntersectionsVisitor::new(&shape_aabb, &mut leaf_callback); + + self.quadtree.traverse_depth_first(&mut visitor); } - */ } -- cgit From aa61fe65e3ff0289ecab57b4053a3410cf6d4a87 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 4 Jan 2021 15:14:25 +0100 Subject: Add support of 64-bits reals. --- src/pipeline/collision_pipeline.rs | 3 ++- src/pipeline/physics_pipeline.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index 06c581b..8855af0 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -5,6 +5,7 @@ use crate::geometry::{ BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactPairFilter, NarrowPhase, ProximityPairFilter, }; +use crate::math::Real; use crate::pipeline::EventHandler; /// The collision pipeline, responsible for performing collision detection between colliders. @@ -38,7 +39,7 @@ impl CollisionPipeline { /// Executes one step of the collision detection. pub fn step( &mut self, - prediction_distance: f32, + prediction_distance: Real, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, bodies: &mut RigidBodySet, diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index e56f8e0..718dd10 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -10,7 +10,7 @@ use crate::geometry::{ BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactManifoldIndex, ContactPairFilter, NarrowPhase, ProximityPairFilter, }; -use crate::math::Vector; +use crate::math::{Real, Vector}; use crate::pipeline::EventHandler; /// The physics pipeline, responsible for stepping the whole physics simulation. @@ -62,7 +62,7 @@ impl PhysicsPipeline { /// Executes one timestep of the physics simulation. pub fn step( &mut self, - gravity: &Vector, + gravity: &Vector, integration_parameters: &IntegrationParameters, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, @@ -250,7 +250,7 @@ impl PhysicsPipeline { mod test { use crate::dynamics::{IntegrationParameters, JointSet, RigidBodyBuilder, RigidBodySet}; use crate::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase}; - use crate::math::Vector; + use crate::math::{Real, Vector}; use crate::pipeline::PhysicsPipeline; #[test] -- cgit From 261ed1ebed04fb594f612b66811350f63b73f104 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 6 Jan 2021 12:53:26 +0100 Subject: Fix 2D compilation. --- src/pipeline/query_pipeline.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 9e20088..5e0b2ea 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -58,7 +58,7 @@ impl<'a> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a> { fn map_untyped_part_at( &self, shape_id: Self::PartId, - mut f: impl FnMut(Option<&Isometry>, &Self::PartShape), + f: impl FnMut(Option<&Isometry>, &Self::PartShape), ) { self.map_typed_part_at(shape_id, f); } @@ -216,7 +216,7 @@ impl QueryPipeline { } /// Find up to one collider intersecting the given shape. - fn intersection_with_shape( + pub fn intersection_with_shape( &self, colliders: &ColliderSet, shape_pos: &Isometry, @@ -237,7 +237,7 @@ impl QueryPipeline { } /// Projects a point on the scene. - fn project_point( + pub fn project_point( &self, colliders: &ColliderSet, point: &Point, @@ -279,7 +279,7 @@ impl QueryPipeline { } /// Projects a point on the scene and get - fn project_point_and_get_feature( + pub fn project_point_and_get_feature( &self, colliders: &ColliderSet, point: &Point, -- cgit From 90db26eb501b65cda362dcef34777106f533248b Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Sat, 23 Jan 2021 13:34:03 +0100 Subject: Fix warnings in tests and testbed. --- src/pipeline/physics_pipeline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pipeline') diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index d59a534..cba256c 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -250,7 +250,7 @@ impl PhysicsPipeline { mod test { use crate::dynamics::{IntegrationParameters, JointSet, RigidBodyBuilder, RigidBodySet}; use crate::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase}; - use crate::math::{Real, Vector}; + use crate::math::Vector; use crate::pipeline::PhysicsPipeline; #[test] -- cgit From 8f7220f03d3c23574b9ece09d81d32e862f1b5c6 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Sun, 24 Jan 2021 11:13:44 +0100 Subject: Rename cdl to parry. --- src/pipeline/collision_pipeline.rs | 6 +++--- src/pipeline/physics_pipeline.rs | 4 ++-- src/pipeline/query_pipeline.rs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index 8855af0..866c3a5 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -2,8 +2,8 @@ use crate::dynamics::{JointSet, RigidBodySet}; use crate::geometry::{ - BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactPairFilter, NarrowPhase, - ProximityPairFilter, + BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactPairFilter, + IntersectionPairFilter, NarrowPhase, }; use crate::math::Real; use crate::pipeline::EventHandler; @@ -45,7 +45,7 @@ impl CollisionPipeline { bodies: &mut RigidBodySet, colliders: &mut ColliderSet, contact_pair_filter: Option<&dyn ContactPairFilter>, - proximity_pair_filter: Option<&dyn ProximityPairFilter>, + proximity_pair_filter: Option<&dyn IntersectionPairFilter>, events: &dyn EventHandler, ) { bodies.maintain(colliders); diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index cba256c..b5f123d 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -8,7 +8,7 @@ use crate::dynamics::{IntegrationParameters, JointSet, RigidBodySet}; use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver}; use crate::geometry::{ BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactManifoldIndex, - ContactPairFilter, NarrowPhase, ProximityPairFilter, + ContactPairFilter, IntersectionPairFilter, NarrowPhase, }; use crate::math::{Real, Vector}; use crate::pipeline::EventHandler; @@ -70,7 +70,7 @@ impl PhysicsPipeline { colliders: &mut ColliderSet, joints: &mut JointSet, contact_pair_filter: Option<&dyn ContactPairFilter>, - proximity_pair_filter: Option<&dyn ProximityPairFilter>, + proximity_pair_filter: Option<&dyn IntersectionPairFilter>, events: &dyn EventHandler, ) { self.counters.step_started(); diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 5e0b2ea..145dd87 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -1,22 +1,22 @@ -use crate::cdl::motion::RigidMotion; use crate::dynamics::RigidBodySet; use crate::geometry::{ Collider, ColliderHandle, ColliderSet, InteractionGroups, PointProjection, Ray, RayIntersection, SimdQuadTree, }; use crate::math::{Isometry, Point, Real, Vector}; -use cdl::query::details::{ +use crate::parry::motion::RigidMotion; +use parry::query::details::{ IntersectionCompositeShapeShapeBestFirstVisitor, NonlinearTOICompositeShapeShapeBestFirstVisitor, PointCompositeShapeProjBestFirstVisitor, PointCompositeShapeProjWithFeatureBestFirstVisitor, RayCompositeShapeToiAndNormalBestFirstVisitor, RayCompositeShapeToiBestFirstVisitor, TOICompositeShapeShapeBestFirstVisitor, }; -use cdl::query::visitors::{ +use parry::query::visitors::{ BoundingVolumeIntersectionsVisitor, PointIntersectionsVisitor, RayIntersectionsVisitor, }; -use cdl::query::{DefaultQueryDispatcher, QueryDispatcher, TOI}; -use cdl::shape::{FeatureId, Shape, TypedSimdCompositeShape}; +use parry::query::{DefaultQueryDispatcher, QueryDispatcher, TOI}; +use parry::shape::{FeatureId, Shape, TypedSimdCompositeShape}; use std::sync::Arc; /// A pipeline for performing queries on all the colliders of a scene. -- cgit From 8ff2bcc3ec666805aceedaa477bde89f2a577d1c Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 27 Jan 2021 14:20:14 +0100 Subject: Add all the missing docs. --- src/pipeline/query_pipeline.rs | 86 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 145dd87..8cc6a60 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -92,6 +92,10 @@ impl QueryPipeline { } } + /// Initializes an empty query pipeline with a custom `QueryDispatcher`. + /// + /// Use this constructor in order to use a custom `QueryDispatcher` that is + /// awary of your own user-defined shapes. pub fn with_query_dispatcher(d: D) -> Self where D: 'static + QueryDispatcher, @@ -215,7 +219,14 @@ impl QueryPipeline { self.quadtree.traverse_depth_first(&mut visitor); } - /// Find up to one collider intersecting the given shape. + /// Gets the handle of up to one collider intersecting the given shape. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `shape_pos` - The position of the shape used for the intersection test. + /// * `shape` - The shape used for the intersection test. + /// * `groups` - The bit groups and filter associated to the ray, in order to only + /// hit the colliders with collision groups compatible with the ray's group. pub fn intersection_with_shape( &self, colliders: &ColliderSet, @@ -236,7 +247,18 @@ impl QueryPipeline { .map(|h| (h.1 .0)) } - /// Projects a point on the scene. + /// Find the projection of a point on the closest collider. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `point` - The point to project. + /// * `solid` - If this is set to `true` then the collider shapes are considered to + /// be plain (if the point is located inside of a plain shape, its projection is the point + /// itself). If it is set to `false` the collider shapes are considered to be hollow + /// (if the point is located inside of an hollow shape, it is projected on the shape's + /// boundary). + /// * `groups` - The bit groups and filter associated to the point to project, in order to only + /// project on colliders with collision groups compatible with the ray's group. pub fn project_point( &self, colliders: &ColliderSet, @@ -253,7 +275,15 @@ impl QueryPipeline { .map(|h| (h.1 .1, h.1 .0)) } - /// Gets all the colliders containing the given point. + /// Find all the colliders containing the given point. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `point` - The point used for the containment test. + /// * `groups` - The bit groups and filter associated to the point to test, in order to only + /// test on colliders with collision groups compatible with the ray's group. + /// * `callback` - A function called with each collider with a shape + /// containing the `point`. pub fn intersections_with_point<'a>( &self, colliders: &'a ColliderSet, @@ -278,7 +308,20 @@ impl QueryPipeline { self.quadtree.traverse_depth_first(&mut visitor); } - /// Projects a point on the scene and get + /// Find the projection of a point on the closest collider. + /// + /// The results include the ID of the feature hit by the point. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `point` - The point to project. + /// * `solid` - If this is set to `true` then the collider shapes are considered to + /// be plain (if the point is located inside of a plain shape, its projection is the point + /// itself). If it is set to `false` the collider shapes are considered to be hollow + /// (if the point is located inside of an hollow shape, it is projected on the shape's + /// boundary). + /// * `groups` - The bit groups and filter associated to the point to project, in order to only + /// project on colliders with collision groups compatible with the ray's group. pub fn project_point_and_get_feature( &self, colliders: &ColliderSet, @@ -293,6 +336,20 @@ impl QueryPipeline { .map(|h| (h.1 .1 .0, h.1 .0, h.1 .1 .1)) } + /// Casts a shape at a constant linear velocity and retrieve the first collider it hits. + /// + /// This is similar to ray-casting except that we are casting a whole shape instead of + /// just a point (the ray origin). + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `shape_pos` - The initial position of the shape to cast. + /// * `shape_vel` - The constant velocity of the shape to cast (i.e. the cast direction). + /// * `shape` - The shape to cast. + /// * `max_toi` - The maximum time-of-impact that can be reported by this cast. This effectively + /// limits the distance traveled by the shape to `shapeVel.norm() * maxToi`. + /// * `groups` - The bit groups and filter associated to the shape to cast, in order to only + /// test on colliders with collision groups compatible with this group. pub fn cast_shape<'a>( &self, colliders: &'a ColliderSet, @@ -316,6 +373,16 @@ impl QueryPipeline { self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) } + /// Casts a shape with an arbitrary continuous motion and retrieve the first collider it hits. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `shape_motion` - The motion of the shape. + /// * `shape` - The shape to cast. + /// * `max_toi` - The maximum time-of-impact that can be reported by this cast. This effectively + /// limits the distance traveled by the shape to `shapeVel.norm() * maxToi`. + /// * `groups` - The bit groups and filter associated to the shape to cast, in order to only + /// test on colliders with collision groups compatible with this group. pub fn nonlinear_cast_shape( &self, colliders: &ColliderSet, @@ -337,7 +404,16 @@ impl QueryPipeline { self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1) } - /// Gets all the colliders containing the given shape. + /// Retrieve all the colliders intersecting the given shape. + /// + /// # Parameters + /// * `colliders` - The set of colliders taking part in this pipeline. + /// * `shapePos` - The position of the shape to test. + /// * `shapeRot` - The orientation of the shape to test. + /// * `shape` - The shape to test. + /// * `groups` - The bit groups and filter associated to the shape to test, in order to only + /// test on colliders with collision groups compatible with this group. + /// * `callback` - A function called with the handles of each collider intersecting the `shape`. pub fn intersections_with_shape<'a>( &self, colliders: &'a ColliderSet, -- cgit