feat: reduce the amount of duplicate work the broad-phase is doing for user changes and CCD + release v0.28.0 (#872)
* feat: reduce the amount of duplicate work the broad-phase is doing for user changes and CCD * Release v0.28.0 * chore: fix warnings * chore: clippy fixes * chore: more clippy fixes
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
use super::TOIEntry;
|
||||
use crate::dynamics::{IslandManager, RigidBodyHandle, RigidBodySet};
|
||||
use crate::geometry::{ColliderParent, ColliderSet, CollisionEvent, NarrowPhase};
|
||||
use crate::dynamics::{IntegrationParameters, IslandManager, RigidBodyHandle, RigidBodySet};
|
||||
use crate::geometry::{BroadPhaseBvh, ColliderParent, ColliderSet, CollisionEvent, NarrowPhase};
|
||||
use crate::math::Real;
|
||||
use crate::parry::utils::SortedPair;
|
||||
use crate::pipeline::{EventHandler, QueryFilter, QueryPipeline};
|
||||
use crate::pipeline::{EventHandler, QueryFilter};
|
||||
use crate::prelude::{ActiveEvents, CollisionEventFlags};
|
||||
use parry::partitioning::{Bvh, BvhBuildStrategy};
|
||||
use parry::utils::hashmap::HashMap;
|
||||
use std::collections::BinaryHeap;
|
||||
|
||||
@@ -16,26 +15,14 @@ pub enum PredictedImpacts {
|
||||
}
|
||||
|
||||
/// Solver responsible for performing motion-clamping on fast-moving bodies.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
pub struct CCDSolver {
|
||||
// TODO PERF: for now the CCD solver maintains its own bvh for CCD queries.
|
||||
// At each frame it get rebuilt.
|
||||
// We should consider an alternative to directly use the broad-phase’s.
|
||||
#[cfg_attr(feature = "serde-serialize", serde(skip))]
|
||||
bvh: Bvh,
|
||||
}
|
||||
|
||||
impl Default for CCDSolver {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
pub struct CCDSolver;
|
||||
|
||||
impl CCDSolver {
|
||||
/// Initializes a new CCD solver
|
||||
pub fn new() -> Self {
|
||||
Self { bvh: Bvh::new() }
|
||||
Self
|
||||
}
|
||||
|
||||
/// Apply motion-clamping to the bodies affected by the given `impacts`.
|
||||
@@ -101,42 +88,35 @@ impl CCDSolver {
|
||||
#[profiling::function]
|
||||
pub fn find_first_impact(
|
||||
&mut self,
|
||||
dt: Real,
|
||||
dt: Real, // NOTE: this doesn’t necessarily match the `params.dt`.
|
||||
params: &IntegrationParameters,
|
||||
islands: &IslandManager,
|
||||
bodies: &RigidBodySet,
|
||||
colliders: &ColliderSet,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &NarrowPhase,
|
||||
) -> Option<Real> {
|
||||
// Update the query pipeline with the colliders’ predicted positions.
|
||||
self.bvh = Bvh::from_iter(
|
||||
BvhBuildStrategy::Binned,
|
||||
colliders.iter_enabled().map(|(co_handle, co)| {
|
||||
let id = co_handle.into_raw_parts().0;
|
||||
if let Some(co_parent) = co.parent {
|
||||
let rb = &bodies[co_parent.handle];
|
||||
for (handle, co) in colliders.iter_enabled() {
|
||||
if let Some(co_parent) = co.parent {
|
||||
let rb = &bodies[co_parent.handle];
|
||||
if rb.is_ccd_active() {
|
||||
let predicted_pos = rb
|
||||
.pos
|
||||
.integrate_forces_and_velocities(dt, &rb.forces, &rb.vels, &rb.mprops);
|
||||
|
||||
let next_position = predicted_pos * co_parent.pos_wrt_parent;
|
||||
(
|
||||
id as usize,
|
||||
co.shape.compute_swept_aabb(&co.pos, &next_position),
|
||||
)
|
||||
} else {
|
||||
(id as usize, co.shape.compute_aabb(&co.pos))
|
||||
let swept_aabb = co.shape.compute_swept_aabb(&co.pos, &next_position);
|
||||
broad_phase.set_aabb(params, handle, swept_aabb);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let query_pipeline = QueryPipeline {
|
||||
// NOTE: the upcast needs at least rust 1.86
|
||||
dispatcher: narrow_phase.query_dispatcher(),
|
||||
bvh: &self.bvh,
|
||||
let query_pipeline = broad_phase.as_query_pipeline(
|
||||
narrow_phase.query_dispatcher(),
|
||||
bodies,
|
||||
colliders,
|
||||
filter: QueryFilter::default(),
|
||||
};
|
||||
QueryFilter::default(),
|
||||
);
|
||||
|
||||
let mut pairs_seen = HashMap::default();
|
||||
let mut min_toi = dt;
|
||||
@@ -234,43 +214,39 @@ impl CCDSolver {
|
||||
#[profiling::function]
|
||||
pub fn predict_impacts_at_next_positions(
|
||||
&mut self,
|
||||
dt: Real,
|
||||
params: &IntegrationParameters,
|
||||
islands: &IslandManager,
|
||||
bodies: &RigidBodySet,
|
||||
colliders: &ColliderSet,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &NarrowPhase,
|
||||
events: &dyn EventHandler,
|
||||
) -> PredictedImpacts {
|
||||
let dt = params.dt;
|
||||
let mut frozen = HashMap::<_, Real>::default();
|
||||
let mut all_toi = BinaryHeap::new();
|
||||
let mut pairs_seen = HashMap::default();
|
||||
let mut min_overstep = dt;
|
||||
|
||||
// Update the query pipeline with the colliders’ `next_position`.
|
||||
self.bvh = Bvh::from_iter(
|
||||
BvhBuildStrategy::Binned,
|
||||
colliders.iter_enabled().map(|(co_handle, co)| {
|
||||
let id = co_handle.into_raw_parts().0;
|
||||
if let Some(co_parent) = co.parent {
|
||||
for (handle, co) in colliders.iter_enabled() {
|
||||
if let Some(co_parent) = co.parent {
|
||||
let rb = &bodies[co_parent.handle];
|
||||
if rb.is_ccd_active() {
|
||||
let rb_next_pos = &bodies[co_parent.handle].pos.next_position;
|
||||
let next_position = rb_next_pos * co_parent.pos_wrt_parent;
|
||||
(
|
||||
id as usize,
|
||||
co.shape.compute_swept_aabb(&co.pos, &next_position),
|
||||
)
|
||||
} else {
|
||||
(id as usize, co.shape.compute_aabb(&co.pos))
|
||||
let swept_aabb = co.shape.compute_swept_aabb(&co.pos, &next_position);
|
||||
broad_phase.set_aabb(params, handle, swept_aabb);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let query_pipeline = QueryPipeline {
|
||||
dispatcher: narrow_phase.query_dispatcher(),
|
||||
bvh: &self.bvh,
|
||||
let query_pipeline = broad_phase.as_query_pipeline(
|
||||
narrow_phase.query_dispatcher(),
|
||||
bodies,
|
||||
colliders,
|
||||
filter: QueryFilter::default(),
|
||||
};
|
||||
QueryFilter::default(),
|
||||
);
|
||||
|
||||
/*
|
||||
*
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
use crate::dynamics::RigidBodySet;
|
||||
use crate::geometry::{BroadPhasePairEvent, ColliderHandle, ColliderSet};
|
||||
use crate::prelude::IntegrationParameters;
|
||||
use downcast_rs::DowncastSync;
|
||||
|
||||
/// Trait implemented by broad-phase algorithms supported by Rapier.
|
||||
///
|
||||
/// The task of a broad-phase algorithm is to detect potential collision pairs, usually based on
|
||||
/// bounding volumes. The pairs must be conservative: it is OK to create a collision pair if
|
||||
/// two objects don’t actually touch, but it is incorrect to remove a pair between two objects
|
||||
/// that are still touching. In other words, it can have false-positive (though these induce
|
||||
/// some computational overhead on the narrow-phase), but cannot have false-negative.
|
||||
pub trait BroadPhase: Send + Sync + 'static + DowncastSync {
|
||||
/// Updates the broad-phase.
|
||||
///
|
||||
/// The results must be output through the `events` struct. The broad-phase algorithm is only
|
||||
/// required to generate new events (i.e. no need to re-send an `AddPair` event if it was already
|
||||
/// sent previously and no `RemovePair` happened since then). Sending redundant events is allowed
|
||||
/// but can result in a slight computational overhead.
|
||||
///
|
||||
/// The `colliders` set is mutable only to provide access to
|
||||
/// [`collider.set_internal_broad_phase_proxy_index`]. Other properties of the collider should
|
||||
/// **not** be modified during the broad-phase update.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `params`: the integration parameters governing the simulation.
|
||||
/// - `colliders`: the set of colliders. Change detection with `collider.needs_broad_phase_update()`
|
||||
/// can be relied on at this stage.
|
||||
/// - `modified_colliders`: colliders that are know to be modified since the last update.
|
||||
/// - `removed_colliders`: colliders that got removed since the last update. Any associated data
|
||||
/// in the broad-phase should be removed by this call to `update`.
|
||||
/// - `events`: the broad-phase’s output. They indicate what collision pairs need to be created
|
||||
/// and what pairs need to be removed. It is OK to create pairs for colliders that don’t
|
||||
/// actually collide (though this can increase computational overhead in the narrow-phase)
|
||||
/// but it is important not to indicate removal of a collision pair if the underlying colliders
|
||||
/// are still touching or closer than `prediction_distance`.
|
||||
fn update(
|
||||
&mut self,
|
||||
params: &IntegrationParameters,
|
||||
colliders: &ColliderSet,
|
||||
bodies: &RigidBodySet,
|
||||
modified_colliders: &[ColliderHandle],
|
||||
removed_colliders: &[ColliderHandle],
|
||||
events: &mut Vec<BroadPhasePairEvent>,
|
||||
);
|
||||
}
|
||||
|
||||
downcast_rs::impl_downcast!(sync BroadPhase);
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::dynamics::{IntegrationParameters, RigidBodySet};
|
||||
use crate::geometry::{BroadPhase, BroadPhasePairEvent, ColliderHandle, ColliderPair, ColliderSet};
|
||||
use parry::bounding_volume::BoundingVolume;
|
||||
use crate::geometry::{Aabb, BroadPhasePairEvent, ColliderHandle, ColliderPair, ColliderSet};
|
||||
use crate::math::Real;
|
||||
use parry::partitioning::{Bvh, BvhWorkspace};
|
||||
use parry::utils::hashmap::{Entry, HashMap};
|
||||
|
||||
@@ -36,6 +36,9 @@ pub enum BvhOptimizationStrategy {
|
||||
const ENABLE_TREE_VALIDITY_CHECK: bool = false;
|
||||
|
||||
impl BroadPhaseBvh {
|
||||
const CHANGE_DETECTION_ENABLED: bool = true;
|
||||
const CHANGE_DETECTION_FACTOR: Real = 1.0e-2;
|
||||
|
||||
/// Initializes a new empty broad-phase.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
@@ -50,7 +53,30 @@ impl BroadPhaseBvh {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_with_strategy(
|
||||
/// Updates the broad-phase.
|
||||
///
|
||||
/// The results are output through the `events` struct. The broad-phase algorithm is only
|
||||
/// required to generate new events (i.e. no need to re-send an `AddPair` event if it was already
|
||||
/// sent previously and no `RemovePair` happened since then). Sending redundant events is allowed
|
||||
/// but can result in a slight computational overhead.
|
||||
///
|
||||
/// The `colliders` set is mutable only to provide access to
|
||||
/// [`collider.set_internal_broad_phase_proxy_index`]. Other properties of the collider should
|
||||
/// **not** be modified during the broad-phase update.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `params`: the integration parameters governing the simulation.
|
||||
/// - `colliders`: the set of colliders. Change detection with `collider.needs_broad_phase_update()`
|
||||
/// can be relied on at this stage.
|
||||
/// - `modified_colliders`: colliders that are know to be modified since the last update.
|
||||
/// - `removed_colliders`: colliders that got removed since the last update. Any associated data
|
||||
/// in the broad-phase should be removed by this call to `update`.
|
||||
/// - `events`: the broad-phase’s output. They indicate what collision pairs need to be created
|
||||
/// and what pairs need to be removed. It is OK to create pairs for colliders that don’t
|
||||
/// actually collide (though this can increase computational overhead in the narrow-phase)
|
||||
/// but it is important not to indicate removal of a collision pair if the underlying colliders
|
||||
/// are still touching or closer than `prediction_distance`.
|
||||
pub fn update(
|
||||
&mut self,
|
||||
params: &IntegrationParameters,
|
||||
colliders: &ColliderSet,
|
||||
@@ -58,10 +84,7 @@ impl BroadPhaseBvh {
|
||||
modified_colliders: &[ColliderHandle],
|
||||
removed_colliders: &[ColliderHandle],
|
||||
events: &mut Vec<BroadPhasePairEvent>,
|
||||
strategy: BvhOptimizationStrategy,
|
||||
) {
|
||||
const CHANGE_DETECTION_ENABLED: bool = true;
|
||||
|
||||
self.frame_index = self.frame_index.overflowing_add(1).0;
|
||||
|
||||
// Removals must be handled first, in case another collider in
|
||||
@@ -70,9 +93,9 @@ impl BroadPhaseBvh {
|
||||
self.tree.remove(handle.into_raw_parts().0);
|
||||
}
|
||||
|
||||
if modified_colliders.is_empty() {
|
||||
return;
|
||||
}
|
||||
// if modified_colliders.is_empty() {
|
||||
// return;
|
||||
// }
|
||||
|
||||
let first_pass = self.tree.is_empty();
|
||||
|
||||
@@ -83,29 +106,10 @@ impl BroadPhaseBvh {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take soft-ccd into account by growing the aabb.
|
||||
let next_pose = collider.parent.and_then(|p| {
|
||||
let parent = bodies.get(p.handle)?;
|
||||
(parent.soft_ccd_prediction() > 0.0).then(|| {
|
||||
parent.predict_position_using_velocity_and_forces_with_max_dist(
|
||||
params.dt,
|
||||
parent.soft_ccd_prediction(),
|
||||
) * p.pos_wrt_parent
|
||||
})
|
||||
});
|
||||
let aabb = collider.compute_broad_phase_aabb(params, bodies);
|
||||
|
||||
let prediction_distance = params.prediction_distance();
|
||||
let mut aabb = collider.compute_collision_aabb(prediction_distance / 2.0);
|
||||
if let Some(next_pose) = next_pose {
|
||||
let next_aabb = collider
|
||||
.shape
|
||||
.compute_aabb(&next_pose)
|
||||
.loosened(collider.contact_skin() + prediction_distance / 2.0);
|
||||
aabb.merge(&next_aabb);
|
||||
}
|
||||
|
||||
let change_detection_skin = if CHANGE_DETECTION_ENABLED {
|
||||
1.0e-2 * params.length_unit
|
||||
let change_detection_skin = if Self::CHANGE_DETECTION_ENABLED {
|
||||
Self::CHANGE_DETECTION_FACTOR * params.length_unit
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
@@ -127,7 +131,7 @@ impl BroadPhaseBvh {
|
||||
}
|
||||
|
||||
// let t0 = std::time::Instant::now();
|
||||
match strategy {
|
||||
match self.optimization_strategy {
|
||||
BvhOptimizationStrategy::SubtreeOptimizer => {
|
||||
self.tree.optimize_incremental(&mut self.workspace);
|
||||
}
|
||||
@@ -190,7 +194,7 @@ impl BroadPhaseBvh {
|
||||
|
||||
// let t0 = std::time::Instant::now();
|
||||
self.tree
|
||||
.traverse_bvtt_single_tree::<CHANGE_DETECTION_ENABLED>(
|
||||
.traverse_bvtt_single_tree::<{ Self::CHANGE_DETECTION_ENABLED }>(
|
||||
&mut self.workspace,
|
||||
&mut pairs_collector,
|
||||
);
|
||||
@@ -220,7 +224,7 @@ impl BroadPhaseBvh {
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!CHANGE_DETECTION_ENABLED || node0.is_changed() || node1.is_changed())
|
||||
if (!Self::CHANGE_DETECTION_ENABLED || node0.is_changed() || node1.is_changed())
|
||||
&& !node0.intersects(node1)
|
||||
{
|
||||
events.push(BroadPhasePairEvent::DeletePair(ColliderPair::new(*h0, *h1)));
|
||||
@@ -245,26 +249,21 @@ impl BroadPhaseBvh {
|
||||
// removed_pairs
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
impl BroadPhase for BroadPhaseBvh {
|
||||
fn update(
|
||||
&mut self,
|
||||
params: &IntegrationParameters,
|
||||
colliders: &ColliderSet,
|
||||
bodies: &RigidBodySet,
|
||||
modified_colliders: &[ColliderHandle],
|
||||
removed_colliders: &[ColliderHandle],
|
||||
events: &mut Vec<BroadPhasePairEvent>,
|
||||
) {
|
||||
self.update_with_strategy(
|
||||
params,
|
||||
colliders,
|
||||
bodies,
|
||||
modified_colliders,
|
||||
removed_colliders,
|
||||
events,
|
||||
self.optimization_strategy,
|
||||
/// Sets the AABB associated to the given collider.
|
||||
///
|
||||
/// The AABB change will be immediately applied and propagated through the underlying BVH.
|
||||
/// Change detection will automatically take it into account during the next broad-phase update.
|
||||
pub fn set_aabb(&mut self, params: &IntegrationParameters, handle: ColliderHandle, aabb: Aabb) {
|
||||
let change_detection_skin = if Self::CHANGE_DETECTION_ENABLED {
|
||||
Self::CHANGE_DETECTION_FACTOR * params.length_unit
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
self.tree.insert_with_change_detection(
|
||||
aabb,
|
||||
handle.into_raw_parts().0,
|
||||
change_detection_skin,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
|
||||
use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle, RigidBodySet};
|
||||
#[cfg(feature = "dim3")]
|
||||
use crate::geometry::HeightFieldFlags;
|
||||
use crate::geometry::{
|
||||
@@ -9,7 +9,7 @@ use crate::geometry::{
|
||||
use crate::math::{AngVector, DIM, Isometry, Point, Real, Rotation, Vector};
|
||||
use crate::parry::transformation::vhacd::VHACDParameters;
|
||||
use crate::pipeline::{ActiveEvents, ActiveHooks};
|
||||
use crate::prelude::ColliderEnabled;
|
||||
use crate::prelude::{ColliderEnabled, IntegrationParameters};
|
||||
use na::Unit;
|
||||
use parry::bounding_volume::{Aabb, BoundingVolume};
|
||||
use parry::shape::{Shape, TriMeshBuilderError, TriMeshFlags};
|
||||
@@ -457,6 +457,40 @@ impl Collider {
|
||||
self.shape.compute_swept_aabb(&self.pos, next_position)
|
||||
}
|
||||
|
||||
// TODO: we have a lot of different AABB computation functions
|
||||
// We should group them somehow.
|
||||
/// Computes the collider’s AABB for usage in a broad-phase.
|
||||
///
|
||||
/// It takes into account soft-ccd, the contact skin, and the contact prediction.
|
||||
pub fn compute_broad_phase_aabb(
|
||||
&self,
|
||||
params: &IntegrationParameters,
|
||||
bodies: &RigidBodySet,
|
||||
) -> Aabb {
|
||||
// Take soft-ccd into account by growing the aabb.
|
||||
let next_pose = self.parent.and_then(|p| {
|
||||
let parent = bodies.get(p.handle)?;
|
||||
(parent.soft_ccd_prediction() > 0.0).then(|| {
|
||||
parent.predict_position_using_velocity_and_forces_with_max_dist(
|
||||
params.dt,
|
||||
parent.soft_ccd_prediction(),
|
||||
) * p.pos_wrt_parent
|
||||
})
|
||||
});
|
||||
|
||||
let prediction_distance = params.prediction_distance();
|
||||
let mut aabb = self.compute_collision_aabb(prediction_distance / 2.0);
|
||||
if let Some(next_pose) = next_pose {
|
||||
let next_aabb = self
|
||||
.shape
|
||||
.compute_aabb(&next_pose)
|
||||
.loosened(self.contact_skin() + prediction_distance / 2.0);
|
||||
aabb.merge(&next_aabb);
|
||||
}
|
||||
|
||||
aabb
|
||||
}
|
||||
|
||||
/// Compute the local-space mass properties of this collider.
|
||||
pub fn mass_properties(&self) -> MassProperties {
|
||||
self.mprops.mass_properties(&*self.shape)
|
||||
|
||||
@@ -53,6 +53,10 @@ impl ColliderSet {
|
||||
std::mem::take(&mut self.modified_colliders)
|
||||
}
|
||||
|
||||
pub(crate) fn set_modified(&mut self, modified: ModifiedColliders) {
|
||||
self.modified_colliders = modified;
|
||||
}
|
||||
|
||||
pub(crate) fn take_removed(&mut self) -> Vec<ColliderHandle> {
|
||||
std::mem::take(&mut self.removed_colliders)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Structures related to geometry: colliders, shapes, etc.
|
||||
|
||||
pub use self::broad_phase::BroadPhase;
|
||||
pub use self::broad_phase_bvh::{BroadPhaseBvh, BvhOptimizationStrategy};
|
||||
pub use self::broad_phase_pair_event::{BroadPhasePairEvent, ColliderPair};
|
||||
pub use self::collider::{Collider, ColliderBuilder};
|
||||
@@ -199,7 +198,6 @@ mod interaction_graph;
|
||||
mod interaction_groups;
|
||||
mod narrow_phase;
|
||||
|
||||
mod broad_phase;
|
||||
mod broad_phase_bvh;
|
||||
mod broad_phase_pair_event;
|
||||
mod collider;
|
||||
|
||||
@@ -697,14 +697,9 @@ impl NarrowPhase {
|
||||
&mut self,
|
||||
bodies: &RigidBodySet,
|
||||
colliders: &ColliderSet,
|
||||
modified_colliders: &[ColliderHandle],
|
||||
hooks: &dyn PhysicsHooks,
|
||||
events: &dyn EventHandler,
|
||||
) {
|
||||
if modified_colliders.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let nodes = &self.intersection_graph.graph.nodes;
|
||||
let query_dispatcher = &*self.query_dispatcher;
|
||||
|
||||
@@ -806,14 +801,9 @@ impl NarrowPhase {
|
||||
colliders: &ColliderSet,
|
||||
impulse_joints: &ImpulseJointSet,
|
||||
multibody_joints: &MultibodyJointSet,
|
||||
modified_colliders: &[ColliderHandle],
|
||||
hooks: &dyn PhysicsHooks,
|
||||
events: &dyn EventHandler,
|
||||
) {
|
||||
if modified_colliders.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let query_dispatcher = &*self.query_dispatcher;
|
||||
|
||||
// TODO: don't iterate on all the edges.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::dynamics::{ImpulseJointSet, IntegrationParameters, MultibodyJointSet};
|
||||
use crate::geometry::{
|
||||
BroadPhase, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair,
|
||||
BroadPhaseBvh, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair,
|
||||
ModifiedColliders, NarrowPhase,
|
||||
};
|
||||
use crate::math::Real;
|
||||
@@ -44,7 +44,7 @@ impl CollisionPipeline {
|
||||
fn detect_collisions(
|
||||
&mut self,
|
||||
prediction_distance: Real,
|
||||
broad_phase: &mut dyn BroadPhase,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &mut NarrowPhase,
|
||||
bodies: &mut RigidBodySet,
|
||||
colliders: &mut ColliderSet,
|
||||
@@ -93,11 +93,10 @@ impl CollisionPipeline {
|
||||
colliders,
|
||||
&ImpulseJointSet::new(),
|
||||
&MultibodyJointSet::new(),
|
||||
modified_colliders,
|
||||
hooks,
|
||||
events,
|
||||
);
|
||||
narrow_phase.compute_intersections(bodies, colliders, modified_colliders, hooks, events);
|
||||
narrow_phase.compute_intersections(bodies, colliders, hooks, events);
|
||||
}
|
||||
|
||||
fn clear_modified_colliders(
|
||||
@@ -118,7 +117,7 @@ impl CollisionPipeline {
|
||||
pub fn step(
|
||||
&mut self,
|
||||
prediction_distance: Real,
|
||||
broad_phase: &mut dyn BroadPhase,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &mut NarrowPhase,
|
||||
bodies: &mut RigidBodySet,
|
||||
colliders: &mut ColliderSet,
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::dynamics::{
|
||||
RigidBodyChanges, RigidBodyPosition, RigidBodyType,
|
||||
};
|
||||
use crate::geometry::{
|
||||
BroadPhase, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair,
|
||||
BroadPhaseBvh, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair,
|
||||
ContactManifoldIndex, ModifiedColliders, NarrowPhase, TemporaryInteractionIndex,
|
||||
};
|
||||
use crate::math::{Real, Vector};
|
||||
@@ -71,11 +71,14 @@ impl PhysicsPipeline {
|
||||
colliders: &mut ColliderSet,
|
||||
modified_colliders: &mut ModifiedColliders,
|
||||
) {
|
||||
for handle in modified_colliders.iter() {
|
||||
if let Some(co) = colliders.get_mut_internal(*handle) {
|
||||
co.changes = ColliderChanges::empty();
|
||||
}
|
||||
for co in colliders.colliders.iter_mut() {
|
||||
co.1.changes = ColliderChanges::empty();
|
||||
}
|
||||
// for handle in modified_colliders.iter() {
|
||||
// if let Some(co) = colliders.get_mut_internal(*handle) {
|
||||
// co.changes = ColliderChanges::empty();
|
||||
// }
|
||||
// }
|
||||
|
||||
modified_colliders.clear();
|
||||
}
|
||||
@@ -98,7 +101,7 @@ impl PhysicsPipeline {
|
||||
&mut self,
|
||||
integration_parameters: &IntegrationParameters,
|
||||
islands: &mut IslandManager,
|
||||
broad_phase: &mut dyn BroadPhase,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &mut NarrowPhase,
|
||||
bodies: &mut RigidBodySet,
|
||||
colliders: &mut ColliderSet,
|
||||
@@ -153,11 +156,10 @@ impl PhysicsPipeline {
|
||||
colliders,
|
||||
impulse_joints,
|
||||
multibody_joints,
|
||||
modified_colliders,
|
||||
hooks,
|
||||
events,
|
||||
);
|
||||
narrow_phase.compute_intersections(bodies, colliders, modified_colliders, hooks, events);
|
||||
narrow_phase.compute_intersections(bodies, colliders, hooks, events);
|
||||
|
||||
self.counters.cd.narrow_phase_time.pause();
|
||||
self.counters.stages.collision_detection_time.pause();
|
||||
@@ -340,6 +342,7 @@ impl PhysicsPipeline {
|
||||
islands: &IslandManager,
|
||||
bodies: &mut RigidBodySet,
|
||||
colliders: &mut ColliderSet,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &NarrowPhase,
|
||||
ccd_solver: &mut CCDSolver,
|
||||
events: &dyn EventHandler,
|
||||
@@ -347,10 +350,11 @@ impl PhysicsPipeline {
|
||||
self.counters.ccd.toi_computation_time.start();
|
||||
// Handle CCD
|
||||
let impacts = ccd_solver.predict_impacts_at_next_positions(
|
||||
integration_parameters.dt,
|
||||
integration_parameters,
|
||||
islands,
|
||||
bodies,
|
||||
colliders,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
events,
|
||||
);
|
||||
@@ -414,7 +418,7 @@ impl PhysicsPipeline {
|
||||
gravity: &Vector<Real>,
|
||||
integration_parameters: &IntegrationParameters,
|
||||
islands: &mut IslandManager,
|
||||
broad_phase: &mut dyn BroadPhase,
|
||||
broad_phase: &mut BroadPhaseBvh,
|
||||
narrow_phase: &mut NarrowPhase,
|
||||
bodies: &mut RigidBodySet,
|
||||
colliders: &mut ColliderSet,
|
||||
@@ -535,9 +539,11 @@ impl PhysicsPipeline {
|
||||
let first_impact = if ccd_active {
|
||||
ccd_solver.find_first_impact(
|
||||
remaining_time,
|
||||
&integration_parameters,
|
||||
islands,
|
||||
bodies,
|
||||
colliders,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
)
|
||||
} else {
|
||||
@@ -605,6 +611,7 @@ impl PhysicsPipeline {
|
||||
islands,
|
||||
bodies,
|
||||
colliders,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
ccd_solver,
|
||||
events,
|
||||
@@ -616,23 +623,35 @@ impl PhysicsPipeline {
|
||||
self.advance_to_final_positions(islands, bodies, colliders, &mut modified_colliders);
|
||||
self.counters.stages.update_time.pause();
|
||||
|
||||
self.detect_collisions(
|
||||
&integration_parameters,
|
||||
islands,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
bodies,
|
||||
colliders,
|
||||
impulse_joints,
|
||||
multibody_joints,
|
||||
&modified_colliders,
|
||||
&[],
|
||||
hooks,
|
||||
events,
|
||||
false,
|
||||
);
|
||||
if remaining_substeps > 0 {
|
||||
self.detect_collisions(
|
||||
&integration_parameters,
|
||||
islands,
|
||||
broad_phase,
|
||||
narrow_phase,
|
||||
bodies,
|
||||
colliders,
|
||||
impulse_joints,
|
||||
multibody_joints,
|
||||
&modified_colliders,
|
||||
&[],
|
||||
hooks,
|
||||
events,
|
||||
false,
|
||||
);
|
||||
|
||||
self.clear_modified_colliders(colliders, &mut modified_colliders);
|
||||
self.clear_modified_colliders(colliders, &mut modified_colliders);
|
||||
} else {
|
||||
// If we ran the last substep, just update the broad-phase bvh instead
|
||||
// of a full collision-detection step.
|
||||
for handle in modified_colliders.iter() {
|
||||
let co = &colliders[*handle];
|
||||
let aabb = co.compute_broad_phase_aabb(&integration_parameters, bodies);
|
||||
broad_phase.set_aabb(&integration_parameters, *handle, aabb);
|
||||
}
|
||||
modified_colliders.clear();
|
||||
// self.clear_modified_colliders(colliders, &mut modified_colliders);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, make sure we update the world mass-properties of the rigid-bodies
|
||||
@@ -648,6 +667,9 @@ impl PhysicsPipeline {
|
||||
}
|
||||
self.counters.stages.update_time.pause();
|
||||
|
||||
// Re-insert the modified vector we extracted for the borrow-checker.
|
||||
colliders.set_modified(modified_colliders);
|
||||
|
||||
self.counters.step_completed();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user