aboutsummaryrefslogtreecommitdiff
path: root/src/pipeline
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-05-01 10:17:23 +0200
committerGitHub <noreply@github.com>2021-05-01 10:17:23 +0200
commita385efc5582c7918f11c01a2b6bf26a46919d3a0 (patch)
treec5b9c5e6fcb5561421e2b4b9d99f28e4c83c745e /src/pipeline
parentaaf80bfa872c6f29b248cab8eb5658ab0d73cb4a (diff)
parent2dfbd9ae92c139e306afc87994adac82489f30eb (diff)
downloadrapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.tar.gz
rapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.tar.bz2
rapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.zip
Merge pull request #183 from dimforge/bundles
Make Rapier accept any kind of data storage instead of RigidBodySet/ColliderSet
Diffstat (limited to 'src/pipeline')
-rw-r--r--src/pipeline/collision_pipeline.rs187
-rw-r--r--src/pipeline/mod.rs1
-rw-r--r--src/pipeline/physics_hooks.rs83
-rw-r--r--src/pipeline/physics_pipeline.rs393
-rw-r--r--src/pipeline/query_pipeline.rs444
-rw-r--r--src/pipeline/user_changes.rs178
6 files changed, 1017 insertions, 269 deletions
diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs
index da572f3..455e75d 100644
--- a/src/pipeline/collision_pipeline.rs
+++ b/src/pipeline/collision_pipeline.rs
@@ -1,10 +1,21 @@
//! Physics pipeline structures.
-use crate::dynamics::{JointSet, RigidBodySet};
-use crate::geometry::{BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, NarrowPhase};
+use crate::data::{ComponentSet, ComponentSetMut, ComponentSetOption};
+use crate::dynamics::{
+ RigidBodyActivation, RigidBodyChanges, RigidBodyColliders, RigidBodyDominance, RigidBodyHandle,
+ RigidBodyIds, RigidBodyPosition, RigidBodyType, RigidBodyVelocity,
+};
+use crate::geometry::{
+ BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups,
+ ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition,
+ ColliderShape, ColliderType, NarrowPhase,
+};
use crate::math::Real;
use crate::pipeline::{EventHandler, PhysicsHooks};
+#[cfg(feature = "default-sets")]
+use crate::{dynamics::RigidBodySet, geometry::ColliderSet};
+
/// The collision pipeline, responsible for performing collision detection between colliders.
///
/// This structure only contains temporary data buffers. It can be dropped and replaced by a fresh
@@ -14,7 +25,6 @@ use crate::pipeline::{EventHandler, PhysicsHooks};
pub struct CollisionPipeline {
broadphase_collider_pairs: Vec<ColliderPair>,
broad_phase_events: Vec<BroadPhasePairEvent>,
- empty_joints: JointSet,
}
#[allow(dead_code)]
@@ -29,11 +39,83 @@ impl CollisionPipeline {
CollisionPipeline {
broadphase_collider_pairs: Vec::new(),
broad_phase_events: Vec::new(),
- empty_joints: JointSet::new(),
+ }
+ }
+
+ fn detect_collisions<Bodies, Colliders>(
+ &mut self,
+ prediction_distance: Real,
+ broad_phase: &mut BroadPhase,
+ narrow_phase: &mut NarrowPhase,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
+ modified_colliders: &[ColliderHandle],
+ removed_colliders: &[ColliderHandle],
+ hooks: &dyn PhysicsHooks<Bodies, Colliders>,
+ events: &dyn EventHandler,
+ handle_user_changes: bool,
+ ) where
+ Bodies: ComponentSetMut<RigidBodyActivation>
+ + ComponentSet<RigidBodyType>
+ + ComponentSetMut<RigidBodyIds>
+ + ComponentSet<RigidBodyDominance>,
+ Colliders: ComponentSetMut<ColliderBroadPhaseData>
+ + ComponentSet<ColliderChanges>
+ + ComponentSet<ColliderPosition>
+ + ComponentSet<ColliderShape>
+ + ComponentSetOption<ColliderParent>
+ + ComponentSet<ColliderType>
+ + ComponentSet<ColliderGroups>
+ + ComponentSet<ColliderMaterial>,
+ {
+ // Update broad-phase.
+ self.broad_phase_events.clear();
+ self.broadphase_collider_pairs.clear();
+
+ broad_phase.update(
+ prediction_distance,
+ colliders,
+ modified_colliders,
+ removed_colliders,
+ &mut self.broad_phase_events,
+ );
+
+ // Update narrow-phase.
+ if handle_user_changes {
+ narrow_phase.handle_user_changes(
+ None,
+ modified_colliders,
+ removed_colliders,
+ colliders,
+ bodies,
+ events,
+ );
+ }
+
+ narrow_phase.register_pairs(None, colliders, bodies, &self.broad_phase_events, events);
+ narrow_phase.compute_contacts(
+ prediction_distance,
+ bodies,
+ colliders,
+ modified_colliders,
+ hooks,
+ events,
+ );
+ narrow_phase.compute_intersections(bodies, colliders, modified_colliders, hooks, events);
+ }
+
+ fn clear_modified_colliders(
+ &mut self,
+ colliders: &mut impl ComponentSetMut<ColliderChanges>,
+ modified_colliders: &mut Vec<ColliderHandle>,
+ ) {
+ for handle in modified_colliders.drain(..) {
+ colliders.set_internal(handle.0, ColliderChanges::empty())
}
}
/// Executes one step of the collision detection.
+ #[cfg(feature = "default-sets")]
pub fn step(
&mut self,
prediction_distance: Real,
@@ -41,39 +123,84 @@ impl CollisionPipeline {
narrow_phase: &mut NarrowPhase,
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
- hooks: &dyn PhysicsHooks,
+ hooks: &dyn PhysicsHooks<RigidBodySet, ColliderSet>,
events: &dyn EventHandler,
) {
- colliders.handle_user_changes(bodies);
- bodies.handle_user_changes(colliders);
- self.broadphase_collider_pairs.clear();
+ let mut modified_bodies = bodies.take_modified();
+ let mut modified_colliders = colliders.take_modified();
+ let mut removed_colliders = colliders.take_removed();
- self.broad_phase_events.clear();
- broad_phase.update(prediction_distance, colliders, &mut self.broad_phase_events);
-
- narrow_phase.handle_user_changes(colliders, bodies, events);
- narrow_phase.register_pairs(colliders, bodies, &self.broad_phase_events, events);
- narrow_phase.compute_contacts(prediction_distance, bodies, colliders, hooks, events);
- narrow_phase.compute_intersections(bodies, colliders, hooks, events);
+ self.step_generic(
+ prediction_distance,
+ broad_phase,
+ narrow_phase,
+ bodies,
+ colliders,
+ &mut modified_bodies,
+ &mut modified_colliders,
+ &mut removed_colliders,
+ hooks,
+ events,
+ );
+ }
- bodies.update_active_set_with_contacts(
+ /// Executes one step of the collision detection.
+ pub fn step_generic<Bodies, Colliders>(
+ &mut self,
+ prediction_distance: Real,
+ broad_phase: &mut BroadPhase,
+ narrow_phase: &mut NarrowPhase,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
+ modified_bodies: &mut Vec<RigidBodyHandle>,
+ modified_colliders: &mut Vec<ColliderHandle>,
+ removed_colliders: &mut Vec<ColliderHandle>,
+ hooks: &dyn PhysicsHooks<Bodies, Colliders>,
+ events: &dyn EventHandler,
+ ) where
+ Bodies: ComponentSetMut<RigidBodyPosition>
+ + ComponentSetMut<RigidBodyVelocity>
+ + ComponentSetMut<RigidBodyIds>
+ + ComponentSetMut<RigidBodyActivation>
+ + ComponentSetMut<RigidBodyChanges>
+ + ComponentSet<RigidBodyColliders>
+ + ComponentSet<RigidBodyDominance>
+ + ComponentSet<RigidBodyType>,
+ Colliders: ComponentSetMut<ColliderBroadPhaseData>
+ + ComponentSetMut<ColliderChanges>
+ + ComponentSetMut<ColliderPosition>
+ + ComponentSet<ColliderShape>
+ + ComponentSetOption<ColliderParent>
+ + ComponentSet<ColliderType>
+ + ComponentSet<ColliderGroups>
+ + ComponentSet<ColliderMaterial>,
+ {
+ super::user_changes::handle_user_changes_to_colliders(
+ bodies,
+ colliders,
+ &modified_colliders[..],
+ );
+ super::user_changes::handle_user_changes_to_rigid_bodies(
+ None,
+ bodies,
colliders,
+ &modified_bodies,
+ modified_colliders,
+ );
+ self.detect_collisions(
+ prediction_distance,
+ broad_phase,
narrow_phase,
- self.empty_joints.joint_graph(),
- 128,
+ bodies,
+ colliders,
+ &modified_colliders[..],
+ removed_colliders,
+ hooks,
+ events,
+ true,
);
- // Update colliders positions and kinematic bodies positions.
- bodies.foreach_active_body_mut_internal(|_, rb| {
- rb.position = rb.next_position;
- rb.update_colliders_positions(colliders);
-
- for handle in &rb.colliders {
- let collider = colliders.get_mut_internal(*handle).unwrap();
- collider.position = rb.position * collider.delta;
- }
- });
-
- bodies.modified_inactive_set.clear();
+ self.clear_modified_colliders(colliders, modified_colliders);
+ removed_colliders.clear();
}
}
diff --git a/src/pipeline/mod.rs b/src/pipeline/mod.rs
index 5fad9bc..ad288d6 100644
--- a/src/pipeline/mod.rs
+++ b/src/pipeline/mod.rs
@@ -13,3 +13,4 @@ mod event_handler;
mod physics_hooks;
mod physics_pipeline;
mod query_pipeline;
+mod user_changes;
diff --git a/src/pipeline/physics_hooks.rs b/src/pipeline/physics_hooks.rs
index 72b635f..c4ef245 100644
--- a/src/pipeline/physics_hooks.rs
+++ b/src/pipeline/physics_hooks.rs
@@ -1,38 +1,38 @@
-use crate::dynamics::RigidBody;
-use crate::geometry::{Collider, ColliderHandle, ContactManifold, SolverContact, SolverFlags};
+use crate::dynamics::RigidBodyHandle;
+use crate::geometry::{ColliderHandle, ContactManifold, SolverContact, SolverFlags};
use crate::math::{Real, Vector};
use na::ComplexField;
/// Context given to custom collision filters to filter-out collisions.
-pub struct PairFilterContext<'a> {
- /// The first collider involved in the potential collision.
- pub rigid_body1: &'a RigidBody,
- /// The first collider involved in the potential collision.
- pub rigid_body2: &'a RigidBody,
- /// The first collider involved in the potential collision.
- pub collider_handle1: ColliderHandle,
- /// The first collider involved in the potential collision.
- pub collider_handle2: ColliderHandle,
- /// The first collider involved in the potential collision.
- pub collider1: &'a Collider,
- /// The first collider involved in the potential collision.
- pub collider2: &'a Collider,
+pub struct PairFilterContext<'a, Bodies, Colliders> {
+ /// The set of rigid-bodies.
+ pub bodies: &'a Bodies,
+ /// The set of colliders.
+ pub colliders: &'a Colliders,
+ /// The handle of the first collider involved in the potential collision.
+ pub collider1: ColliderHandle,
+ /// The handle of the first collider involved in the potential collision.
+ pub collider2: ColliderHandle,
+ /// The handle of the first body involved in the potential collision.
+ pub rigid_body1: Option<RigidBodyHandle>,
+ /// The handle of the first body involved in the potential collision.
+ pub rigid_body2: Option<RigidBodyHandle>,
}
/// Context given to custom contact modifiers to modify the contacts seen by the constraints solver.
-pub struct ContactModificationContext<'a> {
- /// The first collider involved in the potential collision.
- pub rigid_body1: &'a RigidBody,
- /// The first collider involved in the potential collision.
- pub rigid_body2: &'a RigidBody,
- /// The first collider involved in the potential collision.
- pub collider_handle1: ColliderHandle,
- /// The first collider involved in the potential collision.
- pub collider_handle2: ColliderHandle,
- /// The first collider involved in the potential collision.
- pub collider1: &'a Collider,
- /// The first collider involved in the potential collision.
- pub collider2: &'a Collider,
+pub struct ContactModificationContext<'a, Bodies, Colliders> {
+ /// The set of rigid-bodies.
+ pub bodies: &'a Bodies,
+ /// The set of colliders.
+ pub colliders: &'a Colliders,
+ /// The handle of the first collider involved in the potential collision.
+ pub collider1: ColliderHandle,
+ /// The handle of the first collider involved in the potential collision.
+ pub collider2: ColliderHandle,
+ /// The handle of the first body involved in the potential collision.
+ pub rigid_body1: Option<RigidBodyHandle>,
+ /// The handle of the first body involved in the potential collision.
+ pub rigid_body2: Option<RigidBodyHandle>,
/// The contact manifold.
pub manifold: &'a ContactManifold,
/// The solver contacts that can be modified.
@@ -45,7 +45,7 @@ pub struct ContactModificationContext<'a> {
pub user_data: &'a mut u32,
}
-impl<'a> ContactModificationContext<'a> {
+impl<'a, Bodies, Colliders> ContactModificationContext<'a, Bodies, Colliders> {
/// Helper function to update `self` to emulate a oneway-platform.
///
/// The "oneway" behavior will only allow contacts between two colliders
@@ -127,9 +127,14 @@ bitflags::bitflags! {
const MODIFY_SOLVER_CONTACTS = 0b0100;
}
}
+impl Default for PhysicsHooksFlags {
+ fn default() -> Self {
+ PhysicsHooksFlags::empty()
+ }
+}
/// User-defined functions called by the physics engines during one timestep in order to customize its behavior.
-pub trait PhysicsHooks: Send + Sync {
+pub trait PhysicsHooks<Bodies, Colliders>: Send + Sync {
/// The sets of hooks that must be taken into account.
fn active_hooks(&self) -> PhysicsHooksFlags;
@@ -156,7 +161,10 @@ pub trait PhysicsHooks: Send + Sync {
/// will be taken into account by the constraints solver. If this returns
/// `Some(SolverFlags::empty())` then the constraints solver will ignore these
/// contacts.
- fn filter_contact_pair(&self, _context: &PairFilterContext) -> Option<SolverFlags> {
+ fn filter_contact_pair(
+ &self,
+ _context: &PairFilterContext<Bodies, Colliders>,
+ ) -> Option<SolverFlags> {
None
}
@@ -179,7 +187,7 @@ pub trait PhysicsHooks: Send + Sync {
/// not compute any intersection information for it.
/// If this return `true` then the narrow-phase will compute intersection
/// information for this pair.
- fn filter_intersection_pair(&self, _context: &PairFilterContext) -> bool {
+ fn filter_intersection_pair(&self, _context: &PairFilterContext<Bodies, Colliders>) -> bool {
false
}
@@ -207,21 +215,22 @@ pub trait PhysicsHooks: Send + Sync {
/// as 0 and can be modified in `context.user_data`.
///
/// The world-space contact normal can be modified in `context.normal`.
- fn modify_solver_contacts(&self, _context: &mut ContactModificationContext) {}
+ fn modify_solver_contacts(&self, _context: &mut ContactModificationContext<Bodies, Colliders>) {
+ }
}
-impl PhysicsHooks for () {
+impl<Bodies, Colliders> PhysicsHooks<Bodies, Colliders> for () {
fn active_hooks(&self) -> PhysicsHooksFlags {
PhysicsHooksFlags::empty()
}
- fn filter_contact_pair(&self, _: &PairFilterContext) -> Option<SolverFlags> {
+ fn filter_contact_pair(&self, _: &PairFilterContext<Bodies, Colliders>) -> Option<SolverFlags> {
None
}
- fn filter_intersection_pair(&self, _: &PairFilterContext) -> bool {
+ fn filter_intersection_pair(&self, _: &PairFilterContext<Bodies, Colliders>) -> bool {
false
}
- fn modify_solver_contacts(&self, _: &mut ContactModificationContext) {}
+ fn modify_solver_contacts(&self, _: &mut ContactModificationContext<Bodies, Colliders>) {}
}
diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs
index f4ac531..2f2a95d 100644
--- a/src/pipeline/physics_pipeline.rs
+++ b/src/pipeline/physics_pipeline.rs
@@ -1,17 +1,28 @@
//! Physics pipeline structures.
use crate::counters::Counters;
+use crate::data::{BundleSet, ComponentSet, ComponentSetMut, ComponentSetOption};
#[cfg(not(feature = "parallel"))]
use crate::dynamics::IslandSolver;
-use crate::dynamics::{CCDSolver, IntegrationParameters, JointSet, RigidBodySet};
+use crate::dynamics::{
+ CCDSolver, IntegrationParameters, IslandManager, JointSet, RigidBodyActivation, RigidBodyCcd,
+ RigidBodyChanges, RigidBodyColliders, RigidBodyDamping, RigidBodyDominance, RigidBodyForces,
+ RigidBodyHandle, RigidBodyIds, RigidBodyMassProps, RigidBodyPosition, RigidBodyType,
+ RigidBodyVelocity,
+};
#[cfg(feature = "parallel")]
use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver};
use crate::geometry::{
- BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactManifoldIndex, NarrowPhase,
+ BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups,
+ ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition,
+ ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase,
};
use crate::math::{Real, Vector};
use crate::pipeline::{EventHandler, PhysicsHooks};
+#[cfg(feature = "default-sets")]
+use {crate::dynamics::RigidBodySet, crate::geometry::ColliderSet};
+
/// The physics pipeline, responsible for stepping the whole physics simulation.
///
/// This structure only contains temporary data buffers. It can be dropped and replaced by a fresh
@@ -58,17 +69,43 @@ impl PhysicsPipeline {
}
}
- fn detect_collisions(
+ fn clear_modified_colliders(
+ &mut self,
+ colliders: &mut impl ComponentSetMut<ColliderChanges>,
+ modified_colliders: &mut Vec<ColliderHandle>,
+ ) {
+ for handle in modified_colliders.drain(..) {
+ colliders.set_internal(handle.0, ColliderChanges::empty())
+ }
+ }
+
+ fn detect_collisions<Bodies, Colliders>(
&mut self,
integration_parameters: &IntegrationParameters,
+ islands: &mut IslandManager,
broad_phase: &mut BroadPhase,
narrow_phase: &mut NarrowPhase,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
- hooks: &dyn PhysicsHooks,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
+ modified_colliders: &[ColliderHandle],
+ removed_colliders: &[ColliderHandle],
+ hooks: &dyn PhysicsHooks<Bodies, Colliders>,
events: &dyn EventHandler,
handle_user_changes: bool,
- ) {
+ ) where
+ Bodies: ComponentSetMut<RigidBodyActivation>
+ + ComponentSet<RigidBodyType>
+ + ComponentSetMut<RigidBodyIds>
+ + ComponentSet<RigidBodyDominance>,
+ Colliders: ComponentSetMut<ColliderBroadPhaseData>
+ + ComponentSet<ColliderChanges>
+ + ComponentSet<ColliderPosition>
+ + ComponentSet<ColliderShape>
+ + ComponentSetOption<ColliderParent>
+ + ComponentSet<ColliderType>
+ + ComponentSet<ColliderGroups>
+ + ComponentSet<ColliderMaterial>,
+ {
self.counters.stages.collision_detection_time.resume();
self.counters.cd.broad_phase_time.resume();
@@ -78,6 +115,8 @@ impl PhysicsPipeline {
broad_phase.update(
integration_parameters.prediction_distance,
colliders,
+ modified_colliders,
+ removed_colliders,
&mut self.broad_phase_events,
);
@@ -86,37 +125,52 @@ impl PhysicsPipeline {
// Update narrow-phase.
if handle_user_changes {
- narrow_phase.handle_user_changes(colliders, bodies, events);
+ narrow_phase.handle_user_changes(
+ Some(islands),
+ modified_colliders,
+ removed_colliders,
+ colliders,
+ bodies,
+ events,
+ );
}
- narrow_phase.register_pairs(colliders, bodies, &self.broad_phase_events, events);
+ narrow_phase.register_pairs(
+ Some(islands),
+ colliders,
+ bodies,
+ &self.broad_phase_events,
+ events,
+ );
narrow_phase.compute_contacts(
integration_parameters.prediction_distance,
bodies,
colliders,
+ modified_colliders,
hooks,
events,
);
- narrow_phase.compute_intersections(bodies, colliders, hooks, events);
-
- // Clear colliders modification flags.
- colliders.clear_modified_colliders();
+ narrow_phase.compute_intersections(bodies, colliders, modified_colliders, hooks, events);
self.counters.cd.narrow_phase_time.pause();
self.counters.stages.collision_detection_time.pause();
}
- fn solve_position_constraints(
+ fn solve_position_constraints<Bodies>(
&mut self,
integration_parameters: &IntegrationParameters,
- bodies: &mut RigidBodySet,
- ) {
+ islands: &IslandManager,
+ bodies: &mut Bodies,
+ ) where
+ Bodies: ComponentSet<RigidBodyIds> + ComponentSetMut<RigidBodyPosition>,
+ {
#[cfg(not(feature = "parallel"))]
{
enable_flush_to_zero!();
- for island_id in 0..bodies.num_islands() {
+ for island_id in 0..islands.num_islands() {
self.solvers[island_id].solve_position_constraints(
island_id,
+ islands,
&mut self.counters,
integration_parameters,
bodies,
@@ -129,7 +183,7 @@ impl PhysicsPipeline {
use rayon::prelude::*;
use std::sync::atomic::Ordering;
- let num_islands = bodies.num_islands();
+ let num_islands = islands.num_islands();
let solvers = &mut self.solvers[..num_islands];
let bodies = &std::sync::atomic::AtomicPtr::new(bodies as *mut _);
@@ -140,12 +194,13 @@ impl PhysicsPipeline {
.par_iter_mut()
.enumerate()
.for_each(|(island_id, solver)| {
- let bodies: &mut RigidBodySet =
+ let bodies: &mut Bodies =
unsafe { std::mem::transmute(bodies.load(Ordering::Relaxed)) };
solver.solve_position_constraints(
scope,
island_id,
+ islands,
integration_parameters,
bodies,
)
@@ -154,17 +209,30 @@ impl PhysicsPipeline {
}
}
- fn build_islands_and_solve_velocity_constraints(
+ fn build_islands_and_solve_velocity_constraints<Bodies, Colliders>(
&mut self,
gravity: &Vector<Real>,
integration_parameters: &IntegrationParameters,
+ islands: &mut IslandManager,
narrow_phase: &mut NarrowPhase,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
joints: &mut JointSet,
- ) {
+ ) where
+ Bodies: ComponentSetMut<RigidBodyPosition>
+ + ComponentSetMut<RigidBodyVelocity>
+ + ComponentSetMut<RigidBodyMassProps>
+ + ComponentSetMut<RigidBodyForces>
+ + ComponentSetMut<RigidBodyIds>
+ + ComponentSetMut<RigidBodyActivation>
+ + ComponentSet<RigidBodyDamping>
+ + ComponentSet<RigidBodyColliders>
+ + ComponentSet<RigidBodyType>,
+ Colliders: ComponentSetOption<ColliderParent>,
+ {
self.counters.stages.island_construction_time.resume();
- bodies.update_active_set_with_contacts(
+ islands.update_active_set_with_contacts(
+ bodies,
colliders,
narrow_phase,
joints.joint_graph(),
@@ -172,42 +240,58 @@ impl PhysicsPipeline {
);
self.counters.stages.island_construction_time.pause();
- if self.manifold_indices.len() < bodies.num_islands() {
+ if self.manifold_indices.len() < islands.num_islands() {
self.manifold_indices
- .resize(bodies.num_islands(), Vec::new());
+ .resize(islands.num_islands(), Vec::new());
}
- if self.joint_constraint_indices.len() < bodies.num_islands() {
+ if self.joint_constraint_indices.len() < islands.num_islands() {
self.joint_constraint_indices
- .resize(bodies.num_islands(), Vec::new());
+ .resize(islands.num_islands(), Vec::new());
}
let mut manifolds = Vec::new();
- narrow_phase.select_active_contacts(bodies, &mut manifolds, &mut self.manifold_indices);
- joints.select_active_interactions(bodies, &mut self.joint_constraint_indices);
+ narrow_phase.select_active_contacts(
+ islands,
+ bodies,
+ &mut manifolds,
+ &mut self.manifold_indices,
+ );
+ joints.select_active_interactions(islands, bodies, &mut self.joint_constraint_indices);
self.counters.stages.update_time.resume();
- bodies.foreach_active_dynamic_body_mut_internal(|_, b| {
- b.update_world_mass_properties();
- b.add_gravity(*gravity)
- });
+ for handle in islands.active_dynamic_bodies() {
+ let poss: &RigidBodyPosition = bodies.index(handle.0);
+ let position = poss.position;
+
+ let effective_inv_mass = bodies
+ .map_mut_internal(handle.0, |mprops: &mut RigidBodyMassProps| {
+ mprops.update_world_mass_properties(&position);
+ mprops.effective_mass()
+ })
+ .unwrap();
+ bodies.map_mut_internal(handle.0, |forces: &mut RigidBodyForces| {
+ forces.add_gravity_acceleration(&gravity, effective_inv_mass)
+ });
+ }
self.counters.stages.update_time.pause();
self.counters.stages.solver_time.resume();
- if self.solvers.len() < bodies.num_islands() {
+ if self.solvers.len() < islands.num_islands() {
self.solvers
- .resize_with(bodies.num_islands(), IslandSolver::new);
+ .resize_with(islands.num_islands(), IslandSolver::new);
}
#[cfg(not(feature = "parallel"))]
{
enable_flush_to_zero!();
- for island_id in 0..bodies.num_islands() {
+ for island_id in 0..islands.num_islands() {
self.solvers[island_id].init_constraints_and_solve_velocity_constraints(
island_id,
&mut self.counters,
integration_parameters,
+ islands,
bodies,
&mut manifolds[..],
&self.manifold_indices[island_id],
@@ -223,7 +307,7 @@ impl PhysicsPipeline {
use rayon::prelude::*;
use std::sync::atomic::Ordering;
- let num_islands = bodies.num_islands();
+ let num_islands = islands.num_islands();
let solvers = &mut self.solvers[..num_islands];
let bodies = &std::sync::atomic::AtomicPtr::new(bodies as *mut _);
let manifolds = &std::sync::atomic::AtomicPtr::new(&mut manifolds as *mut _);
@@ -238,7 +322,7 @@ impl PhysicsPipeline {
.par_iter_mut()
.enumerate()
.for_each(|(island_id, solver)| {
- let bodies: &mut RigidBodySet =
+ let bodies: &mut Bodies =
unsafe { std::mem::transmute(bodies.load(Ordering::Relaxed)) };
let manifolds: &mut Vec<&mut ContactManifold> =
unsafe { std::mem::transmute(manifolds.load(Ordering::Relaxed)) };
@@ -248,6 +332,7 @@ impl PhysicsPipeline {
solver.init_constraints_and_solve_velocity_constraints(
scope,
island_id,
+ islands,
integration_parameters,
bodies,
manifolds,
@@ -261,19 +346,32 @@ impl PhysicsPipeline {
self.counters.stages.solver_time.pause();
}
- fn run_ccd_motion_clamping(
+ fn run_ccd_motion_clamping<Bodies, Colliders>(
&mut self,
integration_parameters: &IntegrationParameters,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
+ islands: &IslandManager,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
narrow_phase: &NarrowPhase,
ccd_solver: &mut CCDSolver,
events: &dyn EventHandler,
- ) {
+ ) where
+ Bodies: ComponentSetMut<RigidBodyPosition>
+ + ComponentSet<RigidBodyVelocity>
+ + ComponentSet<RigidBodyCcd>
+ + ComponentSet<RigidBodyColliders>
+ + ComponentSet<RigidBodyForces>
+ + ComponentSet<RigidBodyMassProps>,
+ Colliders: ComponentSetOption<ColliderParent>
+ + ComponentSet<ColliderPosition>
+ + ComponentSet<ColliderShape>
+ + ComponentSet<ColliderType>,
+ {
self.counters.ccd.toi_computation_time.start();
// Handle CCD
let impacts = ccd_solver.predict_impacts_at_next_positions(
integration_parameters.dt,
+ islands,
bodies,
colliders,
narrow_phase,
@@ -283,74 +381,180 @@ impl PhysicsPipeline {
self.counters.ccd.toi_computation_time.pause();
}
- fn advance_to_final_positions(
+ fn advance_to_final_positions<Bodies, Colliders>(
&mut self,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
+ islands: &IslandManager,
+ bodies: &mut Bodies,
+ colliders: &mut Colliders,
+ modified_colliders: &mut Vec<ColliderHandle>,
clear_forces: bool,
- ) {
+ ) where
+ Bodies: ComponentSetMut<RigidBodyVelocity>
+ + ComponentSetMut<RigidBodyForces>
+ + ComponentSetMut<RigidBodyPosition>
+ + ComponentSet<RigidBodyType>
+ + ComponentSet<RigidBodyColliders>,
+ Colliders: ComponentSetMut<ColliderPosition>
+ + ComponentSetMut<ColliderChanges>
+ + ComponentSetOption<ColliderParent>,
+ {
// Set the rigid-bodies and kinematic bodies to their final position.
- bodies.foreach_active_body_mut_internal(|_, rb| {
- if rb.is_kinematic() {
- rb.linvel = na::zero();
- rb.angvel = na::zero();
+ for handle in islands.iter_active_bodies() {
+ let status: &RigidBodyType = bodies.index(handle.0);
+ if status.is_kinematic() {
+ bodies.set_internal(handle.0, RigidBodyVelocity::zero());
}
if clear_forces {
- rb.force = na::zero();
- rb.torque = na::zero();
+ bodies.map_mut_internal(handle.0, |f: &mut RigidBodyForces| {
+ f.torque = na::zero();
+ f.force = na::zero();
+ });
}
- rb.position = rb.next_position;
- rb.update_colliders_positions(colliders);
- });
+ bodies.map_mut_internal(handle.0, |poss: &mut RigidBodyPosition| {
+ poss.position = poss.next_position
+ });
+
+ let (rb_poss, rb_colls): (&RigidBodyPosition, &RigidBodyColliders) =
+ bodies.index_bundle(handle.0);
+ rb_colls.update_positions(colliders, modified_colliders, &rb_poss.position);
+ }
}
- fn interpolate_kinematic_velocities(
+ fn interpolate_kinematic_velocities<Bodies>(
&mut self,
integration_parameters: &IntegrationParameters,
- bodies: &mut RigidBodySet,
- ) {
+ islands: &IslandManager,
+ bodies: &mut Bodies,
+ ) where
+ Bodies: ComponentSetMut<RigidBodyVelocity> + ComponentSet<RigidBodyPosition>,
+ {
// Update kinematic bodies velocities.
// TODO: what is the best place for this? It should at least be
// located before the island computation because we test the velocity
// there to determine if this kinematic body should wake-up dynamic
// bodies it is touching.
- bodies.foreach_active_kinematic_body_mut_internal(|_, body| {
- body.compute_velocity_from_next_position(integration_parameters.inv_dt());
- });
+ for handle in islands.active_kinematic_bodies() {
+ let ppos: &RigidBodyPosition = bodies.index(handle.0);
+ let new_vel = ppos.interpolate_velocity(integration_parameters.inv_dt());
+ bodies.set_internal(handle.0, new_vel);
+ }
}
/// Executes one timestep of the physics simulation.
+ ///
+ /// This is the same as `self.step_generic`, except that it is specialized
+ /// to work with `RigidBodySet` and `ColliderSet`.
+ #[cfg(feature = "default-sets")]
pub fn step(
&mut self,
gravity: &Vector<Real>,
integration_parameters: &IntegrationParameters,
+ islands: &mut IslandManager,
broad_phase: &mut BroadPhase,
narrow_phase: &mut NarrowPhase,
bodies: &mut RigidBodySet,
colliders: &mut ColliderSet,
joints: &mut JointSet,
ccd_solver: &mut CCDSolver,
- hooks: &dyn PhysicsHooks,
+ hooks: &dyn PhysicsHooks<RigidBodySet, ColliderSet>,
events: &dyn EventHandler,
) {
+ let mut modified_bodies = bodies.take_modified();
+ let mut modified_colliders = colliders.take_modified();
+ let mut removed_colliders = colliders.take_removed();
+
+ self.step_generic(
+ gravity,
+ integration_parameters,
+ islands,
+ broad_phase,
+ narrow_phase,
+ bodies,
+ colliders,
+ &mut modified_bodies,
+ &mut modified_colliders,
+ &mut removed_colliders,
+ joints,
+ ccd_solver,
+ hooks,
+ events,
+ );
+ }
+
+ /// Executes one timestep of the physics simulation.
+ pub fn step_generic<Bodies, Colliders>(