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 "btDeformableContactProjection.h"
17 #include "btDeformableMultiBodyDynamicsWorld.h"
20 btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
22 btScalar residualSquare = 0;
23 for (int i = 0; i < numDeformableBodies; ++i)
25 for (int j = 0; j < m_softBodies.size(); ++j)
27 btCollisionObject* psb = m_softBodies[j];
28 if (psb != deformableBodies[i])
32 for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
34 btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
35 btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
36 residualSquare = btMax(residualSquare, localResidualSquare);
38 for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
40 btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
41 btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
42 residualSquare = btMax(residualSquare, localResidualSquare);
44 for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
46 btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
47 btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
48 residualSquare = btMax(residualSquare, localResidualSquare);
50 for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
52 btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
53 btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
54 residualSquare = btMax(residualSquare, localResidualSquare);
58 return residualSquare;
61 btScalar btDeformableContactProjection::solveSplitImpulse(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
63 btScalar residualSquare = 0;
64 for (int i = 0; i < numDeformableBodies; ++i)
66 for (int j = 0; j < m_softBodies.size(); ++j)
68 btCollisionObject* psb = m_softBodies[j];
69 if (psb != deformableBodies[i])
73 for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
75 btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
76 btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
77 residualSquare = btMax(residualSquare, localResidualSquare);
79 for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
81 btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
82 btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
83 residualSquare = btMax(residualSquare, localResidualSquare);
87 return residualSquare;
90 void btDeformableContactProjection::setConstraints(const btContactSolverInfo& infoGlobal)
92 BT_PROFILE("setConstraints");
93 for (int i = 0; i < m_softBodies.size(); ++i)
95 btSoftBody* psb = m_softBodies[i];
101 // set Dirichlet constraint
102 for (int j = 0; j < psb->m_nodes.size(); ++j)
104 if (psb->m_nodes[j].m_im == 0)
106 btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
107 m_staticConstraints[i].push_back(static_constraint);
111 // set up deformable anchors
112 for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
114 btSoftBody::DeformableNodeRigidAnchor& anchor = psb->m_deformableAnchors[j];
116 if (anchor.m_node->m_im == 0)
120 anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
121 btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
122 m_nodeAnchorConstraints[i].push_back(constraint);
125 // set Deformable Node vs. Rigid constraint
126 for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
128 const btSoftBody::DeformableNodeRigidContact& contact = psb->m_nodeRigidContacts[j];
130 if (contact.m_node->m_im == 0)
134 btDeformableNodeRigidContactConstraint constraint(contact, infoGlobal);
135 m_nodeRigidConstraints[i].push_back(constraint);
138 // set Deformable Face vs. Rigid constraint
139 for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
141 const btSoftBody::DeformableFaceRigidContact& contact = psb->m_faceRigidContacts[j];
143 if (contact.m_c2 == 0)
147 btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting);
148 m_faceRigidConstraints[i].push_back(constraint);
153 void btDeformableContactProjection::project(TVStack& x)
157 for (int index = 0; index < m_projectionsDict.size(); ++index)
159 btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
160 size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
161 if (projectionDirs.size() >= dim)
167 else if (projectionDirs.size() == 2)
169 btVector3 dir0 = projectionDirs[0];
170 btVector3 dir1 = projectionDirs[1];
171 btVector3 free_dir = btCross(dir0, dir1);
172 if (free_dir.safeNorm() < SIMD_EPSILON)
174 x[i] -= x[i].dot(dir0) * dir0;
178 free_dir.normalize();
179 x[i] = x[i].dot(free_dir) * free_dir;
184 btAssert(projectionDirs.size() == 1);
185 btVector3 dir0 = projectionDirs[0];
186 x[i] -= x[i].dot(dir0) * dir0;
190 btReducedVector p(x.size());
191 for (int i = 0; i < m_projections.size(); ++i)
193 p += (m_projections[i].dot(x) * m_projections[i]);
195 for (int i = 0; i < p.m_indices.size(); ++i)
197 x[p.m_indices[i]] -= p.m_vecs[i];
202 void btDeformableContactProjection::setProjection()
205 BT_PROFILE("btDeformableContactProjection::setProjection");
206 btAlignedObjectArray<btVector3> units;
207 units.push_back(btVector3(1, 0, 0));
208 units.push_back(btVector3(0, 1, 0));
209 units.push_back(btVector3(0, 0, 1));
210 for (int i = 0; i < m_softBodies.size(); ++i)
212 btSoftBody* psb = m_softBodies[i];
213 if (!psb->isActive())
217 for (int j = 0; j < m_staticConstraints[i].size(); ++j)
219 int index = m_staticConstraints[i][j].m_node->index;
220 m_staticConstraints[i][j].m_node->m_constrained = true;
221 if (m_projectionsDict.find(index) == NULL)
223 m_projectionsDict.insert(index, units);
227 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
228 for (int k = 0; k < 3; ++k)
230 projections.push_back(units[k]);
234 for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
236 int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
237 m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
238 if (m_projectionsDict.find(index) == NULL)
240 m_projectionsDict.insert(index, units);
244 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
245 for (int k = 0; k < 3; ++k)
247 projections.push_back(units[k]);
251 for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
253 int index = m_nodeRigidConstraints[i][j].m_node->index;
254 m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
255 if (m_nodeRigidConstraints[i][j].m_binding)
257 if (m_nodeRigidConstraints[i][j].m_static)
259 if (m_projectionsDict.find(index) == NULL)
261 m_projectionsDict.insert(index, units);
265 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
266 for (int k = 0; k < 3; ++k)
268 projections.push_back(units[k]);
274 if (m_projectionsDict.find(index) == NULL)
276 btAlignedObjectArray<btVector3> projections;
277 projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
278 m_projectionsDict.insert(index, projections);
282 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
283 projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
288 for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
290 const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
291 if (m_faceRigidConstraints[i][j].m_binding)
293 for (int k = 0; k < 3; ++k)
295 face->m_n[k]->m_constrained = true;
298 for (int k = 0; k < 3; ++k)
300 btSoftBody::Node* node = face->m_n[k];
301 int index = node->index;
302 if (m_faceRigidConstraints[i][j].m_static)
304 if (m_projectionsDict.find(index) == NULL)
306 m_projectionsDict.insert(index, units);
310 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
311 for (int l = 0; l < 3; ++l)
313 projections.push_back(units[l]);
319 if (m_projectionsDict.find(index) == NULL)
321 btAlignedObjectArray<btVector3> projections;
322 projections.push_back(m_faceRigidConstraints[i][j].m_normal);
323 m_projectionsDict.insert(index, projections);
327 btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
328 projections.push_back(m_faceRigidConstraints[i][j].m_normal);
336 for (int i = 0; i < m_softBodies.size(); ++i)
338 dof += m_softBodies[i]->m_nodes.size();
340 for (int i = 0; i < m_softBodies.size(); ++i)
342 btSoftBody* psb = m_softBodies[i];
343 if (!psb->isActive())
347 for (int j = 0; j < m_staticConstraints[i].size(); ++j)
349 int index = m_staticConstraints[i][j].m_node->index;
350 m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
351 btAlignedObjectArray<int> indices;
352 btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
353 indices.push_back(index);
354 vecs1.push_back(btVector3(1, 0, 0));
355 vecs2.push_back(btVector3(0, 1, 0));
356 vecs3.push_back(btVector3(0, 0, 1));
357 m_projections.push_back(btReducedVector(dof, indices, vecs1));
358 m_projections.push_back(btReducedVector(dof, indices, vecs2));
359 m_projections.push_back(btReducedVector(dof, indices, vecs3));
362 for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
364 int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
365 m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
366 btAlignedObjectArray<int> indices;
367 btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
368 indices.push_back(index);
369 vecs1.push_back(btVector3(1, 0, 0));
370 vecs2.push_back(btVector3(0, 1, 0));
371 vecs3.push_back(btVector3(0, 0, 1));
372 m_projections.push_back(btReducedVector(dof, indices, vecs1));
373 m_projections.push_back(btReducedVector(dof, indices, vecs2));
374 m_projections.push_back(btReducedVector(dof, indices, vecs3));
376 for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
378 int index = m_nodeRigidConstraints[i][j].m_node->index;
379 m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
380 btAlignedObjectArray<int> indices;
381 indices.push_back(index);
382 btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
383 if (m_nodeRigidConstraints[i][j].m_static)
385 vecs1.push_back(btVector3(1, 0, 0));
386 vecs2.push_back(btVector3(0, 1, 0));
387 vecs3.push_back(btVector3(0, 0, 1));
388 m_projections.push_back(btReducedVector(dof, indices, vecs1));
389 m_projections.push_back(btReducedVector(dof, indices, vecs2));
390 m_projections.push_back(btReducedVector(dof, indices, vecs3));
394 vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
395 m_projections.push_back(btReducedVector(dof, indices, vecs1));
398 for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
400 const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
401 btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
402 btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
403 for (int k = 0; k < 3; ++k)
405 face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
407 if (m_faceRigidConstraints[i][j].m_static)
409 for (int l = 0; l < 3; ++l)
411 btReducedVector rv(dof);
412 for (int k = 0; k < 3; ++k)
414 rv.m_indices.push_back(face->m_n[k]->index);
415 btVector3 v(0, 0, 0);
417 rv.m_vecs.push_back(v);
420 m_projections.push_back(rv);
425 btReducedVector rv(dof);
426 for (int k = 0; k < 3; ++k)
428 rv.m_indices.push_back(face->m_n[k]->index);
429 rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
432 m_projections.push_back(rv);
436 btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
438 m_projections = mgs.m_out;
442 void btDeformableContactProjection::checkConstraints(const TVStack& x)
444 for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
446 btVector3 d(0, 0, 0);
447 const LagrangeMultiplier& lm = m_lagrangeMultipliers[i];
448 for (int j = 0; j < lm.m_num_constraints; ++j)
450 for (int k = 0; k < lm.m_num_nodes; ++k)
452 d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
455 // printf("d = %f, %f, %f\n", d[0], d[1], d[2]);
456 // printf("val = %f, %f, %f\n", lm.m_vals[0], lm.m_vals[1], lm.m_vals[2]);
460 void btDeformableContactProjection::setLagrangeMultiplier()
462 for (int i = 0; i < m_softBodies.size(); ++i)
464 btSoftBody* psb = m_softBodies[i];
465 if (!psb->isActive())
469 for (int j = 0; j < m_staticConstraints[i].size(); ++j)
471 int index = m_staticConstraints[i][j].m_node->index;
472 m_staticConstraints[i][j].m_node->m_constrained = true;
473 LagrangeMultiplier lm;
475 lm.m_indices[0] = index;
476 lm.m_weights[0] = 1.0;
477 lm.m_num_constraints = 3;
478 lm.m_dirs[0] = btVector3(1, 0, 0);
479 lm.m_dirs[1] = btVector3(0, 1, 0);
480 lm.m_dirs[2] = btVector3(0, 0, 1);
481 m_lagrangeMultipliers.push_back(lm);
483 for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
485 int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
486 m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
487 LagrangeMultiplier lm;
489 lm.m_indices[0] = index;
490 lm.m_weights[0] = 1.0;
491 lm.m_num_constraints = 3;
492 lm.m_dirs[0] = btVector3(1, 0, 0);
493 lm.m_dirs[1] = btVector3(0, 1, 0);
494 lm.m_dirs[2] = btVector3(0, 0, 1);
495 m_lagrangeMultipliers.push_back(lm);
498 for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
500 if (!m_nodeRigidConstraints[i][j].m_binding)
504 int index = m_nodeRigidConstraints[i][j].m_node->index;
505 m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
506 LagrangeMultiplier lm;
508 lm.m_indices[0] = index;
509 lm.m_weights[0] = 1.0;
510 if (m_nodeRigidConstraints[i][j].m_static)
512 lm.m_num_constraints = 3;
513 lm.m_dirs[0] = btVector3(1, 0, 0);
514 lm.m_dirs[1] = btVector3(0, 1, 0);
515 lm.m_dirs[2] = btVector3(0, 0, 1);
519 lm.m_num_constraints = 1;
520 lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
522 m_lagrangeMultipliers.push_back(lm);
525 for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
527 if (!m_faceRigidConstraints[i][j].m_binding)
531 btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
533 btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
534 LagrangeMultiplier lm;
537 for (int k = 0; k < 3; ++k)
539 face->m_n[k]->m_constrained = true;
540 lm.m_indices[k] = face->m_n[k]->index;
541 lm.m_weights[k] = bary[k];
543 if (m_faceRigidConstraints[i][j].m_static)
545 face->m_pcontact[3] = 1;
546 lm.m_num_constraints = 3;
547 lm.m_dirs[0] = btVector3(1, 0, 0);
548 lm.m_dirs[1] = btVector3(0, 1, 0);
549 lm.m_dirs[2] = btVector3(0, 0, 1);
553 face->m_pcontact[3] = 0;
554 lm.m_num_constraints = 1;
555 lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
557 m_lagrangeMultipliers.push_back(lm);
563 void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
565 for (int i = 0; i < m_softBodies.size(); ++i)
567 for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
569 const btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
570 const btSoftBody::Node* node = constraint.m_node;
573 int index = node->index;
574 f[index] += constraint.getDv(node) * (1. / node->m_im);
577 for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
579 const btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
580 const btSoftBody::Face* face = constraint.getContact()->m_face;
581 for (int k = 0; k < 3; ++k)
583 const btSoftBody::Node* node = face->m_n[k];
586 int index = node->index;
587 f[index] += constraint.getDv(node) * (1. / node->m_im);
591 for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
593 const btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[i][j];
594 const btSoftBody::Face* face = constraint.getContact()->m_face;
595 const btSoftBody::Node* node = constraint.getContact()->m_node;
598 int index = node->index;
599 f[index] += constraint.getDv(node) * (1. / node->m_im);
601 for (int k = 0; k < 3; ++k)
603 const btSoftBody::Node* node = face->m_n[k];
606 int index = node->index;
607 f[index] += constraint.getDv(node) * (1. / node->m_im);
614 void btDeformableContactProjection::reinitialize(bool nodeUpdated)
616 int N = m_softBodies.size();
619 m_staticConstraints.resize(N);
620 m_nodeAnchorConstraints.resize(N);
621 m_nodeRigidConstraints.resize(N);
622 m_faceRigidConstraints.resize(N);
623 m_deformableConstraints.resize(N);
625 for (int i = 0; i < N; ++i)
627 m_staticConstraints[i].clear();
628 m_nodeAnchorConstraints[i].clear();
629 m_nodeRigidConstraints[i].clear();
630 m_faceRigidConstraints[i].clear();
631 m_deformableConstraints[i].clear();
634 m_projectionsDict.clear();
636 m_projections.clear();
638 m_lagrangeMultipliers.clear();