diff options
Diffstat (limited to 'src/pipeline')
| -rw-r--r-- | src/pipeline/collision_pipeline.rs | 187 | ||||
| -rw-r--r-- | src/pipeline/mod.rs | 1 | ||||
| -rw-r--r-- | src/pipeline/physics_hooks.rs | 83 | ||||
| -rw-r--r-- | src/pipeline/physics_pipeline.rs | 393 | ||||
| -rw-r--r-- | src/pipeline/query_pipeline.rs | 444 | ||||
| -rw-r--r-- | src/pipeline/user_changes.rs | 178 |
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>( + &mut self, + gravity: &Vector<Real>, + integration_parameters: &IntegrationParameters, + islands: &mut IslandManager, + 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>, + joints: &mut JointSet, + ccd_solver: &mut CCDSolver, + hooks: &dyn PhysicsHooks<Bodies, Colliders>, + events: &dyn EventHandler, + ) where + Bodies: ComponentSetMut<RigidBodyPosition> + + ComponentSetMut<RigidBodyVelocity> + + ComponentSetMut<RigidBodyMassProps> + + ComponentSetMut<RigidBodyIds> + + ComponentSetMut<RigidBodyForces> + + ComponentSetMut<RigidBodyActivation> + + ComponentSetMut<RigidBodyChanges> + + ComponentSetMut<RigidBodyCcd> + + ComponentSet<RigidBodyColliders> + + ComponentSet<RigidBodyDamping> + + ComponentSet<RigidBodyDominance> + + ComponentSet<RigidBodyType>, + Colliders: ComponentSetMut<ColliderBroadPhaseData> + + ComponentSetMut<ColliderChanges> + + ComponentSetMut<ColliderPosition> + + ComponentSet<ColliderShape> |
