Attenuate the warmstart impulse for CCD contacts.
CCD contacts result in very strong, instantaneous, impulses. So it is preferable to attenuate their contribution to subsequent timesteps to avoid overshooting.
This commit is contained in:
@@ -10,6 +10,7 @@ use crate::math::{
|
||||
#[cfg(feature = "dim2")]
|
||||
use crate::utils::WBasis;
|
||||
use crate::utils::{WAngularInertia, WCross, WDot};
|
||||
use na::SimdComplexField;
|
||||
use num::Zero;
|
||||
use simba::simd::{SimdPartialOrd, SimdValue};
|
||||
|
||||
@@ -77,6 +78,7 @@ impl WVelocityGroundConstraint {
|
||||
let warmstart_multiplier =
|
||||
SimdReal::from(array![|ii| manifolds[ii].data.warmstart_multiplier; SIMD_WIDTH]);
|
||||
let warmstart_coeff = warmstart_multiplier * SimdReal::splat(params.warmstart_coeff);
|
||||
let warmstart_correction_slope = SimdReal::splat(params.warmstart_correction_slope);
|
||||
let num_active_contacts = manifolds[0].data.num_active_contacts();
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
@@ -118,13 +120,17 @@ impl WVelocityGroundConstraint {
|
||||
let tangent_velocity =
|
||||
Vector::from(array![|ii| manifold_points[ii][k].tangent_velocity; SIMD_WIDTH]);
|
||||
|
||||
let impulse =
|
||||
SimdReal::from(array![|ii| manifold_points[ii][k].data.impulse; SIMD_WIDTH]);
|
||||
let impulse = SimdReal::from(
|
||||
array![|ii| manifold_points[ii][k].warmstart_impulse; SIMD_WIDTH],
|
||||
);
|
||||
let prev_rhs =
|
||||
SimdReal::from(array![|ii| manifold_points[ii][k].prev_rhs; SIMD_WIDTH]);
|
||||
let dp1 = point - world_com1;
|
||||
let dp2 = point - world_com2;
|
||||
|
||||
let vel1 = linvel1 + angvel1.gcross(dp1);
|
||||
let vel2 = linvel2 + angvel2.gcross(dp2);
|
||||
let warmstart_correction;
|
||||
|
||||
constraint.limit = friction;
|
||||
constraint.manifold_contact_id[k] =
|
||||
@@ -142,11 +148,14 @@ impl WVelocityGroundConstraint {
|
||||
rhs *= is_bouncy + is_resting * velocity_solve_fraction;
|
||||
rhs +=
|
||||
dist.simd_min(SimdReal::zero()) * (velocity_based_erp_inv_dt * is_resting);
|
||||
warmstart_correction = (warmstart_correction_slope
|
||||
/ (rhs - prev_rhs).simd_abs())
|
||||
.simd_min(warmstart_coeff);
|
||||
|
||||
constraint.elements[k].normal_part = VelocityGroundConstraintNormalPart {
|
||||
gcross2,
|
||||
rhs,
|
||||
impulse: impulse * warmstart_coeff,
|
||||
impulse: impulse * warmstart_correction,
|
||||
r,
|
||||
};
|
||||
}
|
||||
@@ -154,13 +163,14 @@ impl WVelocityGroundConstraint {
|
||||
// tangent parts.
|
||||
#[cfg(feature = "dim2")]
|
||||
let impulse = [SimdReal::from(
|
||||
array![|ii| manifold_points[ii][k].data.tangent_impulse; SIMD_WIDTH],
|
||||
)];
|
||||
array![|ii| manifold_points[ii][k].warmstart_tangent_impulse; SIMD_WIDTH],
|
||||
) * warmstart_correction];
|
||||
#[cfg(feature = "dim3")]
|
||||
let impulse = tangent_rot1
|
||||
* na::Vector2::from(
|
||||
array![|ii| manifold_points[ii][k].data.tangent_impulse; SIMD_WIDTH],
|
||||
);
|
||||
array![|ii| manifold_points[ii][k].warmstart_tangent_impulse; SIMD_WIDTH],
|
||||
)
|
||||
* warmstart_correction;
|
||||
constraint.elements[k].tangent_part.impulse = impulse;
|
||||
|
||||
for j in 0..DIM - 1 {
|
||||
@@ -237,6 +247,7 @@ impl WVelocityGroundConstraint {
|
||||
// FIXME: duplicated code. This is exactly the same as in the non-ground velocity constraint.
|
||||
pub fn writeback_impulses(&self, manifolds_all: &mut [&mut ContactManifold]) {
|
||||
for k in 0..self.num_contacts as usize {
|
||||
let rhs: [_; SIMD_WIDTH] = self.elements[k].normal_part.rhs.into();
|
||||
let impulses: [_; SIMD_WIDTH] = self.elements[k].normal_part.impulse.into();
|
||||
#[cfg(feature = "dim2")]
|
||||
let tangent_impulses: [_; SIMD_WIDTH] = self.elements[k].tangent_part.impulse[0].into();
|
||||
@@ -249,6 +260,7 @@ impl WVelocityGroundConstraint {
|
||||
let manifold = &mut manifolds_all[self.manifold_id[ii]];
|
||||
let contact_id = self.manifold_contact_id[k][ii];
|
||||
let active_contact = &mut manifold.points[contact_id as usize];
|
||||
active_contact.data.rhs = rhs[ii];
|
||||
active_contact.data.impulse = impulses[ii];
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
|
||||
Reference in New Issue
Block a user