diff options
| author | Crozet Sébastien <developer@crozet.re> | 2020-12-31 18:23:14 +0100 |
|---|---|---|
| committer | Crozet Sébastien <developer@crozet.re> | 2020-12-31 18:23:14 +0100 |
| commit | a1aa8855f76168d8af14244a54c9f28d15696342 (patch) | |
| tree | 4fcfcad9d2b79a21e0422a53a515c31e2d2dde04 /src | |
| parent | 7b098606c230256c72b73291c15cbd5fabe02653 (diff) | |
| download | rapier-a1aa8855f76168d8af14244a54c9f28d15696342.tar.gz rapier-a1aa8855f76168d8af14244a54c9f28d15696342.tar.bz2 rapier-a1aa8855f76168d8af14244a54c9f28d15696342.zip | |
Query pipeline: add methods to collect all intersections with a point or a shape.
Diffstat (limited to 'src')
| -rw-r--r-- | src/pipeline/query_pipeline.rs | 89 |
1 files changed, 66 insertions, 23 deletions
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<Real>, + 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); } - */ } |
