From 2b1374c596957ac8cabe085859be3b823a1ba0c6 Mon Sep 17 00:00:00 2001 From: Sébastien Crozet Date: Tue, 19 Apr 2022 18:57:40 +0200 Subject: First round deleting the component sets. --- src/pipeline/collision_pipeline.rs | 66 +++-------- src/pipeline/physics_hooks.rs | 53 ++++----- src/pipeline/physics_pipeline.rs | 139 +++++----------------- src/pipeline/query_pipeline.rs | 231 +++++++++++-------------------------- src/pipeline/user_changes.rs | 98 ++++++---------- 5 files changed, 168 insertions(+), 419 deletions(-) (limited to 'src/pipeline') diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index 009dfa9..48a11e7 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -1,14 +1,8 @@ //! Physics pipeline structures. -use crate::data::{ComponentSet, ComponentSetMut, ComponentSetOption}; -use crate::dynamics::{ - RigidBodyActivation, RigidBodyChanges, RigidBodyColliders, RigidBodyDominance, RigidBodyHandle, - RigidBodyIds, RigidBodyMassProps, RigidBodyPosition, RigidBodyType, RigidBodyVelocity, -}; +use crate::dynamics::RigidBodyHandle; use crate::geometry::{ - BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, - ColliderHandle, ColliderMassProps, ColliderMaterial, ColliderPair, ColliderParent, - ColliderPosition, ColliderShape, ColliderType, NarrowPhase, + BroadPhase, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair, NarrowPhase, }; use crate::math::Real; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -48,32 +42,19 @@ impl CollisionPipeline { } } - fn detect_collisions( + fn detect_collisions( &mut self, prediction_distance: Real, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_colliders: &[ColliderHandle], removed_colliders: &[ColliderHandle], - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, handle_user_changes: bool, - ) where - Bodies: ComponentSetMut - + ComponentSet - + ComponentSetMut - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSetOption - + ComponentSet - + ComponentSet - + ComponentSet, - { + ) { // Update broad-phase. self.broad_phase_events.clear(); self.broadphase_collider_pairs.clear(); @@ -112,7 +93,7 @@ impl CollisionPipeline { fn clear_modified_colliders( &mut self, - colliders: &mut impl ComponentSetMut, + colliders: &mut ColliderSet, modified_colliders: &mut Vec, ) { for handle in modified_colliders.drain(..) { @@ -129,7 +110,7 @@ impl CollisionPipeline { narrow_phase: &mut NarrowPhase, bodies: &mut RigidBodySet, colliders: &mut ColliderSet, - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, ) { let mut modified_bodies = bodies.take_modified(); @@ -151,38 +132,19 @@ impl CollisionPipeline { } /// Executes one step of the collision detection. - pub fn step_generic( + pub fn step_generic( &mut self, prediction_distance: Real, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_bodies: &mut Vec, modified_colliders: &mut Vec, removed_colliders: &mut Vec, - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, - ) where - Bodies: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSetOption - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - { + ) { super::user_changes::handle_user_changes_to_colliders( bodies, colliders, diff --git a/src/pipeline/physics_hooks.rs b/src/pipeline/physics_hooks.rs index 68a05d1..4024237 100644 --- a/src/pipeline/physics_hooks.rs +++ b/src/pipeline/physics_hooks.rs @@ -1,14 +1,14 @@ -use crate::dynamics::RigidBodyHandle; -use crate::geometry::{ColliderHandle, ContactManifold, SolverContact, SolverFlags}; +use crate::dynamics::{RigidBodyHandle, RigidBodySet}; +use crate::geometry::{ColliderHandle, ColliderSet, 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, Bodies, Colliders> { +pub struct PairFilterContext<'a> { /// The set of rigid-bodies. - pub bodies: &'a Bodies, + pub bodies: &'a RigidBodySet, /// The set of colliders. - pub colliders: &'a Colliders, + pub colliders: &'a ColliderSet, /// 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. @@ -20,11 +20,11 @@ pub struct PairFilterContext<'a, Bodies, Colliders> { } /// Context given to custom contact modifiers to modify the contacts seen by the constraints solver. -pub struct ContactModificationContext<'a, Bodies, Colliders> { +pub struct ContactModificationContext<'a> { /// The set of rigid-bodies. - pub bodies: &'a Bodies, + pub bodies: &'a RigidBodySet, /// The set of colliders. - pub colliders: &'a Colliders, + pub colliders: &'a ColliderSet, /// 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. @@ -45,7 +45,7 @@ pub struct ContactModificationContext<'a, Bodies, Colliders> { pub user_data: &'a mut u32, } -impl<'a, Bodies, Colliders> ContactModificationContext<'a, Bodies, Colliders> { +impl<'a> ContactModificationContext<'a> { /// Helper function to update `self` to emulate a oneway-platform. /// /// The "oneway" behavior will only allow contacts between two colliders @@ -139,28 +139,24 @@ impl Default for ActiveHooks { // not having Send+Sync isn't a problem. /// User-defined functions called by the physics engines during one timestep in order to customize its behavior. #[cfg(target_arch = "wasm32")] -pub trait PhysicsHooks { +pub trait PhysicsHooks { /// Applies the contact pair filter. - fn filter_contact_pair( - &self, - _context: &PairFilterContext, - ) -> Option { + fn filter_contact_pair(&self, _context: &PairFilterContext) -> Option { None } /// Applies the intersection pair filter. - fn filter_intersection_pair(&self, _context: &PairFilterContext) -> bool { + fn filter_intersection_pair(&self, _context: &PairFilterContext) -> bool { false } /// Modifies the set of contacts seen by the constraints solver. - fn modify_solver_contacts(&self, _context: &mut ContactModificationContext) { - } + fn modify_solver_contacts(&self, _context: &mut ContactModificationContext) {} } /// User-defined functions called by the physics engines during one timestep in order to customize its behavior. #[cfg(not(target_arch = "wasm32"))] -pub trait PhysicsHooks: Send + Sync { +pub trait PhysicsHooks: Send + Sync { /// Applies the contact pair filter. /// /// Note that this method will only be called if at least one of the colliders @@ -185,10 +181,7 @@ 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 { + fn filter_contact_pair(&self, _context: &PairFilterContext) -> Option { Some(SolverFlags::COMPUTE_IMPULSES) } @@ -212,7 +205,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) -> bool { true } @@ -241,21 +234,17 @@ 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) {} } -impl PhysicsHooks for () { - fn filter_contact_pair( - &self, - _context: &PairFilterContext, - ) -> Option { +impl PhysicsHooks for () { + fn filter_contact_pair(&self, _context: &PairFilterContext) -> Option { Some(SolverFlags::default()) } - fn filter_intersection_pair(&self, _: &PairFilterContext) -> bool { + fn filter_intersection_pair(&self, _: &PairFilterContext) -> bool { true } - fn modify_solver_contacts(&self, _: &mut ContactModificationContext) {} + fn modify_solver_contacts(&self, _: &mut ContactModificationContext) {} } diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index 2d90c4b..ffcb25f 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -1,21 +1,18 @@ //! 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, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, - RigidBodyActivation, RigidBodyCcd, RigidBodyChanges, RigidBodyColliders, RigidBodyDamping, - RigidBodyDominance, RigidBodyForces, RigidBodyHandle, RigidBodyIds, RigidBodyMassProps, - RigidBodyPosition, RigidBodyType, RigidBodyVelocity, + RigidBodyColliders, RigidBodyForces, RigidBodyHandle, RigidBodyMassProps, RigidBodyPosition, + RigidBodyType, RigidBodyVelocity, }; #[cfg(feature = "parallel")] use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver}; use crate::geometry::{ - BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, - ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, - ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase, ColliderMassProps + BroadPhase, BroadPhasePairEvent, ColliderChanges, ColliderHandle, ColliderPair, + ContactManifoldIndex, NarrowPhase, }; use crate::math::{Real, Vector}; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -71,7 +68,7 @@ impl PhysicsPipeline { fn clear_modified_colliders( &mut self, - colliders: &mut impl ComponentSetMut, + colliders: &mut ColliderSet, modified_colliders: &mut Vec, ) { for handle in modified_colliders.drain(..) { @@ -79,33 +76,20 @@ impl PhysicsPipeline { } } - fn detect_collisions( + fn detect_collisions( &mut self, integration_parameters: &IntegrationParameters, islands: &mut IslandManager, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_colliders: &[ColliderHandle], removed_colliders: &[ColliderHandle], - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, handle_user_changes: bool, - ) where - Bodies: ComponentSetMut - + ComponentSet - + ComponentSetMut - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSetOption - + ComponentSet - + ComponentSet - + ComponentSet, - { + ) { self.counters.stages.collision_detection_time.resume(); self.counters.cd.broad_phase_time.resume(); @@ -155,28 +139,17 @@ impl PhysicsPipeline { self.counters.stages.collision_detection_time.pause(); } - fn build_islands_and_solve_velocity_constraints( + fn build_islands_and_solve_velocity_constraints( &mut self, gravity: &Vector, integration_parameters: &IntegrationParameters, islands: &mut IslandManager, narrow_phase: &mut NarrowPhase, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, impulse_joints: &mut ImpulseJointSet, multibody_joints: &mut MultibodyJointSet, - ) where - Bodies: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSetOption, - { + ) { self.counters.stages.island_construction_time.resume(); islands.update_active_set_with_contacts( integration_parameters.dt, @@ -285,7 +258,7 @@ impl PhysicsPipeline { .par_iter_mut() .enumerate() .for_each(|(island_id, solver)| { - let bodies: &mut Bodies = + let bodies: &mut RigidBodySet = unsafe { std::mem::transmute(bodies.load(Ordering::Relaxed)) }; let manifolds: &mut Vec<&mut ContactManifold> = unsafe { std::mem::transmute(manifolds.load(Ordering::Relaxed)) }; @@ -313,28 +286,16 @@ impl PhysicsPipeline { self.counters.stages.solver_time.pause(); } - fn run_ccd_motion_clamping( + fn run_ccd_motion_clamping( &mut self, integration_parameters: &IntegrationParameters, islands: &IslandManager, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, narrow_phase: &NarrowPhase, ccd_solver: &mut CCDSolver, events: &dyn EventHandler, - ) where - Bodies: ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSetOption - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - { + ) { self.counters.ccd.toi_computation_time.start(); // Handle CCD let impacts = ccd_solver.predict_impacts_at_next_positions( @@ -349,22 +310,13 @@ impl PhysicsPipeline { self.counters.ccd.toi_computation_time.pause(); } - fn advance_to_final_positions( + fn advance_to_final_positions( &mut self, islands: &IslandManager, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_colliders: &mut Vec, - ) where - Bodies: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSetMut - + ComponentSetOption, - { + ) { // Set the rigid-bodies and kinematic bodies to their final position. for handle in islands.iter_active_bodies() { bodies.map_mut_internal(handle.0, |poss: &mut RigidBodyPosition| { @@ -377,17 +329,12 @@ impl PhysicsPipeline { } } - fn interpolate_kinematic_velocities( + fn interpolate_kinematic_velocities( &mut self, integration_parameters: &IntegrationParameters, islands: &IslandManager, - bodies: &mut Bodies, - ) where - Bodies: ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet, - { + bodies: &mut RigidBodySet, + ) { // 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 @@ -440,7 +387,7 @@ impl PhysicsPipeline { impulse_joints: &mut ImpulseJointSet, multibody_joints: &mut MultibodyJointSet, ccd_solver: &mut CCDSolver, - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, ) { let mut modified_bodies = bodies.take_modified(); @@ -467,46 +414,24 @@ impl PhysicsPipeline { } /// Executes one timestep of the physics simulation. - pub fn step_generic( + pub fn step_generic( &mut self, gravity: &Vector, integration_parameters: &IntegrationParameters, islands: &mut IslandManager, broad_phase: &mut BroadPhase, narrow_phase: &mut NarrowPhase, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_bodies: &mut Vec, modified_colliders: &mut Vec, removed_colliders: &mut Vec, impulse_joints: &mut ImpulseJointSet, multibody_joints: &mut MultibodyJointSet, ccd_solver: &mut CCDSolver, - hooks: &dyn PhysicsHooks, + hooks: &dyn PhysicsHooks, events: &dyn EventHandler, - ) where - Bodies: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSetOption - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - { + ) { self.counters.reset(); self.counters.step_started(); diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index a5565cd..584989e 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -1,4 +1,3 @@ -use crate::data::{BundleSet, ComponentSet, ComponentSetOption}; use crate::dynamics::{ IslandManager, RigidBodyColliders, RigidBodyForces, RigidBodyMassProps, RigidBodyPosition, RigidBodyVelocity, @@ -40,9 +39,9 @@ pub struct QueryPipeline { dilation_factor: Real, } -struct QueryPipelineAsCompositeShape<'a, Colliders> { +struct QueryPipelineAsCompositeShape<'a> { query_pipeline: &'a QueryPipeline, - colliders: &'a Colliders, + colliders: &'a ColliderSet, query_groups: InteractionGroups, filter: Option<&'a dyn Fn(ColliderHandle) -> bool>, } @@ -63,12 +62,7 @@ pub enum QueryPipelineMode { }, } -impl<'a, Colliders> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a, Colliders> -where - // TODO ECS: make everything optional but the shape? - Colliders: - ComponentSet + ComponentSet + ComponentSet, -{ +impl<'a> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a> { type PartShape = dyn Shape; type PartId = ColliderHandle; @@ -77,15 +71,11 @@ where shape_id: Self::PartId, mut f: impl FnMut(Option<&Isometry>, &Self::PartShape), ) { - let co_flags: Option<&ColliderFlags> = self.colliders.get(shape_id.0); - - if let Some(co_flags) = co_flags { - if co_flags.collision_groups.test(self.query_groups) + if let Some(co) = self.colliders.get(shape_id) { + if co.flags.collision_groups.test(self.query_groups) && self.filter.map(|f| f(shape_id)).unwrap_or(true) { - let (co_pos, co_shape): (&ColliderPosition, &ColliderShape) = - self.colliders.index_bundle(shape_id.0); - f(Some(co_pos), &**co_shape) + f(Some(co.pos), &**co.shape) } } } @@ -115,12 +105,12 @@ impl QueryPipeline { Self::with_query_dispatcher(DefaultQueryDispatcher) } - fn as_composite_shape<'a, Colliders>( + fn as_composite_shape<'a>( &'a self, - colliders: &'a Colliders, + colliders: &'a ColliderSet, query_groups: InteractionGroups, filter: Option<&'a dyn Fn(ColliderHandle) -> bool>, - ) -> QueryPipelineAsCompositeShape<'a, Colliders> { + ) -> QueryPipelineAsCompositeShape<'a> { QueryPipelineAsCompositeShape { query_pipeline: self, colliders, @@ -162,21 +152,12 @@ impl QueryPipeline { } /// Update the acceleration structure on the query pipeline. - pub fn update_generic( + pub fn update_generic( &mut self, islands: &IslandManager, - bodies: &Bodies, - colliders: &Colliders, - ) where - Bodies: ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSet - + ComponentSet - + ComponentSetOption, - { + bodies: &RigidBodySet, + colliders: &ColliderSet, + ) { self.update_with_mode( islands, bodies, @@ -186,40 +167,22 @@ impl QueryPipeline { } /// Update the acceleration structure on the query pipeline. - pub fn update_with_mode( + pub fn update_with_mode( &mut self, islands: &IslandManager, - bodies: &Bodies, - colliders: &Colliders, + bodies: &RigidBodySet, + colliders: &ColliderSet, mode: QueryPipelineMode, - ) where - Bodies: ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - Colliders: ComponentSet - + ComponentSet - + ComponentSetOption, - { - struct DataGenerator<'a, Bs, Cs> { - bodies: &'a Bs, - colliders: &'a Cs, + ) { + struct DataGenerator<'a> { + bodies: &'a RigidBodySet, + colliders: &'a ColliderSet, mode: QueryPipelineMode, } - impl<'a, Bs, Cs> QBVHDataGenerator for DataGenerator<'a, Bs, Cs> - where - Bs: ComponentSet - + ComponentSet - + ComponentSet - + ComponentSet, - Cs: ComponentSet - + ComponentSet - + ComponentSetOption, - { + impl<'a> QBVHDataGenerator for DataGenerator<'a> { fn size_hint(&self) -> usize { - ComponentSet::::size_hint(self.colliders) + self.colliders.len() } #[inline(always)] @@ -313,16 +276,13 @@ impl QueryPipeline { QueryPipelineMode::SweepTestWithNextPosition => { self.qbvh.update( |handle| { - let co_parent: Option<&ColliderParent> = colliders.get(handle.0); - let (co_pos, co_shape): (&ColliderPosition, &ColliderShape) = - colliders.index_bundle(handle.0); - - if let Some(co_parent) = co_parent { - let rb_pos: &RigidBodyPosition = bodies.index(co_parent.handle.0); - let next_position = rb_pos.next_position * co_parent.pos_wrt_parent; - co_shape.compute_swept_aabb(&co_pos, &next_position) + let co = &colliders[handle]; + if let Some(parent) = co.parent { + let rb_pos: &RigidBodyPosition = bodies.index(co.parent.handle.0); + let next_position = rb_pos.next_position * co.parent.pos_wrt_parent; + co.shape.compute_swept_aabb(&co.pos, &next_position) } else { - co_shape.compute_aabb(&co_pos) + co.shape.compute_aabb(&co.pos) } }, self.dilation_factor, @@ -331,25 +291,17 @@ impl QueryPipeline { QueryPipelineMode::SweepTestWithPredictedPosition { dt } => { self.qbvh.update( |handle| { - let co_parent: Option<&ColliderParent> = colliders.get(handle.0); - let (co_pos, co_shape): (&ColliderPosition, &ColliderShape) = - colliders.index_bundle(handle.0); - - if let Some(co_parent) = co_parent { - let (rb_pos, vels, forces, mprops): ( - &RigidBodyPosition, - &RigidBodyVelocity, - &RigidBodyForces, - &RigidBodyMassProps, - ) = bodies.index_bundle(co_parent.handle.0); - - let predicted_pos = - rb_pos.integrate_forces_and_velocities(dt, forces, vels, mprops); - - let next_position = predicted_pos * co_parent.pos_wrt_parent; - co_shape.compute_swept_aabb(&co_pos, &next_position) + let co = &colliders[handle]; + if let Some(parent) = co.parent { + let rb = &bodies[parent.handle]; + let predicted_pos = rb + .pos + .integrate_forces_and_velocities(dt, rb.forces, rb.vels, rb.mprops); + + let next_position = predicted_pos * parent.pos_wrt_parent; + co.shape.compute_swept_aabb(&co.pos, &next_position) } else { - co_shape.compute_aabb(&co_pos) + co.shape.compute_aabb(&co.pos) } }, self.dilation_factor, @@ -373,20 +325,15 @@ impl QueryPipeline { /// * `filter`: a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn cast_ray( + pub fn cast_ray( &self, - colliders: &Colliders, + colliders: &ColliderSet, ray: &Ray, max_toi: Real, solid: bool, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, Real)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, Real)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = RayCompositeShapeToiBestFirstVisitor::new(&pipeline_shape, ray, max_toi, solid); @@ -409,20 +356,15 @@ impl QueryPipeline { /// * `filter`: a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn cast_ray_and_get_normal( + pub fn cast_ray_and_get_normal( &self, - colliders: &Colliders, + colliders: &ColliderSet, ray: &Ray, max_toi: Real, solid: bool, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, RayIntersection)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, RayIntersection)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = RayCompositeShapeToiAndNormalBestFirstVisitor::new( &pipeline_shape, @@ -452,20 +394,16 @@ impl QueryPipeline { /// * `callback`: function executed on each collider for which a ray intersection has been found. /// There is no guarantees on the order the results will be yielded. If this callback returns `false`, /// this method will exit early, ignore any further raycast. - pub fn intersections_with_ray<'a, Colliders>( + pub fn intersections_with_ray<'a, ColliderSet>( &self, - colliders: &'a Colliders, + colliders: &'a ColliderSet, ray: &Ray, max_toi: Real, solid: bool, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle, RayIntersection) -> bool, - ) where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) { let mut leaf_callback = &mut |handle: &ColliderHandle| { let co_shape: Option<&ColliderShape> = colliders.get(handle.0); if let Some(co_shape) = co_shape { @@ -499,19 +437,14 @@ impl QueryPipeline { /// * `filter` - a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn intersection_with_shape( + pub fn intersection_with_shape( &self, - colliders: &Colliders, + colliders: &ColliderSet, shape_pos: &Isometry, shape: &dyn Shape, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = IntersectionCompositeShapeShapeBestFirstVisitor::new( &*self.query_dispatcher, @@ -540,19 +473,14 @@ impl QueryPipeline { /// * `filter` - a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn project_point( + pub fn project_point( &self, - colliders: &Colliders, + colliders: &ColliderSet, point: &Point, solid: bool, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, PointProjection)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, PointProjection)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = PointCompositeShapeProjBestFirstVisitor::new(&pipeline_shape, point, solid); @@ -574,18 +502,14 @@ impl QueryPipeline { /// is either `None` or returns `true`. /// * `callback` - A function called with each collider with a shape /// containing the `point`. - pub fn intersections_with_point<'a, Colliders>( + pub fn intersections_with_point<'a, ColliderSet>( &self, - colliders: &'a Colliders, + colliders: &'a ColliderSet, point: &Point, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle) -> bool, - ) where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) { let mut leaf_callback = &mut |handle: &ColliderHandle| { let co_shape: Option<&ColliderShape> = colliders.get(handle.0); @@ -626,18 +550,13 @@ impl QueryPipeline { /// * `filter` - a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn project_point_and_get_feature( + pub fn project_point_and_get_feature( &self, - colliders: &Colliders, + colliders: &ColliderSet, point: &Point, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, PointProjection, FeatureId)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, PointProjection, FeatureId)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = PointCompositeShapeProjWithFeatureBestFirstVisitor::new(&pipeline_shape, point, false); @@ -674,21 +593,16 @@ impl QueryPipeline { /// * `filter` - a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn cast_shape<'a, Colliders>( + pub fn cast_shape<'a>( &self, - colliders: &'a Colliders, + colliders: &'a ColliderSet, shape_pos: &Isometry, shape_vel: &Vector, shape: &dyn Shape, max_toi: Real, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, TOI)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, TOI)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let mut visitor = TOICompositeShapeShapeBestFirstVisitor::new( &*self.query_dispatcher, @@ -724,9 +638,9 @@ impl QueryPipeline { /// * `filter` - a more fine-grained filter. A collider is taken into account by this query if /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. - pub fn nonlinear_cast_shape( + pub fn nonlinear_cast_shape( &self, - colliders: &Colliders, + colliders: &ColliderSet, shape_motion: &NonlinearRigidMotion, shape: &dyn Shape, start_time: Real, @@ -734,12 +648,7 @@ impl QueryPipeline { stop_at_penetration: bool, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, - ) -> Option<(ColliderHandle, TOI)> - where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) -> Option<(ColliderHandle, TOI)> { let pipeline_shape = self.as_composite_shape(colliders, query_groups, filter); let pipeline_motion = NonlinearRigidMotion::identity(); let mut visitor = NonlinearTOICompositeShapeShapeBestFirstVisitor::new( @@ -768,19 +677,15 @@ impl QueryPipeline { /// its `contact_group` is compatible with the `query_groups`, and if this `filter` /// is either `None` or returns `true`. /// * `callback` - A function called with the handles of each collider intersecting the `shape`. - pub fn intersections_with_shape<'a, Colliders>( + pub fn intersections_with_shape<'a, ColliderSet>( &self, - colliders: &'a Colliders, + colliders: &'a ColliderSet, shape_pos: &Isometry, shape: &dyn Shape, query_groups: InteractionGroups, filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle) -> bool, - ) where - Colliders: ComponentSet - + ComponentSet - + ComponentSet, - { + ) { let dispatcher = &*self.query_dispatcher; let inv_shape_pos = shape_pos.inverse(); diff --git a/src/pipeline/user_changes.rs b/src/pipeline/user_changes.rs index 2c03f1c..b999f0f 100644 --- a/src/pipeline/user_changes.rs +++ b/src/pipeline/user_changes.rs @@ -1,28 +1,15 @@ -use crate::data::{BundleSet, ComponentSet, ComponentSetMut, ComponentSetOption}; use crate::dynamics::{ - IslandManager, RigidBodyActivation, RigidBodyChanges, RigidBodyColliders, RigidBodyHandle, - RigidBodyIds, RigidBodyMassProps, RigidBodyPosition, RigidBodyType, -}; -use crate::geometry::{ - ColliderChanges, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition, - ColliderShape, + IslandManager, RigidBodyActivation, RigidBodyChanges, RigidBodyHandle, RigidBodyIds, + RigidBodyPosition, RigidBodySet, RigidBodyType, }; +use crate::geometry::{ColliderChanges, ColliderHandle, ColliderPosition, ColliderSet}; use parry::utils::hashmap::HashMap; -pub(crate) fn handle_user_changes_to_colliders( - bodies: &mut Bodies, - colliders: &mut Colliders, +pub(crate) fn handle_user_changes_to_colliders( + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_colliders: &[ColliderHandle], -) where - Bodies: ComponentSet - + ComponentSet - + ComponentSetMut, - Colliders: ComponentSetMut - + ComponentSetMut - + ComponentSetOption - + ComponentSet - + ComponentSet, -{ +) { // TODO: avoid this hashmap? We could perhaps add a new flag to RigidBodyChanges to // indicated that the mass properties need to be recomputed? let mut mprops_to_update = HashMap::default(); @@ -30,25 +17,20 @@ pub(crate) fn handle_user_changes_to_colliders( for handle in modified_colliders { // NOTE: we use `get` because the collider may no longer // exist if it has been removed. - let co_changes: Option = colliders.get(handle.0).copied(); - - if let Some(co_changes) = co_changes { - if co_changes.contains(ColliderChanges::PARENT) { - let co_parent: Option<&ColliderParent> = colliders.get(handle.0); - - if let Some(co_parent) = co_parent { + if let Some(co) = colliders.get(*handle) { + if co.changes.contains(ColliderChanges::PARENT) { + if let Some(co_parent) = co.parent { let parent_pos: &RigidBodyPosition = bodies.index(co_parent.handle.0); let new_pos = parent_pos.position * co_parent.pos_wrt_parent; - let new_changes = co_changes | ColliderChanges::POSITION; + let new_changes = co.changes | ColliderChanges::POSITION; colliders.set_internal(handle.0, ColliderPosition(new_pos)); colliders.set_internal(handle.0, new_changes); } } - if co_changes.contains(ColliderChanges::SHAPE) { - let co_parent: Option<&ColliderParent> = colliders.get(handle.0); - if let Some(co_parent) = co_parent { + if co.changes.contains(ColliderChanges::SHAPE) { + if let Some(co_parent) = co.parent { mprops_to_update.insert(co_parent.handle, ()); } } @@ -56,11 +38,10 @@ pub(crate) fn handle_user_changes_to_colliders( } for (to_update, _) in mprops_to_update { - let (rb_pos, rb_colliders): (&RigidBodyPosition, &RigidBodyColliders) = - bodies.index_bundle(to_update.0); - let position = rb_pos.position; + let rb = &bodies[to_update]; + let position = rb.position(); // FIXME: remove the clone once we remove the ComponentSets. - let attached_colliders = rb_colliders.clone(); + let attached_colliders = rb.colliders().clone(); bodies.map_mut_internal(to_update.0, |rb_mprops| { rb_mprops.recompute_mass_properties_from_colliders( @@ -72,23 +53,13 @@ pub(crate) fn handle_user_changes_to_colliders( } } -pub(crate) fn handle_user_changes_to_rigid_bodies( +pub(crate) fn handle_user_changes_to_rigid_bodies( mut islands: Option<&mut IslandManager>, - bodies: &mut Bodies, - colliders: &mut Colliders, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, modified_bodies: &[RigidBodyHandle], modified_colliders: &mut Vec, -) where - Bodies: ComponentSetMut - + ComponentSet - + ComponentSetMut - + ComponentSetMut - + ComponentSet - + ComponentSet, - Colliders: ComponentSetMut - + ComponentSetMut - + ComponentSetOption, -{ +) { enum FinalAction { UpdateActiveKinematicSetId, UpdateActiveDynamicSetId, @@ -96,28 +67,23 @@ pub(crate) fn handle_user_changes_to_rigid_bodies( for handle in modified_bodies { let mut final_action = None; - let changes: Option<&RigidBodyChanges> = bodies.get(handle.0); - if changes.is_none() { + if !bodies.contains(*handle) { // The body no longer exists. continue; } - let mut changes = *changes.unwrap(); - let mut ids: RigidBodyIds = *bodies.index(handle.0); - let mut activation: RigidBodyActivation = *bodies.index(handle.0); - let (status, rb_colliders, poss): ( - &RigidBodyType, - &RigidBodyColliders, - &RigidBodyPosition, - ) = bodies.index_bundle(handle.0); + let rb = &bodies[handle]; + let mut changes = rb.changes; + let mut ids: RigidBodyIds = rb.ids; + let mut activation: RigidBodyActivation = rb.activation; { // The body's status changed. We need to make sure // it is on the correct active set. if let Some(islands) = islands.as_deref_mut() { if changes.contains(RigidBodyChanges::TYPE) { - match status { + match rb.status { RigidBodyType::Dynamic => { // Remove from the active kinematic set if it was there. if islands.active_kinematic_set.get(ids.active_set_id) == Some(handle) { @@ -161,9 +127,10 @@ pub(crate) fn handle_user_changes_to_rigid_bodies( if changes.contains(RigidBodyChanges::POSITION) || changes.contains(RigidBodyChanges::COLLIDERS) { - rb_colliders.update_positions(colliders, modified_colliders, &poss.position); + rb.colliders + .update_positions(colliders, modified_colliders, &rb.pos.position); - if status.is_kinematic() + if rb.is_kinematic() && islands.active_kinematic_set.get(ids.active_set_id) != Some(handle) { ids.active_set_id = islands.active_kinematic_set.len(); @@ -175,7 +142,7 @@ pub(crate) fn handle_user_changes_to_rigid_bodies( // sleeping and if it is not already inside of the active set. if changes.contains(RigidBodyChanges::SLEEP) && !activation.sleeping // May happen if the body was put to sleep manually. - && status.is_dynamic() // Only dynamic bodies are in the active dynamic set. + && rb.is_dynamic() // Only dynamic bodies are in the active dynamic set. && islands.active_dynamic_set.get(ids.active_set_id) != Some(handle) { ids.active_set_id = islands.active_dynamic_set.len(); // This will handle the case where the activation_channel contains duplicates. @@ -186,14 +153,15 @@ pub(crate) fn handle_user_changes_to_rigid_bodies( if changes.contains(RigidBodyChanges::POSITION) || changes.contains(RigidBodyChanges::COLLIDERS) { - rb_colliders.update_positions(colliders, modified_colliders, &poss.position); + rb.colliders + .update_positions(colliders, modified_colliders, &rb.pos.position); } } if changes.contains(RigidBodyChanges::DOMINANCE) || changes.contains(RigidBodyChanges::TYPE) { - for handle in rb_colliders.0.iter() { + for handle in rb.colliders.0.iter() { colliders.map_mut_internal(handle.0, |co_changes: &mut ColliderChanges| { if !co_changes.contains(ColliderChanges::MODIFIED) { modified_colliders.push(*handle); -- cgit