aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/solver/contact_constraint/two_body_constraint.rs
diff options
context:
space:
mode:
authorSébastien Crozet <sebcrozet@dimforge.com>2024-04-14 15:53:35 +0200
committerSébastien Crozet <sebastien@crozet.re>2024-04-30 23:10:46 +0200
commit3ddf2441ea6c43aa98718e0ce8650c3b804062d4 (patch)
treecb788bf95da707a683fd949d887d071c68934ae6 /src/dynamics/solver/contact_constraint/two_body_constraint.rs
parent15c07cfeb3d59f116b26eec32e4590dc45d6c26c (diff)
downloadrapier-3ddf2441ea6c43aa98718e0ce8650c3b804062d4.tar.gz
rapier-3ddf2441ea6c43aa98718e0ce8650c3b804062d4.tar.bz2
rapier-3ddf2441ea6c43aa98718e0ce8650c3b804062d4.zip
feat: add exact mlcp solver for pais of 2 constraints
Diffstat (limited to 'src/dynamics/solver/contact_constraint/two_body_constraint.rs')
-rw-r--r--src/dynamics/solver/contact_constraint/two_body_constraint.rs47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/dynamics/solver/contact_constraint/two_body_constraint.rs b/src/dynamics/solver/contact_constraint/two_body_constraint.rs
index 8abf5c5..24a5730 100644
--- a/src/dynamics/solver/contact_constraint/two_body_constraint.rs
+++ b/src/dynamics/solver/contact_constraint/two_body_constraint.rs
@@ -2,11 +2,13 @@ use super::{ContactConstraintTypes, ContactPointInfos};
use crate::dynamics::solver::SolverVel;
use crate::dynamics::solver::{AnyConstraintMut, SolverBody};
+use crate::dynamics::integration_parameters::BLOCK_SOLVER_ENABLED;
use crate::dynamics::{IntegrationParameters, MultibodyJointSet, RigidBodySet};
use crate::geometry::{ContactManifold, ContactManifoldIndex};
use crate::math::{Isometry, Real, Vector, DIM, MAX_MANIFOLD_POINTS};
use crate::utils::{self, SimdAngularInertia, SimdBasis, SimdCross, SimdDot};
-use na::DVector;
+use na::{DVector, Matrix2};
+use num::Pow;
use super::{TwoBodyConstraintElement, TwoBodyConstraintNormalPart};
@@ -225,6 +227,7 @@ impl TwoBodyConstraintBuilder {
impulse: na::zero(),
impulse_accumulator: na::zero(),
r: projected_mass,
+ r_mat_elts: [0.0; 2],
};
}
@@ -284,6 +287,48 @@ impl TwoBodyConstraintBuilder {
builder.infos[k] = infos;
constraint.manifold_contact_id[k] = manifold_point.contact_id;
}
+
+ if BLOCK_SOLVER_ENABLED {
+ // Coupling between consecutive pairs.
+ for k in 0..manifold_points.len() / 2 {
+ let k0 = k * 2;
+ let k1 = k * 2 + 1;
+
+ let mut r_mat = Matrix2::zeros();
+ let imsum = mprops1.effective_inv_mass + mprops2.effective_inv_mass;
+ let r0 = constraint.elements[k0].normal_part.r;
+ let r1 = constraint.elements[k1].normal_part.r;
+ r_mat.m12 = force_dir1.dot(&imsum.component_mul(&force_dir1))
+ + constraint.elements[k0]
+ .normal_part
+ .gcross1
+ .gdot(constraint.elements[k1].normal_part.gcross1)
+ + constraint.elements[k0]
+ .normal_part
+ .gcross2
+ .gdot(constraint.elements[k1].normal_part.gcross2);
+ r_mat.m21 = r_mat.m12;
+ r_mat.m11 = utils::inv(r0);
+ r_mat.m22 = utils::inv(r1);
+
+ if let Some(inv) = r_mat.try_inverse() {
+ constraint.elements[k0].normal_part.r_mat_elts = [inv.m11, inv.m22];
+ constraint.elements[k1].normal_part.r_mat_elts = [inv.m12, r_mat.m12];
+ } else {
+ // If inversion failed, the contacts are redundant.
+ // Ignore the one with the smallest depth (it is too late to
+ // have the constraint removed from the constraint set, so just
+ // set the mass (r) matrix elements to 0.
+ constraint.elements[k0].normal_part.r_mat_elts =
+ if manifold_points[k0].dist <= manifold_points[k1].dist {
+ [r0, 0.0]
+ } else {
+ [0.0, r1]
+ };
+ constraint.elements[k1].normal_part.r_mat_elts = [0.0; 2];
+ }
+ }
+ }
}
}