Skip to content

Commit 0f8d1d0

Browse files
committed
Also update AABBs after physics step, and skip unchanged
1 parent 4ea6152 commit 0f8d1d0

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

src/collider_tree/update.rs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ use crate::{
1313
prelude::*,
1414
};
1515
use bevy::{
16-
ecs::{entity_disabling::Disabled, query::QueryFilter, system::StaticSystemParam},
16+
ecs::{
17+
change_detection::Tick,
18+
entity_disabling::Disabled,
19+
query::QueryFilter,
20+
system::{StaticSystemParam, SystemChangeTick},
21+
},
1722
platform::collections::HashSet,
1823
prelude::*,
1924
};
@@ -36,9 +41,11 @@ impl<C: AnyCollider> Plugin for ColliderTreeUpdatePlugin<C> {
3641
fn build(&self, app: &mut App) {
3742
// Initialize resources.
3843
app.init_resource::<MovedProxies>()
39-
.init_resource::<EnlargedProxies>();
44+
.init_resource::<EnlargedProxies>()
45+
.init_resource::<LastDynamicKinematicAabbUpdate>();
4046

41-
// Add systems for updating collider AABBs.
47+
// Add systems for updating collider AABBs before physics step.
48+
// This accounts for manually moved colliders.
4249
app.add_systems(
4350
PhysicsSchedule,
4451
(
@@ -53,10 +60,13 @@ impl<C: AnyCollider> Plugin for ColliderTreeUpdatePlugin<C> {
5360
.ambiguous_with_all(),
5461
);
5562

56-
// Clear moved proxies after broad phase.
63+
// Clear moved proxies and update dynamic and kinematic collider AABBs.
5764
app.add_systems(
5865
PhysicsSchedule,
59-
clear_moved_proxies.after(ColliderTreeSystems::EndOptimize),
66+
(clear_moved_proxies, update_dynamic_kinematic_aabbs::<C>)
67+
.chain()
68+
.after(PhysicsStepSystems::Finalize)
69+
.before(PhysicsStepSystems::Last),
6070
);
6171

6272
// Initialize `ColliderAabb` for colliders.
@@ -433,6 +443,11 @@ fn remove_from_tree_on<E: EntityEvent, B: Bundle, F: QueryFilter>(
433443
*proxy_key = ColliderTreeProxyKey::PLACEHOLDER;
434444
}
435445

446+
/// A resource for tracking the last system change tick
447+
/// when dynamic or kinematic collider AABBs were updated.
448+
#[derive(Resource, Default)]
449+
struct LastDynamicKinematicAabbUpdate(Tick);
450+
436451
/// A resource for tracking moved proxies.
437452
///
438453
/// Moved proxies are those whose [`ColliderAabb`] has moved outside of their
@@ -554,16 +569,16 @@ impl EnlargedProxies {
554569
}
555570

556571
/// Updates the AABBs of colliders attached to dynamic or kinematic rigid bodies.
572+
// TODO: Optimize the change detection.
557573
fn update_dynamic_kinematic_aabbs<C: AnyCollider>(
558574
mut colliders: ParamSet<(
559575
Query<(
560-
Entity,
561-
&C,
576+
Ref<C>,
562577
&mut ColliderAabb,
563578
&mut EnlargedAabb,
564579
&ColliderTreeProxyKey,
565-
&Position,
566-
&Rotation,
580+
Ref<Position>,
581+
Ref<Rotation>,
567582
Option<&CollisionMargin>,
568583
Option<&SpeculativeMargin>,
569584
)>,
@@ -588,9 +603,13 @@ fn update_dynamic_kinematic_aabbs<C: AnyCollider>(
588603
time: Res<Time>,
589604
collider_context: StaticSystemParam<C::Context>,
590605
mut diagnostics: ResMut<BroadPhaseDiagnostics>,
606+
mut last_tick: ResMut<LastDynamicKinematicAabbUpdate>,
607+
system_tick: SystemChangeTick,
591608
) {
592609
let start = crate::utils::Instant::now();
593610

611+
let this_run = system_tick.this_run();
612+
594613
// An upper bound on the number of proxies, for sizing the bit vectors.
595614
// TODO: Use a better way to track the number of proxies.
596615
let max_num_dynamic_proxies = collider_trees.dynamic_tree.proxies.capacity();
@@ -615,7 +634,6 @@ fn update_dynamic_kinematic_aabbs<C: AnyCollider>(
615634
|(rb_pos, center_of_mass, lin_vel, ang_vel, body_colliders, has_swept_ccd)| {
616635
for collider_entity in body_colliders.iter() {
617636
let Ok((
618-
entity,
619637
collider,
620638
mut aabb,
621639
mut enlarged_aabb,
@@ -629,14 +647,22 @@ fn update_dynamic_kinematic_aabbs<C: AnyCollider>(
629647
continue;
630648
};
631649

650+
// Skip if the collider's AABB can't have changed since the last physics tick.
651+
if !pos.last_changed().is_newer_than(last_tick.0, this_run)
652+
&& !rot.last_changed().is_newer_than(last_tick.0, this_run)
653+
&& !collider.last_changed().is_newer_than(last_tick.0, this_run)
654+
{
655+
continue;
656+
}
657+
632658
let collision_margin = collision_margin.map_or(0.0, |margin| margin.0);
633659
let speculative_margin = if has_swept_ccd {
634660
Scalar::MAX
635661
} else {
636662
speculative_margin.map_or(default_speculative_margin, |margin| margin.0)
637663
};
638664

639-
let context = AabbContext::new(entity, &*collider_context);
665+
let context = AabbContext::new(collider_entity, &*collider_context);
640666

641667
if speculative_margin <= 0.0 {
642668
*aabb = collider
@@ -774,9 +800,15 @@ fn update_dynamic_kinematic_aabbs<C: AnyCollider>(
774800
tree.bvh.refit_all();
775801
}
776802

803+
// Update the last update tick.
804+
last_tick.0 = this_run;
805+
777806
diagnostics.update += start.elapsed();
778807
}
779808

809+
// TODO: If we tagged static colliders with their own marker component,
810+
// we could avoid querying for the bodies, and merge this with the
811+
// standalone collider AABB update.
780812
/// Updates the AABBs of colliders attached to static rigid bodies.
781813
fn update_static_aabbs<C: AnyCollider>(
782814
static_bodies: Query<&RigidBodyColliders, (Without<SolverBody>, Without<Sleeping>)>,

0 commit comments

Comments
 (0)