diff options
| author | Sébastien Crozet <developer@crozet.re> | 2021-05-01 10:17:23 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-01 10:17:23 +0200 |
| commit | a385efc5582c7918f11c01a2b6bf26a46919d3a0 (patch) | |
| tree | c5b9c5e6fcb5561421e2b4b9d99f28e4c83c745e /src/dynamics/solver/parallel_island_solver.rs | |
| parent | aaf80bfa872c6f29b248cab8eb5658ab0d73cb4a (diff) | |
| parent | 2dfbd9ae92c139e306afc87994adac82489f30eb (diff) | |
| download | rapier-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/dynamics/solver/parallel_island_solver.rs')
| -rw-r--r-- | src/dynamics/solver/parallel_island_solver.rs | 119 |
1 files changed, 80 insertions, 39 deletions
diff --git a/src/dynamics/solver/parallel_island_solver.rs b/src/dynamics/solver/parallel_island_solver.rs index add5f2c..9d565c1 100644 --- a/src/dynamics/solver/parallel_island_solver.rs +++ b/src/dynamics/solver/parallel_island_solver.rs @@ -1,9 +1,14 @@ use super::{DeltaVel, ParallelInteractionGroups, ParallelVelocitySolver}; +use crate::data::{BundleSet, ComponentSet, ComponentSetMut}; use crate::dynamics::solver::{ AnyJointPositionConstraint, AnyJointVelocityConstraint, AnyPositionConstraint, AnyVelocityConstraint, ParallelPositionSolver, ParallelSolverConstraints, }; -use crate::dynamics::{IntegrationParameters, JointGraphEdge, JointIndex, RigidBodySet}; +use crate::dynamics::{ + IntegrationParameters, IslandManager, JointGraphEdge, JointIndex, RigidBodyDamping, + RigidBodyForces, RigidBodyIds, RigidBodyMassProps, RigidBodyPosition, RigidBodyType, + RigidBodyVelocity, +}; use crate::geometry::{ContactManifold, ContactManifoldIndex}; use crate::math::{Isometry, Real}; use crate::utils::WAngularInertia; @@ -150,19 +155,22 @@ impl ParallelIslandSolver { } } - pub fn solve_position_constraints<'s>( + pub fn solve_position_constraints<'s, Bodies>( &'s mut self, scope: &Scope<'s>, island_id: usize, + islands: &'s IslandManager, params: &'s IntegrationParameters, - bodies: &'s mut RigidBodySet, - ) { + bodies: &'s mut Bodies, + ) where + Bodies: ComponentSetMut<RigidBodyPosition> + ComponentSet<RigidBodyIds>, + { let num_threads = rayon::current_num_threads(); let num_task_per_island = num_threads; // (num_threads / num_islands).max(1); // TODO: not sure this is the best value. Also, perhaps it is better to interleave tasks of each island? self.thread = ThreadContext::new(8); // TODO: could we compute some kind of optimal value here? self.positions.clear(); self.positions - .resize(bodies.active_island(island_id).len(), Isometry::identity()); + .resize(islands.active_island(island_id).len(), Isometry::identity()); for _ in 0..num_task_per_island { // We use AtomicPtr because it is Send+Sync while *mut is not. @@ -179,7 +187,7 @@ impl ParallelIslandSolver { // Transmute *mut -> &mut let positions: &mut Vec<Isometry<Real>> = unsafe { std::mem::transmute(positions.load(Ordering::Relaxed)) }; - let bodies: &mut RigidBodySet = + let bodies: &mut Bodies = unsafe { std::mem::transmute(bodies.load(Ordering::Relaxed)) }; let parallel_contact_constraints: &mut ParallelSolverConstraints<AnyVelocityConstraint, AnyPositionConstraint> = unsafe { std::mem::transmute(parallel_contact_constraints.load(Ordering::Relaxed)) @@ -191,15 +199,14 @@ impl ParallelIslandSolver { enable_flush_to_zero!(); // Ensure this is enabled on each thread. // Write results back to rigid bodies and integrate velocities. - let island_range = bodies.active_island_range(island_id); - let active_bodies = &bodies.active_dynamic_set[island_range]; - let bodies = &mut bodies.bodies; + let island_range = islands.active_island_range(island_id); + let active_bodies = &islands.active_dynamic_set[island_range]; concurrent_loop! { let batch_size = thread.batch_size; for handle in active_bodies[thread.body_integration_index, thread.num_integrated_bodies] { - let rb = &mut bodies[handle.0]; - positions[rb.active_set_offset] = rb.next_position; + let (rb_ids, rb_pos): (&RigidBodyIds, &RigidBodyPosition) = bodies.index_bundle(handle.0); + positions[rb_ids.active_set_offset] = rb_pos.next_position; } } @@ -217,40 +224,61 @@ impl ParallelIslandSolver { concurrent_loop! { let batch_size = thread.batch_size; for handle in active_bodies[thread.position_writeback_index] { - let rb = &mut bodies[handle.0]; - rb.set_next_position(positions[rb.active_set_offset]); + let rb_ids: RigidBodyIds = *bodies.index(handle.0); + bodies.map_mut_internal(handle.0, |rb_pos: &mut RigidBodyPosition| rb_pos.next_position = positions[rb_ids.active_set_offset]); } } }) } } - pub fn init_constraints_and_solve_velocity_constraints<'s>( + pub fn init_constraints_and_solve_velocity_constraints<'s, Bodies>( &'s mut self, scope: &Scope<'s>, island_id: usize, + islands: &'s IslandManager, params: &'s IntegrationParameters, - bodies: &'s mut RigidBodySet, + bodies: &'s mut Bodies, manifolds: &'s mut Vec<&'s mut ContactManifold>, manifold_indices: &'s [ContactManifoldIndex], joints: &'s mut Vec<JointGraphEdge>, joint_indices: &[JointIndex], - ) { + ) where + Bodies: ComponentSet<RigidBodyForces> + + ComponentSetMut<RigidBodyPosition> + + ComponentSetMut<RigidBodyVelocity> + + ComponentSet<RigidBodyMassProps> + + ComponentSet<RigidBodyDamping> + + ComponentSet<RigidBodyIds> + + ComponentSet<RigidBodyType>, + { let num_threads = rayon::current_num_threads(); let num_task_per_island = num_threads; // (num_threads / num_islands).max(1); // TODO: not sure this is the best value. Also, perhaps it is better to interleave tasks of each island? self.thread = ThreadContext::new(8); // TODO: could we compute some kind of optimal value here? - self.parallel_groups - .group_interactions(island_id, bodies, manifolds, manifold_indices); - self.parallel_joint_groups - .group_interactions(island_id, bodies, joints, joint_indices); + self.parallel_groups.group_interactions( + island_id, + islands, + bodies, + manifolds, + manifold_indices, + ); + self.parallel_joint_groups.group_interactions( + island_id, + islands, + bodies, + joints, + joint_indices, + ); self.parallel_contact_constraints.init_constraint_groups( island_id, + islands, bodies, manifolds, &self.parallel_groups, ); self.parallel_joint_constraints.init_constraint_groups( island_id, + islands, bodies, joints, &self.parallel_joint_groups, @@ -258,10 +286,10 @@ impl ParallelIslandSolver { self.mj_lambdas.clear(); self.mj_lambdas - .resize(bodies.active_island(island_id).len(), DeltaVel::zero()); + .resize(islands.active_island(island_id).len(), DeltaVel::zero()); self.positions.clear(); self.positions - .resize(bodies.active_island(island_id).len(), Isometry::identity()); + .resize(islands.active_island(island_id).len(), Isometry::identity()); for _ in 0..num_task_per_island { // We use AtomicPtr because it is Send+Sync while *mut is not. @@ -280,7 +308,7 @@ impl ParallelIslandSolver { // Transmute *mut -> &mut let mj_lambdas: &mut Vec<DeltaVel<Real>> = unsafe { std::mem::transmute(mj_lambdas.load(Ordering::Relaxed)) }; - 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)) }; @@ -297,20 +325,19 @@ impl ParallelIslandSolver { // Initialize `mj_lambdas` (per-body velocity deltas) with external accelerations (gravity etc): { - let island_range = bodies.active_island_range(island_id); - let active_bodies = &bodies.active_dynamic_set[island_range]; - let bodies = &mut bodies.bodies; + let island_range = islands.active_island_range(island_id); + let active_bodies = &islands.active_dynamic_set[island_range]; concurrent_loop! { let batch_size = thread.batch_size; for handle in active_bodies[thread.body_force_integration_index, thread.num_force_integrated_bodies] { - let rb = &mut bodies[handle.0]; - let dvel = &mut mj_lambdas[rb.active_set_offset]; + let (rb_ids, rb_forces, rb_mass_props): (&RigidBodyIds, &RigidBodyForces, &RigidBodyMassProps) = bodies.index_bundle(handle.0); + let dvel = &mut mj_lambdas[rb_ids.active_set_offset]; // NOTE: `dvel.angular` is actually storing angular velocity delta multiplied // by the square root of the inertia tensor: - dvel.angular += rb.effective_world_inv_inertia_sqrt * rb.torque * params.dt; - dvel.linear += rb.force * (rb.effective_inv_mass * params.dt); + dvel.angular += rb_mass_props.effective_world_inv_inertia_sqrt * rb_forces.torque * params.dt; + dvel.linear += rb_forces.force * (rb_mass_props.effective_inv_mass * params.dt); } } @@ -342,19 +369,33 @@ impl ParallelIslandSolver { ); // Write results back to rigid bodies and integrate velocities. - let island_range = bodies.active_island_range(island_id); - let active_bodies = &bodies.active_dynamic_set[island_range]; - let bodies = &mut bodies.bodies; + let island_range = islands.active_island_range(island_id); + let active_bodies = &islands.active_dynamic_set[island_range]; concurrent_loop! { let batch_size = thread.batch_size; for handle in active_bodies[thread.body_integration_index, thread.num_integrated_bodies] { - let rb = &mut bodies[handle.0]; - let dvel = mj_lambdas[rb.active_set_offset]; - rb.linvel += dvel.linear; - rb.angvel += rb.effective_world_inv_inertia_sqrt.transform_vector(dvel.angular); - rb.apply_damping(params.dt); - rb.integrate_next_position(params.dt); + let (rb_ids, rb_pos, rb_vels, rb_damping, rb_mprops): ( + &RigidBodyIds, + &RigidBodyPosition, + &RigidBodyVelocity, + &RigidBodyDamping, + &RigidBodyMassProps, + ) = bodies.index_bundle(handle.0); + + let mut new_rb_pos = *rb_pos; + let mut new_rb_vels = *rb_vels; + + let dvels = mj_lambdas[rb_ids.active_set_offset]; + new_rb_vels.linvel += dvels.linear; + new_rb_vels.angvel += rb_mprops.effective_world_inv_inertia_sqrt.transform_vector(dvels.angular); + + let new_rb_vels = new_rb_vels.apply_damping(params.dt, rb_damping); + new_rb_pos.next_position = + new_rb_vels.integrate(params.dt, &rb_pos.position, &rb_mprops.mass_properties.local_com); + + bodies.set_internal(handle.0, new_rb_vels); + bodies.set_internal(handle.0, new_rb_pos); } } }) |
