2 Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
4 Bullet Continuous Collision Detection and Physics Library
5 Copyright (c) 2019 Google Inc. http://bulletphysics.org
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it freely,
10 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #include "btDeformableContactConstraint.h"
17 /* ================ Deformable Node Anchor =================== */
18 btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a, const btContactSolverInfo& infoGlobal)
19 : m_anchor(&a), btDeformableContactConstraint(a.m_cti.m_normal, infoGlobal)
23 btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other)
24 : m_anchor(other.m_anchor), btDeformableContactConstraint(other)
28 btVector3 btDeformableNodeAnchorConstraint::getVa() const
30 const btSoftBody::sCti& cti = m_anchor->m_cti;
31 btVector3 va(0, 0, 0);
32 if (cti.m_colObj->hasContactResponse())
34 btRigidBody* rigidCol = 0;
35 btMultiBodyLinkCollider* multibodyLinkCol = 0;
37 // grab the velocity of the rigid body
38 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
40 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
41 va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_anchor->m_c1)) : btVector3(0, 0, 0);
43 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
45 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
48 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
49 const btScalar* J_n = &m_anchor->jacobianData_normal.m_jacobians[0];
50 const btScalar* J_t1 = &m_anchor->jacobianData_t1.m_jacobians[0];
51 const btScalar* J_t2 = &m_anchor->jacobianData_t2.m_jacobians[0];
52 const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
53 const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
54 // add in the normal component of the va
56 for (int k = 0; k < ndof; ++k)
58 vel += (local_v[k] + local_dv[k]) * J_n[k];
60 va = cti.m_normal * vel;
61 // add in the tangential components of the va
63 for (int k = 0; k < ndof; ++k)
65 vel += (local_v[k] + local_dv[k]) * J_t1[k];
67 va += m_anchor->t1 * vel;
69 for (int k = 0; k < ndof; ++k)
71 vel += (local_v[k] + local_dv[k]) * J_t2[k];
73 va += m_anchor->t2 * vel;
80 btScalar btDeformableNodeAnchorConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
82 const btSoftBody::sCti& cti = m_anchor->m_cti;
83 btVector3 va = getVa();
84 btVector3 vb = getVb();
85 btVector3 vr = (vb - va);
86 // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
87 const btScalar dn = btDot(vr, vr);
88 // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
89 btScalar residualSquare = dn * dn;
90 btVector3 impulse = m_anchor->m_c0 * vr;
91 // apply impulse to deformable nodes involved and change their velocities
92 applyImpulse(impulse);
94 // apply impulse to the rigid/multibodies involved and change their velocities
95 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
97 btRigidBody* rigidCol = 0;
98 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
101 rigidCol->applyImpulse(impulse, m_anchor->m_c1);
104 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
106 btMultiBodyLinkCollider* multibodyLinkCol = 0;
107 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
108 if (multibodyLinkCol)
110 const btScalar* deltaV_normal = &m_anchor->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
111 // apply normal component of the impulse
112 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
113 // apply tangential component of the impulse
114 const btScalar* deltaV_t1 = &m_anchor->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
115 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_anchor->t1));
116 const btScalar* deltaV_t2 = &m_anchor->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
117 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_anchor->t2));
120 return residualSquare;
123 btVector3 btDeformableNodeAnchorConstraint::getVb() const
125 return m_anchor->m_node->m_v;
128 void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
130 btVector3 dv = impulse * m_anchor->m_c2;
131 m_anchor->m_node->m_v -= dv;
134 /* ================ Deformable vs. Rigid =================== */
135 btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal)
136 : m_contact(&c), btDeformableContactConstraint(c.m_cti.m_normal, infoGlobal)
138 m_total_normal_dv.setZero();
139 m_total_tangent_dv.setZero();
140 // The magnitude of penetration is the depth of penetration.
141 m_penetration = c.m_cti.m_offset;
142 m_total_split_impulse = 0;
146 btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
147 : m_contact(other.m_contact), btDeformableContactConstraint(other), m_penetration(other.m_penetration), m_total_split_impulse(other.m_total_split_impulse), m_binding(other.m_binding)
149 m_total_normal_dv = other.m_total_normal_dv;
150 m_total_tangent_dv = other.m_total_tangent_dv;
153 btVector3 btDeformableRigidContactConstraint::getVa() const
155 const btSoftBody::sCti& cti = m_contact->m_cti;
156 btVector3 va(0, 0, 0);
157 if (cti.m_colObj->hasContactResponse())
159 btRigidBody* rigidCol = 0;
160 btMultiBodyLinkCollider* multibodyLinkCol = 0;
162 // grab the velocity of the rigid body
163 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
165 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
166 va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
168 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
170 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
171 if (multibodyLinkCol)
173 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
174 const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
175 const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
176 const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
177 const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
178 const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
179 // add in the normal component of the va
181 for (int k = 0; k < ndof; ++k)
183 vel += (local_v[k] + local_dv[k]) * J_n[k];
185 va = cti.m_normal * vel;
186 // add in the tangential components of the va
188 for (int k = 0; k < ndof; ++k)
190 vel += (local_v[k] + local_dv[k]) * J_t1[k];
192 va += m_contact->t1 * vel;
194 for (int k = 0; k < ndof; ++k)
196 vel += (local_v[k] + local_dv[k]) * J_t2[k];
198 va += m_contact->t2 * vel;
205 btVector3 btDeformableRigidContactConstraint::getSplitVa() const
207 const btSoftBody::sCti& cti = m_contact->m_cti;
208 btVector3 va(0, 0, 0);
209 if (cti.m_colObj->hasContactResponse())
211 btRigidBody* rigidCol = 0;
212 btMultiBodyLinkCollider* multibodyLinkCol = 0;
214 // grab the velocity of the rigid body
215 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
217 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
218 va = rigidCol ? (rigidCol->getPushVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
220 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
222 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
223 if (multibodyLinkCol)
225 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
226 const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
227 const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
228 const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
229 const btScalar* local_split_v = multibodyLinkCol->m_multiBody->getSplitVelocityVector();
230 // add in the normal component of the va
232 for (int k = 0; k < ndof; ++k)
234 vel += local_split_v[k] * J_n[k];
236 va = cti.m_normal * vel;
237 // add in the tangential components of the va
239 for (int k = 0; k < ndof; ++k)
241 vel += local_split_v[k] * J_t1[k];
243 va += m_contact->t1 * vel;
245 for (int k = 0; k < ndof; ++k)
247 vel += local_split_v[k] * J_t2[k];
249 va += m_contact->t2 * vel;
256 btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
258 const btSoftBody::sCti& cti = m_contact->m_cti;
259 btVector3 va = getVa();
260 btVector3 vb = getVb();
261 btVector3 vr = vb - va;
262 btScalar dn = btDot(vr, cti.m_normal) + m_total_normal_dv.dot(cti.m_normal) * infoGlobal.m_deformable_cfm;
263 if (m_penetration > 0)
265 dn += m_penetration / infoGlobal.m_timeStep;
267 if (!infoGlobal.m_splitImpulse)
269 dn += m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
271 // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
272 btVector3 impulse = m_contact->m_c0 * (vr + m_total_normal_dv * infoGlobal.m_deformable_cfm + ((m_penetration > 0) ? m_penetration / infoGlobal.m_timeStep * cti.m_normal : btVector3(0, 0, 0)));
273 if (!infoGlobal.m_splitImpulse)
275 impulse += m_contact->m_c0 * (m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep * cti.m_normal);
277 btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
278 btVector3 impulse_tangent = impulse - impulse_normal;
284 btScalar residualSquare = dn * dn;
285 btVector3 old_total_tangent_dv = m_total_tangent_dv;
286 // m_c5 is the inverse mass of the deformable node/face
287 m_total_normal_dv -= m_contact->m_c5 * impulse_normal;
288 m_total_tangent_dv -= m_contact->m_c5 * impulse_tangent;
290 if (m_total_normal_dv.dot(cti.m_normal) < 0)
292 // separating in the normal direction
295 impulse_tangent.setZero();
299 if (m_total_normal_dv.norm() * m_contact->m_c3 < m_total_tangent_dv.norm())
302 // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
304 if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
306 m_total_tangent_dv = btVector3(0, 0, 0);
310 m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_c3;
312 // impulse_tangent = -btScalar(1)/m_contact->m_c2 * (m_total_tangent_dv - old_total_tangent_dv);
313 impulse_tangent = m_contact->m_c5.inverse() * (old_total_tangent_dv - m_total_tangent_dv);
321 impulse = impulse_normal + impulse_tangent;
322 // apply impulse to deformable nodes involved and change their velocities
323 applyImpulse(impulse);
324 // apply impulse to the rigid/multibodies involved and change their velocities
325 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
327 btRigidBody* rigidCol = 0;
328 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
331 rigidCol->applyImpulse(impulse, m_contact->m_c1);
334 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
336 btMultiBodyLinkCollider* multibodyLinkCol = 0;
337 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
338 if (multibodyLinkCol)
340 const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
341 // apply normal component of the impulse
342 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
343 if (impulse_tangent.norm() > SIMD_EPSILON)
345 // apply tangential component of the impulse
346 const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
347 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_contact->t1));
348 const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
349 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_contact->t2));
353 return residualSquare;
356 btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
358 btScalar MAX_PENETRATION_CORRECTION = infoGlobal.m_deformable_maxErrorReduction;
359 const btSoftBody::sCti& cti = m_contact->m_cti;
360 btVector3 vb = getSplitVb();
361 btVector3 va = getSplitVa();
362 btScalar p = m_penetration;
367 btVector3 vr = vb - va;
368 btScalar dn = btDot(vr, cti.m_normal) + p * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
373 if (m_total_split_impulse + dn > MAX_PENETRATION_CORRECTION)
375 dn = MAX_PENETRATION_CORRECTION - m_total_split_impulse;
377 if (m_total_split_impulse + dn < -MAX_PENETRATION_CORRECTION)
379 dn = -MAX_PENETRATION_CORRECTION - m_total_split_impulse;
381 m_total_split_impulse += dn;
383 btScalar residualSquare = dn * dn;
384 const btVector3 impulse = m_contact->m_c0 * (cti.m_normal * dn);
385 applySplitImpulse(impulse);
387 // apply split impulse to the rigid/multibodies involved and change their velocities
388 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
390 btRigidBody* rigidCol = 0;
391 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
394 rigidCol->applyPushImpulse(impulse, m_contact->m_c1);
397 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
399 btMultiBodyLinkCollider* multibodyLinkCol = 0;
400 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
401 if (multibodyLinkCol)
403 const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
404 // apply normal component of the impulse
405 multibodyLinkCol->m_multiBody->applyDeltaSplitVeeMultiDof(deltaV_normal, impulse.dot(cti.m_normal));
408 return residualSquare;
410 /* ================ Node vs. Rigid =================== */
411 btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal)
412 : m_node(contact.m_node), btDeformableRigidContactConstraint(contact, infoGlobal)
416 btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other)
417 : m_node(other.m_node), btDeformableRigidContactConstraint(other)
421 btVector3 btDeformableNodeRigidContactConstraint::getVb() const
426 btVector3 btDeformableNodeRigidContactConstraint::getSplitVb() const
428 return m_node->m_splitv;
431 btVector3 btDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
433 return m_total_normal_dv + m_total_tangent_dv;
436 void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
438 const btSoftBody::DeformableNodeRigidContact* contact = getContact();
439 btVector3 dv = contact->m_c5 * impulse;
440 contact->m_node->m_v -= dv;
443 void btDeformableNodeRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
445 const btSoftBody::DeformableNodeRigidContact* contact = getContact();
446 btVector3 dv = contact->m_c5 * impulse;
447 contact->m_node->m_splitv -= dv;
450 /* ================ Face vs. Rigid =================== */
451 btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting)
452 : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btDeformableRigidContactConstraint(contact, infoGlobal)
456 btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
457 : m_face(other.m_face), m_useStrainLimiting(other.m_useStrainLimiting), btDeformableRigidContactConstraint(other)
461 btVector3 btDeformableFaceRigidContactConstraint::getVb() const
463 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
464 btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
468 btVector3 btDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
470 btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
471 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
472 if (m_face->m_n[0] == node)
474 return face_dv * contact->m_weights[0];
476 if (m_face->m_n[1] == node)
478 return face_dv * contact->m_weights[1];
480 btAssert(node == m_face->m_n[2]);
481 return face_dv * contact->m_weights[2];
484 void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
486 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
487 btVector3 dv = impulse * contact->m_c2;
488 btSoftBody::Face* face = contact->m_face;
490 btVector3& v0 = face->m_n[0]->m_v;
491 btVector3& v1 = face->m_n[1]->m_v;
492 btVector3& v2 = face->m_n[2]->m_v;
493 const btScalar& im0 = face->m_n[0]->m_im;
494 const btScalar& im1 = face->m_n[1]->m_im;
495 const btScalar& im2 = face->m_n[2]->m_im;
497 v0 -= dv * contact->m_weights[0];
499 v1 -= dv * contact->m_weights[1];
501 v2 -= dv * contact->m_weights[2];
502 if (m_useStrainLimiting)
504 btScalar relaxation = 1. / btScalar(m_infoGlobal->m_numIterations);
505 btScalar m01 = (relaxation / (im0 + im1));
506 btScalar m02 = (relaxation / (im0 + im2));
507 btScalar m12 = (relaxation / (im1 + im2));
508 #ifdef USE_STRAIN_RATE_LIMITING
509 // apply strain limiting to prevent the new velocity to change the current length of the edge by more than 1%.
511 btVector3& x0 = face->m_n[0]->m_x;
512 btVector3& x1 = face->m_n[1]->m_x;
513 btVector3& x2 = face->m_n[2]->m_x;
514 const btVector3 x_diff[3] = {x1 - x0, x2 - x0, x2 - x1};
515 const btVector3 v_diff[3] = {v1 - v0, v2 - v0, v2 - v1};
517 btScalar x_diff_dot_u, dn[3];
518 btScalar dt = m_infoGlobal->m_timeStep;
519 for (int i = 0; i < 3; ++i)
521 btScalar x_diff_norm = x_diff[i].safeNorm();
522 btScalar x_diff_norm_new = (x_diff[i] + v_diff[i] * dt).safeNorm();
523 btScalar strainRate = x_diff_norm_new / x_diff_norm;
525 u[i].safeNormalize();
526 if (x_diff_norm == 0 || (1 - p <= strainRate && strainRate <= 1 + p))
531 x_diff_dot_u = btDot(x_diff[i], u[i]);
533 if (1 - p > strainRate)
535 s = 1 / dt * (-x_diff_dot_u - btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p - 2 * p) * x_diff_norm * x_diff_norm));
539 s = 1 / dt * (-x_diff_dot_u + btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p + 2 * p) * x_diff_norm * x_diff_norm));
541 // x_diff_norm_new = (x_diff[i] + s * u[i] * dt).safeNorm();
542 // strainRate = x_diff_norm_new/x_diff_norm;
543 dn[i] = s - v_diff[i].safeNorm();
545 btVector3 dv0 = im0 * (m01 * u[0] * (-dn[0]) + m02 * u[1] * -(dn[1]));
546 btVector3 dv1 = im1 * (m01 * u[0] * (dn[0]) + m12 * u[2] * (-dn[2]));
547 btVector3 dv2 = im2 * (m12 * u[2] * (dn[2]) + m02 * u[1] * (dn[1]));
549 // apply strain limiting to prevent undamped modes
550 btVector3 dv0 = im0 * (m01 * (v1 - v0) + m02 * (v2 - v0));
551 btVector3 dv1 = im1 * (m01 * (v0 - v1) + m12 * (v2 - v1));
552 btVector3 dv2 = im2 * (m12 * (v1 - v2) + m02 * (v0 - v2));
560 btVector3 btDeformableFaceRigidContactConstraint::getSplitVb() const
562 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
563 btVector3 vb = (m_face->m_n[0]->m_splitv) * contact->m_bary[0] + (m_face->m_n[1]->m_splitv) * contact->m_bary[1] + (m_face->m_n[2]->m_splitv) * contact->m_bary[2];
567 void btDeformableFaceRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
569 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
570 btVector3 dv = impulse * contact->m_c2;
571 btSoftBody::Face* face = contact->m_face;
572 btVector3& v0 = face->m_n[0]->m_splitv;
573 btVector3& v1 = face->m_n[1]->m_splitv;
574 btVector3& v2 = face->m_n[2]->m_splitv;
575 const btScalar& im0 = face->m_n[0]->m_im;
576 const btScalar& im1 = face->m_n[1]->m_im;
577 const btScalar& im2 = face->m_n[2]->m_im;
580 v0 -= dv * contact->m_weights[0];
584 v1 -= dv * contact->m_weights[1];
588 v2 -= dv * contact->m_weights[2];
592 /* ================ Face vs. Node =================== */
593 btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal)
594 : m_node(contact.m_node), m_face(contact.m_face), m_contact(&contact), btDeformableContactConstraint(contact.m_normal, infoGlobal)
596 m_total_normal_dv.setZero();
597 m_total_tangent_dv.setZero();
600 btVector3 btDeformableFaceNodeContactConstraint::getVa() const
605 btVector3 btDeformableFaceNodeContactConstraint::getVb() const
607 const btSoftBody::DeformableFaceNodeContact* contact = getContact();
608 btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
612 btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n) const
614 btVector3 dv = m_total_normal_dv + m_total_tangent_dv;
617 const btSoftBody::DeformableFaceNodeContact* contact = getContact();
618 if (m_face->m_n[0] == n)
620 return dv * contact->m_weights[0];
622 if (m_face->m_n[1] == n)
624 return dv * contact->m_weights[1];
626 btAssert(n == m_face->m_n[2]);
627 return dv * contact->m_weights[2];
630 btScalar btDeformableFaceNodeContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
632 btVector3 va = getVa();
633 btVector3 vb = getVb();
634 btVector3 vr = vb - va;
635 const btScalar dn = btDot(vr, m_contact->m_normal);
636 // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
637 btScalar residualSquare = dn * dn;
638 btVector3 impulse = m_contact->m_c0 * vr;
639 const btVector3 impulse_normal = m_contact->m_c0 * (m_contact->m_normal * dn);
640 btVector3 impulse_tangent = impulse - impulse_normal;
642 btVector3 old_total_tangent_dv = m_total_tangent_dv;
643 // m_c2 is the inverse mass of the deformable node/face
644 if (m_node->m_im > 0)
646 m_total_normal_dv -= impulse_normal * m_node->m_im;
647 m_total_tangent_dv -= impulse_tangent * m_node->m_im;
651 m_total_normal_dv -= impulse_normal * m_contact->m_imf;
652 m_total_tangent_dv -= impulse_tangent * m_contact->m_imf;
655 if (m_total_normal_dv.dot(m_contact->m_normal) > 0)
657 // separating in the normal direction
659 m_total_tangent_dv = btVector3(0, 0, 0);
660 impulse_tangent.setZero();
664 if (m_total_normal_dv.norm() * m_contact->m_friction < m_total_tangent_dv.norm())
667 // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
669 if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
671 m_total_tangent_dv = btVector3(0, 0, 0);
675 m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_friction;
677 impulse_tangent = -btScalar(1) / m_node->m_im * (m_total_tangent_dv - old_total_tangent_dv);
685 impulse = impulse_normal + impulse_tangent;
686 // apply impulse to deformable nodes involved and change their velocities
687 applyImpulse(impulse);
688 return residualSquare;
691 void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impulse)
693 const btSoftBody::DeformableFaceNodeContact* contact = getContact();
694 btVector3 dva = impulse * contact->m_node->m_im;
695 btVector3 dvb = impulse * contact->m_imf;
696 if (contact->m_node->m_im > 0)
698 contact->m_node->m_v += dva;
701 btSoftBody::Face* face = contact->m_face;
702 btVector3& v0 = face->m_n[0]->m_v;
703 btVector3& v1 = face->m_n[1]->m_v;
704 btVector3& v2 = face->m_n[2]->m_v;
705 const btScalar& im0 = face->m_n[0]->m_im;
706 const btScalar& im1 = face->m_n[1]->m_im;
707 const btScalar& im2 = face->m_n[2]->m_im;
710 v0 -= dvb * contact->m_weights[0];
714 v1 -= dvb * contact->m_weights[1];
718 v2 -= dvb * contact->m_weights[2];