Merge pull request #158 from dimforge/query_pipeline_filter
Add the ability to pass a custom filter to all the QueryPipeline queries.
This commit is contained in:
@@ -35,7 +35,8 @@ pub struct QueryPipeline {
|
|||||||
struct QueryPipelineAsCompositeShape<'a> {
|
struct QueryPipelineAsCompositeShape<'a> {
|
||||||
query_pipeline: &'a QueryPipeline,
|
query_pipeline: &'a QueryPipeline,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&'a dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates how the colliders position should be taken into account when
|
/// Indicates how the colliders position should be taken into account when
|
||||||
@@ -64,7 +65,9 @@ impl<'a> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a> {
|
|||||||
mut f: impl FnMut(Option<&Isometry<Real>>, &Self::PartShape),
|
mut f: impl FnMut(Option<&Isometry<Real>>, &Self::PartShape),
|
||||||
) {
|
) {
|
||||||
if let Some(collider) = self.colliders.get(shape_id) {
|
if let Some(collider) = self.colliders.get(shape_id) {
|
||||||
if collider.collision_groups.test(self.groups) {
|
if collider.collision_groups.test(self.query_groups)
|
||||||
|
&& self.filter.map(|f| f(shape_id, collider)).unwrap_or(true)
|
||||||
|
{
|
||||||
f(Some(collider.position()), collider.shape())
|
f(Some(collider.position()), collider.shape())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,12 +101,14 @@ impl QueryPipeline {
|
|||||||
fn as_composite_shape<'a>(
|
fn as_composite_shape<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&'a dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> QueryPipelineAsCompositeShape<'a> {
|
) -> QueryPipelineAsCompositeShape<'a> {
|
||||||
QueryPipelineAsCompositeShape {
|
QueryPipelineAsCompositeShape {
|
||||||
query_pipeline: self,
|
query_pipeline: self,
|
||||||
colliders,
|
colliders,
|
||||||
groups,
|
query_groups,
|
||||||
|
filter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,15 +224,24 @@ impl QueryPipeline {
|
|||||||
/// - `ray`: the ray to cast.
|
/// - `ray`: the ray to cast.
|
||||||
/// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively
|
/// - `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.
|
/// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray.
|
||||||
|
/// - `solid`: if this is `true` an impact at time 0.0 (i.e. at the ray origin) is returned if
|
||||||
|
/// it starts inside of a shape. If this `false` then the ray will hit the shape's boundary
|
||||||
|
/// even if its starts inside of it.
|
||||||
|
/// - `query_groups`: the interaction groups which will be tested against the collider's `contact_group`
|
||||||
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// - `filter`: a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn cast_ray(
|
pub fn cast_ray(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
ray: &Ray,
|
ray: &Ray,
|
||||||
max_toi: Real,
|
max_toi: Real,
|
||||||
solid: bool,
|
solid: bool,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, Real)> {
|
) -> Option<(ColliderHandle, Real)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor =
|
let mut visitor =
|
||||||
RayCompositeShapeToiBestFirstVisitor::new(&pipeline_shape, ray, max_toi, solid);
|
RayCompositeShapeToiBestFirstVisitor::new(&pipeline_shape, ray, max_toi, solid);
|
||||||
|
|
||||||
@@ -241,15 +255,24 @@ impl QueryPipeline {
|
|||||||
/// - `ray`: the ray to cast.
|
/// - `ray`: the ray to cast.
|
||||||
/// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively
|
/// - `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.
|
/// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray.
|
||||||
|
/// - `solid`: if this is `true` an impact at time 0.0 (i.e. at the ray origin) is returned if
|
||||||
|
/// it starts inside of a shape. If this `false` then the ray will hit the shape's boundary
|
||||||
|
/// even if its starts inside of it.
|
||||||
|
/// - `query_groups`: the interaction groups which will be tested against the collider's `contact_group`
|
||||||
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// - `filter`: a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn cast_ray_and_get_normal(
|
pub fn cast_ray_and_get_normal(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
ray: &Ray,
|
ray: &Ray,
|
||||||
max_toi: Real,
|
max_toi: Real,
|
||||||
solid: bool,
|
solid: bool,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, RayIntersection)> {
|
) -> Option<(ColliderHandle, RayIntersection)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor = RayCompositeShapeToiAndNormalBestFirstVisitor::new(
|
let mut visitor = RayCompositeShapeToiAndNormalBestFirstVisitor::new(
|
||||||
&pipeline_shape,
|
&pipeline_shape,
|
||||||
ray,
|
ray,
|
||||||
@@ -267,6 +290,14 @@ impl QueryPipeline {
|
|||||||
/// - `ray`: the ray to cast.
|
/// - `ray`: the ray to cast.
|
||||||
/// - `max_toi`: the maximum time-of-impact that can be reported by this cast. This effectively
|
/// - `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.
|
/// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray.
|
||||||
|
/// - `solid`: if this is `true` an impact at time 0.0 (i.e. at the ray origin) is returned if
|
||||||
|
/// it starts inside of a shape. If this `false` then the ray will hit the shape's boundary
|
||||||
|
/// even if its starts inside of it.
|
||||||
|
/// - `query_groups`: the interaction groups which will be tested against the collider's `contact_group`
|
||||||
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// - `filter`: a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
/// - `callback`: function executed on each collider for which a ray intersection has been found.
|
/// - `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`,
|
/// There is no guarantees on the order the results will be yielded. If this callback returns `false`,
|
||||||
/// this method will exit early, ignore any further raycast.
|
/// this method will exit early, ignore any further raycast.
|
||||||
@@ -276,12 +307,15 @@ impl QueryPipeline {
|
|||||||
ray: &Ray,
|
ray: &Ray,
|
||||||
max_toi: Real,
|
max_toi: Real,
|
||||||
solid: bool,
|
solid: bool,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool,
|
mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool,
|
||||||
) {
|
) {
|
||||||
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
if let Some(coll) = colliders.get(*handle) {
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
if coll.collision_groups.test(groups) {
|
if coll.collision_groups.test(query_groups)
|
||||||
|
&& filter.map(|f| f(*handle, coll)).unwrap_or(true)
|
||||||
|
{
|
||||||
if let Some(hit) =
|
if let Some(hit) =
|
||||||
coll.shape()
|
coll.shape()
|
||||||
.cast_ray_and_get_normal(coll.position(), ray, max_toi, solid)
|
.cast_ray_and_get_normal(coll.position(), ray, max_toi, solid)
|
||||||
@@ -304,16 +338,20 @@ impl QueryPipeline {
|
|||||||
/// * `colliders` - The set of colliders taking part in this pipeline.
|
/// * `colliders` - The set of colliders taking part in this pipeline.
|
||||||
/// * `shape_pos` - The position of the shape used for the intersection test.
|
/// * `shape_pos` - The position of the shape used for the intersection test.
|
||||||
/// * `shape` - 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
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// hit the colliders with collision groups compatible with the ray's group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn intersection_with_shape(
|
pub fn intersection_with_shape(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
shape_pos: &Isometry<Real>,
|
shape_pos: &Isometry<Real>,
|
||||||
shape: &dyn Shape,
|
shape: &dyn Shape,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<ColliderHandle> {
|
) -> Option<ColliderHandle> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor = IntersectionCompositeShapeShapeBestFirstVisitor::new(
|
let mut visitor = IntersectionCompositeShapeShapeBestFirstVisitor::new(
|
||||||
&*self.query_dispatcher,
|
&*self.query_dispatcher,
|
||||||
shape_pos,
|
shape_pos,
|
||||||
@@ -336,16 +374,20 @@ impl QueryPipeline {
|
|||||||
/// itself). If it is set to `false` the collider shapes are considered to be hollow
|
/// 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
|
/// (if the point is located inside of an hollow shape, it is projected on the shape's
|
||||||
/// boundary).
|
/// boundary).
|
||||||
/// * `groups` - The bit groups and filter associated to the point to project, in order to only
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// project on colliders with collision groups compatible with the ray's group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn project_point(
|
pub fn project_point(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
point: &Point<Real>,
|
point: &Point<Real>,
|
||||||
solid: bool,
|
solid: bool,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, PointProjection)> {
|
) -> Option<(ColliderHandle, PointProjection)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor =
|
let mut visitor =
|
||||||
PointCompositeShapeProjBestFirstVisitor::new(&pipeline_shape, point, solid);
|
PointCompositeShapeProjBestFirstVisitor::new(&pipeline_shape, point, solid);
|
||||||
|
|
||||||
@@ -359,20 +401,25 @@ impl QueryPipeline {
|
|||||||
/// # Parameters
|
/// # Parameters
|
||||||
/// * `colliders` - The set of colliders taking part in this pipeline.
|
/// * `colliders` - The set of colliders taking part in this pipeline.
|
||||||
/// * `point` - The point used for the containment test.
|
/// * `point` - The point used for the containment test.
|
||||||
/// * `groups` - The bit groups and filter associated to the point to test, in order to only
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// test on colliders with collision groups compatible with the ray's group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
/// * `callback` - A function called with each collider with a shape
|
/// * `callback` - A function called with each collider with a shape
|
||||||
/// containing the `point`.
|
/// containing the `point`.
|
||||||
pub fn intersections_with_point<'a>(
|
pub fn intersections_with_point<'a>(
|
||||||
&self,
|
&self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
point: &Point<Real>,
|
point: &Point<Real>,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
||||||
) {
|
) {
|
||||||
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
if let Some(coll) = colliders.get(*handle) {
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
if coll.collision_groups.test(groups)
|
if coll.collision_groups.test(query_groups)
|
||||||
|
&& filter.map(|f| f(*handle, coll)).unwrap_or(true)
|
||||||
&& coll.shape().contains_point(coll.position(), point)
|
&& coll.shape().contains_point(coll.position(), point)
|
||||||
{
|
{
|
||||||
return callback(*handle, coll);
|
return callback(*handle, coll);
|
||||||
@@ -399,15 +446,19 @@ impl QueryPipeline {
|
|||||||
/// itself). If it is set to `false` the collider shapes are considered to be hollow
|
/// 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
|
/// (if the point is located inside of an hollow shape, it is projected on the shape's
|
||||||
/// boundary).
|
/// boundary).
|
||||||
/// * `groups` - The bit groups and filter associated to the point to project, in order to only
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// project on colliders with collision groups compatible with the ray's group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn project_point_and_get_feature(
|
pub fn project_point_and_get_feature(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
point: &Point<Real>,
|
point: &Point<Real>,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, PointProjection, FeatureId)> {
|
) -> Option<(ColliderHandle, PointProjection, FeatureId)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor =
|
let mut visitor =
|
||||||
PointCompositeShapeProjWithFeatureBestFirstVisitor::new(&pipeline_shape, point, false);
|
PointCompositeShapeProjWithFeatureBestFirstVisitor::new(&pipeline_shape, point, false);
|
||||||
self.quadtree
|
self.quadtree
|
||||||
@@ -437,8 +488,11 @@ impl QueryPipeline {
|
|||||||
/// * `shape` - The shape to cast.
|
/// * `shape` - The shape to cast.
|
||||||
/// * `max_toi` - The maximum time-of-impact that can be reported by this cast. This effectively
|
/// * `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`.
|
/// 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
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// test on colliders with collision groups compatible with this group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn cast_shape<'a>(
|
pub fn cast_shape<'a>(
|
||||||
&self,
|
&self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
@@ -447,9 +501,10 @@ impl QueryPipeline {
|
|||||||
shape: &dyn Shape,
|
shape: &dyn Shape,
|
||||||
max_toi: Real,
|
max_toi: Real,
|
||||||
target_distance: Real,
|
target_distance: Real,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, TOI)> {
|
) -> Option<(ColliderHandle, TOI)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let mut visitor = TOICompositeShapeShapeBestFirstVisitor::new(
|
let mut visitor = TOICompositeShapeShapeBestFirstVisitor::new(
|
||||||
&*self.query_dispatcher,
|
&*self.query_dispatcher,
|
||||||
shape_pos,
|
shape_pos,
|
||||||
@@ -468,10 +523,20 @@ impl QueryPipeline {
|
|||||||
/// * `colliders` - The set of colliders taking part in this pipeline.
|
/// * `colliders` - The set of colliders taking part in this pipeline.
|
||||||
/// * `shape_motion` - The motion of the shape.
|
/// * `shape_motion` - The motion of the shape.
|
||||||
/// * `shape` - The shape to cast.
|
/// * `shape` - The shape to cast.
|
||||||
/// * `max_toi` - The maximum time-of-impact that can be reported by this cast. This effectively
|
/// * `start_time` - The starting time of the interval where the motion takes place.
|
||||||
/// limits the distance traveled by the shape to `shapeVel.norm() * maxToi`.
|
/// * `end_time` - The end time of the interval where the motion takes place.
|
||||||
/// * `groups` - The bit groups and filter associated to the shape to cast, in order to only
|
/// * `stop_at_penetration` - If the casted shape starts in a penetration state with any
|
||||||
/// test on colliders with collision groups compatible with this group.
|
/// collider, two results are possible. If `stop_at_penetration` is `true` then, the
|
||||||
|
/// result will have a `toi` equal to `start_time`. If `stop_at_penetration` is `false`
|
||||||
|
/// then the nonlinear shape-casting will see if further motion wrt. the penetration normal
|
||||||
|
/// would result in tunnelling. If it does not (i.e. we have a separating velocity along
|
||||||
|
/// that normal) then the nonlinear shape-casting will attempt to find another impact,
|
||||||
|
/// at a time `> start_time` that could result in tunnelling.
|
||||||
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
pub fn nonlinear_cast_shape(
|
pub fn nonlinear_cast_shape(
|
||||||
&self,
|
&self,
|
||||||
colliders: &ColliderSet,
|
colliders: &ColliderSet,
|
||||||
@@ -480,9 +545,10 @@ impl QueryPipeline {
|
|||||||
start_time: Real,
|
start_time: Real,
|
||||||
end_time: Real,
|
end_time: Real,
|
||||||
stop_at_penetration: bool,
|
stop_at_penetration: bool,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
) -> Option<(ColliderHandle, TOI)> {
|
) -> Option<(ColliderHandle, TOI)> {
|
||||||
let pipeline_shape = self.as_composite_shape(colliders, groups);
|
let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter);
|
||||||
let pipeline_motion = NonlinearRigidMotion::identity();
|
let pipeline_motion = NonlinearRigidMotion::identity();
|
||||||
let mut visitor = NonlinearTOICompositeShapeShapeBestFirstVisitor::new(
|
let mut visitor = NonlinearTOICompositeShapeShapeBestFirstVisitor::new(
|
||||||
&*self.query_dispatcher,
|
&*self.query_dispatcher,
|
||||||
@@ -504,15 +570,19 @@ impl QueryPipeline {
|
|||||||
/// * `shapePos` - The position of the shape to test.
|
/// * `shapePos` - The position of the shape to test.
|
||||||
/// * `shapeRot` - The orientation of the shape to test.
|
/// * `shapeRot` - The orientation of the shape to test.
|
||||||
/// * `shape` - 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
|
/// * `query_groups` - the interaction groups which will be tested against the collider's `contact_group`
|
||||||
/// test on colliders with collision groups compatible with this group.
|
/// to determine if it should be taken into account by this query.
|
||||||
|
/// * `filter` - a more fine-grained filter. A collider is taken into account by this query if
|
||||||
|
/// its `contact_group` is compatible with the `query_groups`, and if this `filter`
|
||||||
|
/// is either `None` or returns `true`.
|
||||||
/// * `callback` - A function called with the handles of each collider intersecting the `shape`.
|
/// * `callback` - A function called with the handles of each collider intersecting the `shape`.
|
||||||
pub fn intersections_with_shape<'a>(
|
pub fn intersections_with_shape<'a>(
|
||||||
&self,
|
&self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
shape_pos: &Isometry<Real>,
|
shape_pos: &Isometry<Real>,
|
||||||
shape: &dyn Shape,
|
shape: &dyn Shape,
|
||||||
groups: InteractionGroups,
|
query_groups: InteractionGroups,
|
||||||
|
filter: Option<&dyn Fn(ColliderHandle, &Collider) -> bool>,
|
||||||
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
||||||
) {
|
) {
|
||||||
let dispatcher = &*self.query_dispatcher;
|
let dispatcher = &*self.query_dispatcher;
|
||||||
@@ -520,7 +590,9 @@ impl QueryPipeline {
|
|||||||
|
|
||||||
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
if let Some(coll) = colliders.get(*handle) {
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
if coll.collision_groups.test(groups) {
|
if coll.collision_groups.test(query_groups)
|
||||||
|
&& filter.map(|f| f(*handle, coll)).unwrap_or(true)
|
||||||
|
{
|
||||||
let pos12 = inv_shape_pos * coll.position();
|
let pos12 = inv_shape_pos * coll.position();
|
||||||
|
|
||||||
if dispatcher.intersection_test(&pos12, shape, coll.shape()) == Ok(true) {
|
if dispatcher.intersection_test(&pos12, shape, coll.shape()) == Ok(true) {
|
||||||
|
|||||||
@@ -1000,6 +1000,7 @@ impl Testbed {
|
|||||||
f32::MAX,
|
f32::MAX,
|
||||||
true,
|
true,
|
||||||
InteractionGroups::all(),
|
InteractionGroups::all(),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((handle, _)) = hit {
|
if let Some((handle, _)) = hit {
|
||||||
|
|||||||
Reference in New Issue
Block a user