Apply accelerations during velocity solver
Closes https://github.com/dimforge/rapier/issues/97 Instead of applying accelerations from gravity and external forces as a separate step, this PR switches to applying them in the velocity solver.
This commit is contained in:
@@ -135,16 +135,20 @@ impl RigidBody {
|
|||||||
self.active_set_timestamp = 0;
|
self.active_set_timestamp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn integrate_accelerations(&mut self, dt: Real, gravity: Vector<Real>) {
|
pub(crate) fn add_gravity(&mut self, gravity: Vector<Real>) {
|
||||||
if self.effective_inv_mass != 0.0 {
|
if self.effective_inv_mass != 0.0 {
|
||||||
let acceleration = self.force * self.effective_inv_mass;
|
self.force += gravity * self.gravity_scale * self.mass();
|
||||||
self.linvel += (gravity * self.gravity_scale + acceleration) * dt;
|
}
|
||||||
self.force = na::zero();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let angular_acceleration = self.effective_world_inv_inertia_sqrt
|
pub(crate) fn integrate_accelerations(&mut self, dt: Real) {
|
||||||
|
let linear_acc = self.force * self.effective_inv_mass;
|
||||||
|
let angular_acc = self.effective_world_inv_inertia_sqrt
|
||||||
* (self.effective_world_inv_inertia_sqrt * self.torque);
|
* (self.effective_world_inv_inertia_sqrt * self.torque);
|
||||||
self.angvel += angular_acceleration * dt;
|
|
||||||
|
self.linvel += linear_acc * dt;
|
||||||
|
self.angvel += angular_acc * dt;
|
||||||
|
self.force = na::zero();
|
||||||
self.torque = na::zero();
|
self.torque = na::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ impl IslandSolver {
|
|||||||
joints: &mut [JointGraphEdge],
|
joints: &mut [JointGraphEdge],
|
||||||
joint_indices: &[JointIndex],
|
joint_indices: &[JointIndex],
|
||||||
) {
|
) {
|
||||||
if manifold_indices.len() != 0 || joint_indices.len() != 0 {
|
let has_constraints = manifold_indices.len() != 0 || joint_indices.len() != 0;
|
||||||
|
|
||||||
|
if has_constraints {
|
||||||
counters.solver.velocity_assembly_time.resume();
|
counters.solver.velocity_assembly_time.resume();
|
||||||
self.contact_constraints
|
self.contact_constraints
|
||||||
.init(island_id, params, bodies, manifolds, manifold_indices);
|
.init(island_id, params, bodies, manifolds, manifold_indices);
|
||||||
@@ -54,13 +56,13 @@ impl IslandSolver {
|
|||||||
&mut self.joint_constraints.velocity_constraints,
|
&mut self.joint_constraints.velocity_constraints,
|
||||||
);
|
);
|
||||||
counters.solver.velocity_resolution_time.pause();
|
counters.solver.velocity_resolution_time.pause();
|
||||||
}
|
|
||||||
|
|
||||||
counters.solver.velocity_update_time.resume();
|
counters.solver.velocity_update_time.resume();
|
||||||
bodies.foreach_active_island_body_mut_internal(island_id, |_, rb| rb.integrate(params.dt));
|
bodies.foreach_active_island_body_mut_internal(island_id, |_, rb| {
|
||||||
|
rb.integrate(params.dt)
|
||||||
|
});
|
||||||
counters.solver.velocity_update_time.pause();
|
counters.solver.velocity_update_time.pause();
|
||||||
|
|
||||||
if manifold_indices.len() != 0 || joint_indices.len() != 0 {
|
|
||||||
counters.solver.position_resolution_time.resume();
|
counters.solver.position_resolution_time.resume();
|
||||||
self.position_solver.solve(
|
self.position_solver.solve(
|
||||||
island_id,
|
island_id,
|
||||||
@@ -70,6 +72,14 @@ impl IslandSolver {
|
|||||||
&self.joint_constraints.position_constraints,
|
&self.joint_constraints.position_constraints,
|
||||||
);
|
);
|
||||||
counters.solver.position_resolution_time.pause();
|
counters.solver.position_resolution_time.pause();
|
||||||
|
} else {
|
||||||
|
counters.solver.velocity_update_time.resume();
|
||||||
|
bodies.foreach_active_island_body_mut_internal(island_id, |_, rb| {
|
||||||
|
// Since we didn't run the velocity solver we need to integrate the accelerations here
|
||||||
|
rb.integrate_accelerations(params.dt);
|
||||||
|
rb.integrate(params.dt);
|
||||||
|
});
|
||||||
|
counters.solver.velocity_update_time.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,31 @@ impl ParallelIslandSolver {
|
|||||||
self.positions
|
self.positions
|
||||||
.resize(bodies.active_island(island_id).len(), Isometry::identity());
|
.resize(bodies.active_island(island_id).len(), Isometry::identity());
|
||||||
|
|
||||||
|
{
|
||||||
|
// 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 thread = &self.thread;
|
||||||
|
|
||||||
|
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 = &mut self.mj_lambdas[rb.active_set_offset];
|
||||||
|
|
||||||
|
dvel.linear += rb.force * (rb.effective_inv_mass * params.dt);
|
||||||
|
rb.force = na::zero();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
rb.torque = na::zero();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0..num_task_per_island {
|
for _ in 0..num_task_per_island {
|
||||||
// We use AtomicPtr because it is Send+Sync while *mut is not.
|
// We use AtomicPtr because it is Send+Sync while *mut is not.
|
||||||
// See https://internals.rust-lang.org/t/shouldnt-pointers-be-send-sync-or/8818
|
// See https://internals.rust-lang.org/t/shouldnt-pointers-be-send-sync-or/8818
|
||||||
|
|||||||
@@ -32,6 +32,18 @@ impl VelocitySolver {
|
|||||||
self.mj_lambdas
|
self.mj_lambdas
|
||||||
.resize(bodies.active_island(island_id).len(), DeltaVel::zero());
|
.resize(bodies.active_island(island_id).len(), DeltaVel::zero());
|
||||||
|
|
||||||
|
// Initialize delta-velocities (`mj_lambdas`) with external forces (gravity etc):
|
||||||
|
bodies.foreach_active_island_body_mut_internal(island_id, |_, rb| {
|
||||||
|
let dvel = &mut self.mj_lambdas[rb.active_set_offset];
|
||||||
|
|
||||||
|
dvel.linear += rb.force * (rb.effective_inv_mass * params.dt);
|
||||||
|
rb.force = na::zero();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
rb.torque = na::zero();
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Warmstart constraints.
|
* Warmstart constraints.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ impl PhysicsPipeline {
|
|||||||
self.counters.stages.update_time.start();
|
self.counters.stages.update_time.start();
|
||||||
bodies.foreach_active_dynamic_body_mut_internal(|_, b| {
|
bodies.foreach_active_dynamic_body_mut_internal(|_, b| {
|
||||||
b.update_world_mass_properties();
|
b.update_world_mass_properties();
|
||||||
b.integrate_accelerations(integration_parameters.dt, *gravity)
|
b.add_gravity(*gravity)
|
||||||
});
|
});
|
||||||
self.counters.stages.update_time.pause();
|
self.counters.stages.update_time.pause();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user