aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/solver/parallel_island_solver.rs
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/dynamics/solver/parallel_island_solver.rs
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/dynamics/solver/parallel_island_solver.rs')
-rw-r--r--src/dynamics/solver/parallel_island_solver.rs119
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);
}
}
})