Skip to content

Commit

Permalink
avoid allocate on spatial queries *_callback api
Browse files Browse the repository at this point in the history
  • Loading branch information
bnyu committed Aug 26, 2023
1 parent 884055a commit c5bbfeb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 45 deletions.
76 changes: 36 additions & 40 deletions src/plugins/spatial_query/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,18 +208,19 @@ impl SpatialQueryPipeline {
solid: bool,
query_filter: SpatialQueryFilter,
) -> Vec<RayHitData> {
let mut hits = 0;
let mut hits = Vec::with_capacity(10);
self.ray_hits_callback(
origin,
direction,
max_time_of_impact,
solid,
query_filter,
|_| {
hits += 1;
hits < max_hits
|hit| {
hits.push(hit);
(hits.len() as u32) < max_hits
},
)
);
hits
}

/// Casts a [ray](spatial_query#ray-casting) and computes all [hits](RayHitData), calling the given `callback`
Expand All @@ -246,10 +247,9 @@ impl SpatialQueryPipeline {
solid: bool,
query_filter: SpatialQueryFilter,
mut callback: impl FnMut(RayHitData) -> bool,
) -> Vec<RayHitData> {
) {
let colliders = &self.colliders;

let mut hits = Vec::with_capacity(10);
let ray = parry::query::Ray::new(origin.into(), direction.into());

let mut leaf_callback = &mut |entity_index: &u32| {
Expand All @@ -264,7 +264,6 @@ impl SpatialQueryPipeline {
time_of_impact: hit.toi,
normal: hit.normal.into(),
};
hits.push(hit);

return callback(hit);
}
Expand All @@ -276,8 +275,6 @@ impl SpatialQueryPipeline {
let mut visitor =
RayIntersectionsVisitor::new(&ray, max_time_of_impact, &mut leaf_callback);
self.qbvh.traverse_depth_first(&mut visitor);

hits
}

/// Casts a [shape](spatial_query#shape-casting) with a given rotation and computes the closest [hit](ShapeHits)
Expand Down Expand Up @@ -374,7 +371,7 @@ impl SpatialQueryPipeline {
ignore_origin_penetration: bool,
query_filter: SpatialQueryFilter,
) -> Vec<ShapeHitData> {
let mut hits = 0;
let mut hits = Vec::with_capacity(10);
self.shape_hits_callback(
shape,
origin,
Expand All @@ -383,11 +380,12 @@ impl SpatialQueryPipeline {
max_time_of_impact,
ignore_origin_penetration,
query_filter,
|_| {
hits += 1;
hits < max_hits
|hit| {
hits.push(hit);
(hits.len() as u32) < max_hits
},
)
);
hits
}

/// Casts a [shape](spatial_query#shape-casting) with a given rotation and computes computes all [hits](ShapeHitData)
Expand Down Expand Up @@ -419,7 +417,7 @@ impl SpatialQueryPipeline {
ignore_origin_penetration: bool,
mut query_filter: SpatialQueryFilter,
mut callback: impl FnMut(ShapeHitData) -> bool,
) -> Vec<ShapeHitData> {
) {
let rotation: Rotation;
#[cfg(feature = "2d")]
{
Expand All @@ -432,7 +430,6 @@ impl SpatialQueryPipeline {

let shape_isometry = utils::make_isometry(origin, &rotation);
let shape_direction = direction.into();
let mut hits = Vec::with_capacity(10);

loop {
let pipeline_shape = self.as_composite_shape(query_filter.clone());
Expand All @@ -458,7 +455,6 @@ impl SpatialQueryPipeline {
normal2: hit.normal2.into(),
})
{
hits.push(hit);
query_filter.excluded_entities.insert(hit.entity);

if !callback(hit) {
Expand All @@ -468,8 +464,6 @@ impl SpatialQueryPipeline {
break;
}
}

hits
}

/// Finds the [projection](spatial_query#point-projection) of a given point on the closest [collider](Collider).
Expand Down Expand Up @@ -517,7 +511,12 @@ impl SpatialQueryPipeline {
point: Vector,
query_filter: SpatialQueryFilter,
) -> Vec<Entity> {
self.point_intersections_callback(point, query_filter, |_| true)
let mut intersections = vec![];
self.point_intersections_callback(point, query_filter, |e| {
intersections.push(e);
true
});
intersections
}

/// An [intersection test](spatial_query#intersection-tests) that finds all entities with a [collider](Collider)
Expand All @@ -536,16 +535,13 @@ impl SpatialQueryPipeline {
point: Vector,
query_filter: SpatialQueryFilter,
mut callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
) {
let point = point.into();

let mut intersections = vec![];

let mut leaf_callback = &mut |entity_index: &u32| {
let entity = self.entity_from_index(*entity_index);
if let Some((isometry, shape, layers)) = self.colliders.get(&entity) {
if query_filter.test(entity, *layers) && shape.contains_point(isometry, &point) {
intersections.push(entity);
return callback(entity);
}
}
Expand All @@ -554,16 +550,19 @@ impl SpatialQueryPipeline {

let mut visitor = PointIntersectionsVisitor::new(&point, &mut leaf_callback);
self.qbvh.traverse_depth_first(&mut visitor);

intersections
}

/// An [intersection test](spatial_query#intersection-tests) that finds all entities with a [`ColliderAabb`]
/// that is intersecting the given `aabb`.
///
/// See also: [SpatialQuery::point_intersections_callback]
pub fn aabb_intersections_with_aabb(&self, aabb: ColliderAabb) -> Vec<Entity> {
self.aabb_intersections_with_aabb_callback(aabb, |_| true)
let mut intersections = vec![];
self.aabb_intersections_with_aabb_callback(aabb, |e| {
intersections.push(e);
true
});
intersections
}

/// An [intersection test](spatial_query#intersection-tests) that finds all entities with a [`ColliderAabb`]
Expand All @@ -575,18 +574,14 @@ impl SpatialQueryPipeline {
&self,
aabb: ColliderAabb,
mut callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
let mut intersections = vec![];
) {
let mut leaf_callback = |entity_index: &u32| {
let entity = self.entity_from_index(*entity_index);
intersections.push(entity);
callback(entity)
};

let mut visitor = BoundingVolumeIntersectionsVisitor::new(&aabb, &mut leaf_callback);
self.qbvh.traverse_depth_first(&mut visitor);

intersections
}

/// An [intersection test](spatial_query#intersection-tests) that finds all entities with a [`Collider`]
Expand All @@ -607,13 +602,18 @@ impl SpatialQueryPipeline {
shape_rotation: RotationValue,
query_filter: SpatialQueryFilter,
) -> Vec<Entity> {
let mut intersections = vec![];
self.shape_intersections_callback(
shape,
shape_position,
shape_rotation,
query_filter,
|_| true,
)
|e| {
intersections.push(e);
true
},
);
intersections
}

/// An [intersection test](spatial_query#intersection-tests) that finds all entities with a [`Collider`]
Expand All @@ -636,7 +636,7 @@ impl SpatialQueryPipeline {
shape_rotation: RotationValue,
query_filter: SpatialQueryFilter,
mut callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
) {
let colliders = &self.colliders;
let rotation: Rotation;
#[cfg(feature = "2d")]
Expand All @@ -652,7 +652,6 @@ impl SpatialQueryPipeline {
let inverse_shape_isometry = shape_isometry.inverse();

let dispatcher = &*self.dispatcher;
let mut intersections = vec![];

let mut leaf_callback = &mut |entity_index: &u32| {
let entity = self.entity_from_index(*entity_index);
Expand All @@ -667,7 +666,6 @@ impl SpatialQueryPipeline {
&**collider.get_shape(),
) == Ok(true)
{
intersections.push(entity);
return callback(entity);
}
}
Expand All @@ -678,8 +676,6 @@ impl SpatialQueryPipeline {
let shape_aabb = shape.get_shape().compute_aabb(&shape_isometry);
let mut visitor = BoundingVolumeIntersectionsVisitor::new(&shape_aabb, &mut leaf_callback);
self.qbvh.traverse_depth_first(&mut visitor);

intersections
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/plugins/spatial_query/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ impl<'w, 's> SpatialQuery<'w, 's> {
solid: bool,
query_filter: SpatialQueryFilter,
callback: impl FnMut(RayHitData) -> bool,
) -> Vec<RayHitData> {
) {
self.query_pipeline.ray_hits_callback(
origin,
direction,
Expand Down Expand Up @@ -473,7 +473,7 @@ impl<'w, 's> SpatialQuery<'w, 's> {
ignore_origin_penetration: bool,
query_filter: SpatialQueryFilter,
callback: impl FnMut(ShapeHitData) -> bool,
) -> Vec<ShapeHitData> {
) {
self.query_pipeline.shape_hits_callback(
shape,
origin,
Expand Down Expand Up @@ -604,7 +604,7 @@ impl<'w, 's> SpatialQuery<'w, 's> {
point: Vector,
query_filter: SpatialQueryFilter,
callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
) {
self.query_pipeline
.point_intersections_callback(point, query_filter, callback)
}
Expand Down Expand Up @@ -669,7 +669,7 @@ impl<'w, 's> SpatialQuery<'w, 's> {
&self,
aabb: ColliderAabb,
callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
) {
self.query_pipeline
.aabb_intersections_with_aabb_callback(aabb, callback)
}
Expand Down Expand Up @@ -766,7 +766,7 @@ impl<'w, 's> SpatialQuery<'w, 's> {
shape_rotation: RotationValue,
query_filter: SpatialQueryFilter,
callback: impl FnMut(Entity) -> bool,
) -> Vec<Entity> {
) {
self.query_pipeline.shape_intersections_callback(
shape,
shape_position,
Expand Down

0 comments on commit c5bbfeb

Please sign in to comment.