Skip to content

Commit 309be19

Browse files
authored
Use ColliderTrees for spatial queries (#941)
# Objective Fixes #403. #927 added `ColliderTrees` for the new BVH broad phase. We should reuse them for spatial queries instead of maintaining and using a separate BVH from Parry. ## Solution In short: - Add more traversal methods on `Bvh2` via extension traits (we should probably upstream these) - `sweep_traverse`, `sweep_traverse_miss`, `sweep_traverse_anyhit`, and `sweep_traverse_dynamic` - `squared_distance_traverse` and `squared_distance_traverse_dynamic` - Add methods for BVH traversal on `ColliderTree` - `ray_traverse_closest` and `ray_traverse_all` - `sweep_traverse_closest` and `sweep_traverse_all` - `squared_distance_traverse_closest` - `point_traverse` - `aabb_traverse` - Remove `SpatialQueryPipeline`, and use the `ColliderTrees` traversal methods for `SpatialQuery` This involved some other miscellaneous changes: - Shape casts now returns hits in arbitrary order when `max_hits > 1`, similar to ray casts. - `point2` and `normal2` were previously in local space, despite what the docs state. They are now in world space. ## Testing Tested different spatial queries in examples. --- ## Showcase Before, updating the spatial query pipeline was extremely expensive for large scenes with a lot of colliders: <img width="263" height="439" alt="Before" src="https://github.com/user-attachments/assets/0cc11950-cd69-434a-90f6-1fa517d255f9" /> (note that the tree optimization cost is partially hidden here, as it is run in parallel with the spatial query pipeline update) Now, using the much more optimized `ColliderTrees`, that overhead is gone: <img width="263" height="439" alt="After" src="https://github.com/user-attachments/assets/e39091f1-3a6f-4cfd-b22d-c8ac9c646b5f" /> ## Future Work - Generic collider types for spatial queries (#810)
1 parent 4e0c808 commit 309be19

21 files changed

Lines changed: 1290 additions & 1214 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/avian2d/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ approx = "0.5"
9090
parry2d = { version = "0.26", optional = true }
9191
parry2d-f64 = { version = "0.26", optional = true }
9292
obvhs = { version = "0.3" }
93+
obvhs_glam = { package = "glam", version = "0.31" }
9394
serde = { version = "1", features = ["derive"], optional = true }
9495
derive_more = "2"
9596
thiserror = "2"

crates/avian3d/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ approx = "0.5"
9292
parry3d = { version = "0.26", optional = true }
9393
parry3d-f64 = { version = "0.26", optional = true }
9494
obvhs = { version = "0.3" }
95+
obvhs_glam = { package = "glam", version = "0.31" }
9596
serde = { version = "1", features = ["derive"], optional = true }
9697
derive_more = "2"
9798
thiserror = "2"

crates/avian3d/examples/move_and_slide_3d.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ fn update_camera_transform(
257257
accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
258258
player: Single<(Entity, &Transform), With<TouchedEntities>>,
259259
mut camera: Single<&mut Transform, (With<Camera>, Without<TouchedEntities>)>,
260-
spatial: Res<SpatialQueryPipeline>,
260+
spatial: SpatialQuery,
261261
) {
262262
let (player_entity, player_transform) = player.into_inner();
263263
let delta = accumulated_mouse_motion.delta;

migration-guides/0.5-to-main.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ since the latest release. These guides are evolving and may not be polished yet.
66
See [migration-guides/README.md](./README.md) and existing entries for information about Avian's
77
migration guide process and what to put here.
88

9-
## Broad Phase Rework
9+
## Broad Phase
1010

1111
PR [#927](https://github.com/avianphysics/avian/pull/927) overhauled broad phase collision detection
1212
to use a Bounding Volume Hierarchy (BVH).
@@ -30,6 +30,32 @@ The order should still be deterministic across runs, given the same inputs.
3030
Previously, `ContactPair::body1` and `ContactPair::body2` also used the `Entity` of the collider
3131
if the collider was not attached to a body. Now, the properties are instead `None`.
3232

33+
## Spatial Queries
34+
35+
PR [#941](https://github.com/avianphysics/avian/pull/941) changed spatial queries to reuse
36+
the `ColliderTrees` used by the broad phase.
37+
38+
### Removed `SpatialQueryPipeline`
39+
40+
The `SpatialQueryPipeline` has been removed. Instead, use the `SpatialQuery` system parameter,
41+
or for lower level control, use the `ColliderTrees` resource directly.
42+
43+
If you get query conflicts because `SpatialQuery` queries for `&Position` and `&Rotation` and your system
44+
also queries for them mutably, consider deferring the mutation to a later point to avoid the conflict.
45+
46+
Previously, you could call `SpatialQuery::update_pipeline()` to update the internal acceleration structures
47+
when you have made changes to colliders or their positions, and need to perform spatial queries before the next physics step.
48+
This method no longer exists, but there is instead a public `update_moved_collider_aabbs` system that you can run.
49+
50+
### Shape Cast Data
51+
52+
Shape casts now return hits in arbitrary order when `max_hits > 1`, similar to ray casts.
53+
This is for performance reasons.
54+
55+
Previously, `point2` in `ShapeHitData` was also relative to the shape cast origin,
56+
even though documentation described it as a global point. This has been fixed,
57+
and it is now in world space like the other values.
58+
3359
## Joint Motors
3460

3561
`RevoluteJoint` and `PrismaticJoimt` now store motors for driving movement.

src/character_controller/move_and_slide.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ pub const COS_5_DEGREES: Scalar = 0.99619469809;
6767
#[doc(alias = "CollideAndSlide")]
6868
#[doc(alias = "StepSlide")]
6969
pub struct MoveAndSlide<'w, 's> {
70-
/// The [`SpatialQueryPipeline`] used to perform spatial queries.
71-
pub query_pipeline: Res<'w, SpatialQueryPipeline>,
70+
/// The [`SpatialQuery`] system parameter used to perform shape casts and other geometric queries.
71+
pub spatial_query: SpatialQuery<'w, 's>,
7272
/// The [`Query`] used to query for colliders.
7373
pub colliders: Query<
7474
'w,
@@ -538,7 +538,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
538538
position += sweep;
539539
break;
540540
};
541-
let point = sweep_hit.point2 + position;
541+
let point = sweep_hit.point2;
542542

543543
// Move up to the hit point.
544544
time_left -= time_left * (sweep_hit.distance / distance);
@@ -775,7 +775,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
775775
///
776776
/// # Related methods
777777
///
778-
/// - [`SpatialQueryPipeline::cast_shape`]
778+
/// - [`SpatialQuery::cast_shape`]
779779
#[must_use]
780780
#[doc(alias = "sweep")]
781781
pub fn cast_move(
@@ -789,7 +789,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
789789
) -> Option<MoveHitData> {
790790
let (direction, distance) = Dir::new_and_length(movement.f32()).unwrap_or((Dir::X, 0.0));
791791
let distance = distance.adjust_precision();
792-
let shape_hit = self.query_pipeline.cast_shape_predicate(
792+
let shape_hit = self.spatial_query.cast_shape_predicate(
793793
shape,
794794
shape_position,
795795
shape_rotation,
@@ -1078,7 +1078,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
10781078
.aabb(shape_position, shape_rotation)
10791079
.grow(Vector::splat(prediction_distance));
10801080
let aabb_intersections = self
1081-
.query_pipeline
1081+
.spatial_query
10821082
.aabb_intersections_with_aabb(expanded_aabb);
10831083

10841084
'outer: for intersection_entity in aabb_intersections {

src/collider_tree/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@
2222
//! [`BvhBroadPhasePlugin`]: crate::collision::broad_phase::BvhBroadPhasePlugin
2323
2424
mod diagnostics;
25+
mod obvhs_ext;
2526
mod optimization;
2627
mod proxy_key;
28+
mod traverse;
2729
mod tree;
2830
mod update;
2931

3032
pub use diagnostics::ColliderTreeDiagnostics;
33+
pub use obvhs_ext::Bvh2Ext;
34+
pub(crate) use obvhs_ext::obvhs_ray;
3135
pub use optimization::{ColliderTreeOptimization, TreeOptimizationMode};
3236
pub use proxy_key::{ColliderTreeProxyKey, ColliderTreeType, ProxyId};
3337
pub use tree::{ColliderTree, ColliderTreeProxy, ColliderTreeProxyFlags, ColliderTreeWorkspace};
34-
pub use update::MovedProxies;
38+
pub use update::{MovedProxies, update_moved_collider_aabbs};
3539

3640
use optimization::ColliderTreeOptimizationPlugin;
3741
use update::ColliderTreeUpdatePlugin;

0 commit comments

Comments
 (0)