From f7354751a939cc58e419f3fba7f9d01a8c65835e Mon Sep 17 00:00:00 2001 From: Xuchen Han Date: Wed, 17 Jun 2020 18:43:49 -0700 Subject: [PATCH] improve contact stability for implicit scheme --- .../ConstraintSolver/btContactSolverInfo.h | 2 + src/BulletSoftBody/btConjugateGradient.h | 4 +- src/BulletSoftBody/btDeformableBodySolver.cpp | 19 ++++-- .../btDeformableContactConstraint.cpp | 2 +- .../btDeformableContactProjection.cpp | 58 +++++++++---------- 5 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index 6968a3310..3316403a8 100644 --- a/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -48,6 +48,7 @@ struct btContactSolverInfoData btScalar m_erp2; //error reduction for contact constraints btScalar m_deformable_erp; //error reduction for deformable constraints btScalar m_deformable_cfm; //constraint force mixing for deformable constraints + btScalar m_deformable_maxErrorReduction; // maxErrorReduction for deformable contact btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts btScalar m_frictionERP; //error reduction for friction constraints btScalar m_frictionCFM; //constraint force mixing for friction constraints @@ -86,6 +87,7 @@ struct btContactSolverInfo : public btContactSolverInfoData m_erp2 = btScalar(0.2); m_deformable_erp = btScalar(0.06); m_deformable_cfm = btScalar(0.01); + m_deformable_maxErrorReduction = btScalar(0.1); m_globalCfm = btScalar(0.); m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default m_frictionCFM = btScalar(0.); diff --git a/src/BulletSoftBody/btConjugateGradient.h b/src/BulletSoftBody/btConjugateGradient.h index df3f0fdea..635e53e68 100644 --- a/src/BulletSoftBody/btConjugateGradient.h +++ b/src/BulletSoftBody/btConjugateGradient.h @@ -49,7 +49,7 @@ public: A.precondition(r, z); A.project(z); btScalar r_dot_z = this->dot(z,r); - if (r_dot_z <= Base::m_tolerance*d0) { + if (r_dot_z <= Base::m_tolerance * d0) { if (verbose) { std::cout << "Iteration = 0" << std::endl; @@ -86,7 +86,7 @@ public: if (r_dot_z_new < Base::m_tolerance * d0) { if (verbose) { - std::cout << "ConjugateGradient iterations " << k << std::endl; + std::cout << "ConjugateGradient iterations " << k << " residual = " << r_dot_z_new << std::endl; } return k; } diff --git a/src/BulletSoftBody/btDeformableBodySolver.cpp b/src/BulletSoftBody/btDeformableBodySolver.cpp index 25c5d44ad..022539092 100644 --- a/src/BulletSoftBody/btDeformableBodySolver.cpp +++ b/src/BulletSoftBody/btDeformableBodySolver.cpp @@ -438,12 +438,19 @@ void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar d // apply drag n.m_v *= (1 - psb->m_cfg.drag); // scale velocity back - if (n.m_v.norm() > max_v) - { - n.m_v.safeNormalize(); - n.m_v *= max_v; - } - n.m_q = n.m_x + n.m_v * dt; + if (m_implicit) + { + n.m_q = n.m_x; + } + else + { + if (n.m_v.norm() > max_v) + { + n.m_v.safeNormalize(); + n.m_v *= max_v; + } + n.m_q = n.m_x + n.m_v * dt; + } n.m_splitv.setZero(); n.m_constrained = false; } diff --git a/src/BulletSoftBody/btDeformableContactConstraint.cpp b/src/BulletSoftBody/btDeformableContactConstraint.cpp index 907639bb2..a1aa50f4e 100644 --- a/src/BulletSoftBody/btDeformableContactConstraint.cpp +++ b/src/BulletSoftBody/btDeformableContactConstraint.cpp @@ -362,7 +362,7 @@ btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolv btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal) { - btScalar MAX_PENETRATION_CORRECTION = 0.1; + btScalar MAX_PENETRATION_CORRECTION = infoGlobal.m_deformable_maxErrorReduction; const btSoftBody::sCti& cti = m_contact->m_cti; btVector3 vb = getSplitVb(); btVector3 va = getSplitVa(); diff --git a/src/BulletSoftBody/btDeformableContactProjection.cpp b/src/BulletSoftBody/btDeformableContactProjection.cpp index 844af76cc..6921fb631 100644 --- a/src/BulletSoftBody/btDeformableContactProjection.cpp +++ b/src/BulletSoftBody/btDeformableContactProjection.cpp @@ -70,6 +70,12 @@ btScalar btDeformableContactProjection::solveSplitImpulse(btCollisionObject** de { continue; } + for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k) + { + btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k]; + btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal); + residualSquare = btMax(residualSquare, localResidualSquare); + } for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k) { btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k]; @@ -140,15 +146,6 @@ void btDeformableContactProjection::setConstraints(const btContactSolverInfo& in } btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting); m_faceRigidConstraints[i].push_back(constraint); - // btVector3 va = constraint.getVa(); - // btVector3 vb = constraint.getVb(); - // const btVector3 vr = vb - va; - // const btSoftBody::sCti& cti = contact.m_cti; - // const btScalar dn = btDot(vr, cti.m_normal); - // if (dn < SIMD_EPSILON) - // { - // m_faceRigidConstraints[i].push_back(constraint); - // } } } } @@ -255,33 +252,36 @@ void btDeformableContactProjection::setProjection() { int index = m_nodeRigidConstraints[i][j].m_node->index; m_nodeRigidConstraints[i][j].m_node->m_constrained = true; - if (m_nodeRigidConstraints[i][j].m_static) + if (m_nodeRigidConstraints[i][j].m_binding) { - if (m_projectionsDict.find(index) == NULL) + if (m_nodeRigidConstraints[i][j].m_static) { - m_projectionsDict.insert(index, units); - } - else - { - btAlignedObjectArray& projections = *m_projectionsDict[index]; - for (int k = 0; k < 3; ++k) + if (m_projectionsDict.find(index) == NULL) { - projections.push_back(units[k]); + m_projectionsDict.insert(index, units); + } + else + { + btAlignedObjectArray& projections = *m_projectionsDict[index]; + for (int k = 0; k < 3; ++k) + { + projections.push_back(units[k]); + } } } - } - else - { - if (m_projectionsDict.find(index) == NULL) - { - btAlignedObjectArray projections; - projections.push_back(m_nodeRigidConstraints[i][j].m_normal); - m_projectionsDict.insert(index, projections); - } else { - btAlignedObjectArray& projections = *m_projectionsDict[index]; - projections.push_back(m_nodeRigidConstraints[i][j].m_normal); + if (m_projectionsDict.find(index) == NULL) + { + btAlignedObjectArray projections; + projections.push_back(m_nodeRigidConstraints[i][j].m_normal); + m_projectionsDict.insert(index, projections); + } + else + { + btAlignedObjectArray& projections = *m_projectionsDict[index]; + projections.push_back(m_nodeRigidConstraints[i][j].m_normal); + } } } }