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.
18 #include "btDeformableBodySolver.h"
19 #include "btSoftBodyInternals.h"
20 #include "LinearMath/btQuickprof.h"
21 static const int kMaxConjugateGradientIterations = 300;
22 btDeformableBodySolver::btDeformableBodySolver()
23 : m_numNodes(0), m_cg(kMaxConjugateGradientIterations), m_cr(kMaxConjugateGradientIterations), m_maxNewtonIterations(1), m_newtonTolerance(1e-4), m_lineSearch(false), m_useProjection(false)
25 m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
26 m_reducedSolver = false;
29 btDeformableBodySolver::~btDeformableBodySolver()
34 void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
36 BT_PROFILE("solveDeformableConstraints");
39 m_objective->computeResidual(solverdt, m_residual);
40 m_objective->applyDynamicFriction(m_residual);
43 computeStep(m_dv, m_residual);
48 m_objective->addLagrangeMultiplierRHS(m_residual, m_dv, rhs);
49 m_objective->addLagrangeMultiplier(m_dv, x);
50 m_objective->m_preconditioner->reinitialize(true);
52 for (int i = 0; i < m_dv.size(); ++i)
61 for (int i = 0; i < m_maxNewtonIterations; ++i)
64 // add the inertia term in the residual
66 for (int k = 0; k < m_softBodies.size(); ++k)
68 btSoftBody* psb = m_softBodies[k];
69 for (int j = 0; j < psb->m_nodes.size(); ++j)
71 if (psb->m_nodes[j].m_im > 0)
73 m_residual[counter] = (-1. / psb->m_nodes[j].m_im) * m_dv[counter];
79 m_objective->computeResidual(solverdt, m_residual);
80 if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
84 // todo xuchenhan@: this really only needs to be calculated once
85 m_objective->applyDynamicFriction(m_residual);
88 btScalar inner_product = computeDescentStep(m_ddv, m_residual);
89 btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
91 btScalar f0 = m_objective->totalEnergy(solverdt) + kineticEnergy(), f1, f2;
101 f1 = m_objective->totalEnergy(solverdt) + kineticEnergy();
102 f2 = f0 - alpha * scale * inner_product;
103 } while (!(f1 < f2 + SIMD_EPSILON)); // if anything here is nan then the search continues
109 computeStep(m_ddv, m_residual);
112 for (int j = 0; j < m_numNodes; ++j)
115 m_residual[j].setZero();
122 btScalar btDeformableBodySolver::kineticEnergy()
125 for (int i = 0; i < m_softBodies.size(); ++i)
127 btSoftBody* psb = m_softBodies[i];
128 for (int j = 0; j < psb->m_nodes.size(); ++j)
130 btSoftBody::Node& node = psb->m_nodes[j];
133 ke += m_dv[node.index].length2() * 0.5 / node.m_im;
140 void btDeformableBodySolver::backupDv()
142 m_backup_dv.resize(m_dv.size());
143 for (int i = 0; i < m_backup_dv.size(); ++i)
145 m_backup_dv[i] = m_dv[i];
149 void btDeformableBodySolver::revertDv()
151 for (int i = 0; i < m_backup_dv.size(); ++i)
153 m_dv[i] = m_backup_dv[i];
157 void btDeformableBodySolver::updateEnergy(btScalar scale)
159 for (int i = 0; i < m_dv.size(); ++i)
161 m_dv[i] = m_backup_dv[i] + scale * m_ddv[i];
166 btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose)
168 m_cg.solve(*m_objective, ddv, residual, false);
169 btScalar inner_product = m_cg.dot(residual, m_ddv);
170 btScalar res_norm = m_objective->computeNorm(residual);
171 btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
172 if (inner_product < -tol)
176 std::cout << "Looking backwards!" << std::endl;
178 for (int i = 0; i < m_ddv.size(); ++i)
180 m_ddv[i] = -m_ddv[i];
182 inner_product = -inner_product;
184 else if (std::abs(inner_product) < tol)
188 std::cout << "Gradient Descent!" << std::endl;
190 btScalar scale = m_objective->computeNorm(m_ddv) / res_norm;
191 for (int i = 0; i < m_ddv.size(); ++i)
193 m_ddv[i] = scale * residual[i];
195 inner_product = scale * res_norm * res_norm;
197 return inner_product;
200 void btDeformableBodySolver::updateState()
203 updateTempPosition();
206 void btDeformableBodySolver::updateDv(btScalar scale)
208 for (int i = 0; i < m_numNodes; ++i)
210 m_dv[i] += scale * m_ddv[i];
214 void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
217 m_cg.solve(*m_objective, ddv, residual, false);
219 m_cr.solve(*m_objective, ddv, residual, false);
222 void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody*>& softBodies, btScalar dt)
224 m_softBodies.copyFromArray(softBodies);
225 bool nodeUpdated = updateNodes();
229 m_dv.resize(m_numNodes, btVector3(0, 0, 0));
230 m_ddv.resize(m_numNodes, btVector3(0, 0, 0));
231 m_residual.resize(m_numNodes, btVector3(0, 0, 0));
232 m_backupVelocity.resize(m_numNodes, btVector3(0, 0, 0));
235 // need to setZero here as resize only set value for newly allocated items
236 for (int i = 0; i < m_numNodes; ++i)
240 m_residual[i].setZero();
247 m_objective->reinitialize(nodeUpdated, dt);
251 void btDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
253 BT_PROFILE("setConstraint");
254 m_objective->setConstraints(infoGlobal);
257 btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
259 BT_PROFILE("solveContactConstraints");
260 btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies, numDeformableBodies, infoGlobal);
261 return maxSquaredResidual;
264 void btDeformableBodySolver::updateVelocity()
267 for (int i = 0; i < m_softBodies.size(); ++i)
269 btSoftBody* psb = m_softBodies[i];
270 psb->m_maxSpeedSquared = 0;
271 if (!psb->isActive())
273 counter += psb->m_nodes.size();
276 for (int j = 0; j < psb->m_nodes.size(); ++j)
279 if (m_dv[counter] != m_dv[counter])
281 m_dv[counter].setZero();
285 psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter];
289 psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter] - psb->m_nodes[j].m_splitv;
291 psb->m_maxSpeedSquared = btMax(psb->m_maxSpeedSquared, psb->m_nodes[j].m_v.length2());
297 void btDeformableBodySolver::updateTempPosition()
300 for (int i = 0; i < m_softBodies.size(); ++i)
302 btSoftBody* psb = m_softBodies[i];
303 if (!psb->isActive())
305 counter += psb->m_nodes.size();
308 for (int j = 0; j < psb->m_nodes.size(); ++j)
310 psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * (psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv);
313 psb->updateDeformation();
317 void btDeformableBodySolver::backupVelocity()
320 for (int i = 0; i < m_softBodies.size(); ++i)
322 btSoftBody* psb = m_softBodies[i];
323 for (int j = 0; j < psb->m_nodes.size(); ++j)
325 m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
330 void btDeformableBodySolver::setupDeformableSolve(bool implicit)
333 for (int i = 0; i < m_softBodies.size(); ++i)
335 btSoftBody* psb = m_softBodies[i];
336 if (!psb->isActive())
338 counter += psb->m_nodes.size();
341 for (int j = 0; j < psb->m_nodes.size(); ++j)
345 // setting the initial guess for newton, need m_dv = v_{n+1} - v_n for dofs that are in constraint.
346 if (psb->m_nodes[j].m_v == m_backupVelocity[counter])
347 m_dv[counter].setZero();
349 m_dv[counter] = psb->m_nodes[j].m_v - psb->m_nodes[j].m_vn;
350 m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
354 m_dv[counter] = psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv - m_backupVelocity[counter];
356 psb->m_nodes[j].m_v = m_backupVelocity[counter];
362 void btDeformableBodySolver::revertVelocity()
365 for (int i = 0; i < m_softBodies.size(); ++i)
367 btSoftBody* psb = m_softBodies[i];
368 for (int j = 0; j < psb->m_nodes.size(); ++j)
370 psb->m_nodes[j].m_v = m_backupVelocity[counter++];
375 bool btDeformableBodySolver::updateNodes()
378 for (int i = 0; i < m_softBodies.size(); ++i)
379 numNodes += m_softBodies[i]->m_nodes.size();
380 if (numNodes != m_numNodes)
382 m_numNodes = numNodes;
388 void btDeformableBodySolver::predictMotion(btScalar solverdt)
390 // apply explicit forces to velocity
393 for (int i = 0; i < m_softBodies.size(); ++i)
395 btSoftBody* psb = m_softBodies[i];
398 for (int j = 0; j < psb->m_nodes.size(); ++j)
400 psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + psb->m_nodes[j].m_v * solverdt;
405 applyExplicitForce();
406 for (int i = 0; i < m_softBodies.size(); ++i)
408 btSoftBody* psb = m_softBodies[i];
411 /* Clear contacts when softbody is active*/
412 psb->m_nodeRigidContacts.resize(0);
413 psb->m_faceRigidContacts.resize(0);
414 psb->m_faceNodeContacts.resize(0);
415 psb->m_faceNodeContactsCCD.resize(0);
416 // predict motion for collision detection
417 predictDeformableMotion(psb, solverdt);
422 void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
424 BT_PROFILE("btDeformableBodySolver::predictDeformableMotion");
428 if (psb->m_bUpdateRtCst)
430 psb->m_bUpdateRtCst = false;
431 psb->updateConstants();
432 psb->m_fdbvt.clear();
433 if (psb->m_cfg.collisions & btSoftBody::fCollision::SDF_RD)
435 psb->initializeFaceTree();
440 psb->m_sst.sdt = dt * psb->m_cfg.timescale;
441 psb->m_sst.isdt = 1 / psb->m_sst.sdt;
442 psb->m_sst.velmrg = psb->m_sst.sdt * 3;
443 psb->m_sst.radmrg = psb->getCollisionShape()->getMargin();
444 psb->m_sst.updmrg = psb->m_sst.radmrg * (btScalar)0.25;
449 // do not allow particles to move more than the bounding box size
450 btScalar max_v = (psb->m_bounds[1] - psb->m_bounds[0]).norm() / dt;
451 for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
453 btSoftBody::Node& n = psb->m_nodes[i];
455 n.m_v *= (1 - psb->m_cfg.drag);
456 // scale velocity back
463 if (n.m_v.norm() > max_v)
465 n.m_v.safeNormalize();
468 n.m_q = n.m_x + n.m_v * dt;
470 n.m_splitv.setZero();
471 n.m_constrained = false;
475 psb->updateNodeTree(true, true);
476 if (!psb->m_fdbvt.empty())
478 psb->updateFaceTree(true, true);
480 /* Optimize dbvt's */
481 // psb->m_ndbvt.optimizeIncremental(1);
482 // psb->m_fdbvt.optimizeIncremental(1);
485 void btDeformableBodySolver::updateSoftBodies()
487 BT_PROFILE("updateSoftBodies");
488 for (int i = 0; i < m_softBodies.size(); i++)
490 btSoftBody* psb = (btSoftBody*)m_softBodies[i];
493 psb->updateNormals();
498 void btDeformableBodySolver::setImplicit(bool implicit)
500 m_implicit = implicit;
501 m_objective->setImplicit(implicit);
504 void btDeformableBodySolver::setLineSearch(bool lineSearch)
506 m_lineSearch = lineSearch;
509 void btDeformableBodySolver::applyExplicitForce()
511 m_objective->applyExplicitForce(m_residual);
514 void btDeformableBodySolver::applyTransforms(btScalar timeStep)
516 for (int i = 0; i < m_softBodies.size(); ++i)
518 btSoftBody* psb = m_softBodies[i];
519 for (int j = 0; j < psb->m_nodes.size(); ++j)
521 btSoftBody::Node& node = psb->m_nodes[j];
522 btScalar maxDisplacement = psb->getWorldInfo()->m_maxDisplacement;
523 btScalar clampDeltaV = maxDisplacement / timeStep;
524 for (int c = 0; c < 3; c++)
526 if (node.m_v[c] > clampDeltaV)
528 node.m_v[c] = clampDeltaV;
530 if (node.m_v[c] < -clampDeltaV)
532 node.m_v[c] = -clampDeltaV;
535 node.m_x = node.m_x + timeStep * (node.m_v + node.m_splitv);
537 node.m_vn = node.m_v;
539 // enforce anchor constraints
540 for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
542 btSoftBody::DeformableNodeRigidAnchor& a = psb->m_deformableAnchors[j];
543 btSoftBody::Node* n = a.m_node;
544 n->m_x = a.m_cti.m_colObj->getWorldTransform() * a.m_local;
546 // update multibody anchor info
547 if (a.m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
549 btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(a.m_cti.m_colObj);
550 if (multibodyLinkCol)
553 const btCollisionShape* shp = multibodyLinkCol->getCollisionShape();
554 const btTransform& wtr = multibodyLinkCol->getWorldTransform();
555 psb->m_worldInfo->m_sparsesdf.Evaluate(
556 wtr.invXform(n->m_x),
560 a.m_cti.m_normal = wtr.getBasis() * nrm;
561 btVector3 normal = a.m_cti.m_normal;
562 btVector3 t1 = generateUnitOrthogonalVector(normal);
563 btVector3 t2 = btCross(normal, t1);
564 btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
565 findJacobian(multibodyLinkCol, jacobianData_normal, a.m_node->m_x, normal);
566 findJacobian(multibodyLinkCol, jacobianData_t1, a.m_node->m_x, t1);
567 findJacobian(multibodyLinkCol, jacobianData_t2, a.m_node->m_x, t2);
569 btScalar* J_n = &jacobianData_normal.m_jacobians[0];
570 btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
571 btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
573 btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
574 btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
575 btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
577 btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
578 t1.getX(), t1.getY(), t1.getZ(),
579 t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
580 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
581 btMatrix3x3 local_impulse_matrix = (Diagonal(n->m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
582 a.m_c0 = rot.transpose() * local_impulse_matrix * rot;
583 a.jacobianData_normal = jacobianData_normal;
584 a.jacobianData_t1 = jacobianData_t1;
585 a.jacobianData_t2 = jacobianData_t2;
591 psb->interpolateRenderMesh();