1 #include "btReducedDeformableContactConstraint.h"
4 // ================= static constraints ===================
5 btReducedDeformableStaticConstraint::btReducedDeformableStaticConstraint(
6 btReducedDeformableBody* rsb,
7 btSoftBody::Node* node,
11 const btContactSolverInfo& infoGlobal,
13 : m_rsb(rsb), m_ri(ri), m_targetPos(x0), m_impulseDirection(dir), m_dt(dt), btDeformableStaticConstraint(node, infoGlobal)
19 m_impulseFactorMatrix = rsb->getImpulseFactor(m_node->index);
20 m_impulseFactor = (m_impulseFactorMatrix * m_impulseDirection).dot(m_impulseDirection);
22 btScalar vel_error = btDot(-m_node->m_v, m_impulseDirection);
23 btScalar pos_error = btDot(m_targetPos - m_node->m_x, m_impulseDirection);
25 m_rhs = (vel_error + m_erp * pos_error / m_dt) / m_impulseFactor;
28 btScalar btReducedDeformableStaticConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
30 // target velocity of fixed constraint is 0
31 btVector3 deltaVa = getDeltaVa();
32 btScalar deltaV_rel = btDot(deltaVa, m_impulseDirection);
33 btScalar deltaImpulse = m_rhs - deltaV_rel / m_impulseFactor;
34 m_appliedImpulse = m_appliedImpulse + deltaImpulse;
36 btVector3 impulse = deltaImpulse * m_impulseDirection;
37 applyImpulse(impulse);
40 btScalar residualSquare = m_impulseFactor * deltaImpulse;
41 residualSquare *= residualSquare;
43 return residualSquare;
46 // this calls reduced deformable body's internalApplyFullSpaceImpulse
47 void btReducedDeformableStaticConstraint::applyImpulse(const btVector3& impulse)
49 // apply full space impulse
50 m_rsb->internalApplyFullSpaceImpulse(impulse, m_ri, m_node->index, m_dt);
53 btVector3 btReducedDeformableStaticConstraint::getDeltaVa() const
55 return m_rsb->internalComputeNodeDeltaVelocity(m_rsb->getInterpolationWorldTransform(), m_node->index);
58 // ================= base contact constraints ===================
59 btReducedDeformableRigidContactConstraint::btReducedDeformableRigidContactConstraint(
60 btReducedDeformableBody* rsb,
61 const btSoftBody::DeformableRigidContact& c,
62 const btContactSolverInfo& infoGlobal,
64 : m_rsb(rsb), m_dt(dt), btDeformableRigidContactConstraint(c, infoGlobal)
67 m_appliedNormalImpulse = 0;
68 m_appliedTangentImpulse = 0;
71 m_cfm = infoGlobal.m_deformable_cfm;
73 m_erp = infoGlobal.m_deformable_erp;
74 m_erp_friction = infoGlobal.m_deformable_erp;
75 m_friction = infoGlobal.m_friction;
77 m_collideStatic = m_contact->m_cti.m_colObj->isStaticObject();
78 m_collideMultibody = (m_contact->m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK);
81 void btReducedDeformableRigidContactConstraint::setSolverBody(const int bodyId, btSolverBody& solver_body)
83 if (!m_collideMultibody)
85 m_solverBodyId = bodyId;
86 m_solverBody = &solver_body;
87 m_linearComponentNormal = -m_contactNormalA * m_solverBody->internalGetInvMass();
88 btVector3 torqueAxis = -m_relPosA.cross(m_contactNormalA);
89 m_angularComponentNormal = m_solverBody->m_originalBody->getInvInertiaTensorWorld() * torqueAxis;
91 m_linearComponentTangent = m_contactTangent * m_solverBody->internalGetInvMass();
92 btVector3 torqueAxisTangent = m_relPosA.cross(m_contactTangent);
93 m_angularComponentTangent = m_solverBody->m_originalBody->getInvInertiaTensorWorld() * torqueAxisTangent;
97 btVector3 btReducedDeformableRigidContactConstraint::getVa() const
99 btVector3 Va(0, 0, 0);
100 if (!m_collideStatic)
102 Va = btDeformableRigidContactConstraint::getVa();
107 btScalar btReducedDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
109 // btVector3 Va = getVa();
110 // btVector3 deltaVa = Va - m_bufferVelocityA;
111 // if (!m_collideStatic)
113 // std::cout << "moving collision!!!\n";
114 // std::cout << "relPosA: " << m_relPosA[0] << "\t" << m_relPosA[1] << "\t" << m_relPosA[2] << "\n";
115 // std::cout << "moving rigid linear_vel: " << m_solverBody->m_originalBody->getLinearVelocity()[0] << '\t'
116 // << m_solverBody->m_originalBody->getLinearVelocity()[1] << '\t'
117 // << m_solverBody->m_originalBody->getLinearVelocity()[2] << '\n';
119 btVector3 deltaVa = getDeltaVa();
120 btVector3 deltaVb = getDeltaVb();
122 // if (!m_collideStatic)
124 // std::cout << "deltaVa: " << deltaVa[0] << '\t' << deltaVa[1] << '\t' << deltaVa[2] << '\n';
125 // std::cout << "deltaVb: " << deltaVb[0] << '\t' << deltaVb[1] << '\t' << deltaVb[2] << '\n';
128 // get delta relative velocity and magnitude (i.e., how much impulse has been applied?)
129 btVector3 deltaV_rel = deltaVa - deltaVb;
130 btScalar deltaV_rel_normal = -btDot(deltaV_rel, m_contactNormalA);
132 // if (!m_collideStatic)
134 // std::cout << "deltaV_rel: " << deltaV_rel[0] << '\t' << deltaV_rel[1] << '\t' << deltaV_rel[2] << "\n";
135 // std::cout << "deltaV_rel_normal: " << deltaV_rel_normal << "\n";
136 // std::cout << "normal_A: " << m_contactNormalA[0] << '\t' << m_contactNormalA[1] << '\t' << m_contactNormalA[2] << '\n';
139 // get the normal impulse to be applied
140 btScalar deltaImpulse = m_rhs - m_appliedNormalImpulse * m_cfm - deltaV_rel_normal / m_normalImpulseFactor;
141 // if (!m_collideStatic)
143 // std::cout << "m_rhs: " << m_rhs << '\t' << "m_appliedNormalImpulse: " << m_appliedNormalImpulse << "\n";
144 // std::cout << "m_normalImpulseFactor: " << m_normalImpulseFactor << '\n';
148 // cumulative impulse that has been applied
149 btScalar sum = m_appliedNormalImpulse + deltaImpulse;
150 // if the cumulative impulse is pushing the object into the rigid body, set it zero
153 deltaImpulse = -m_appliedNormalImpulse;
154 m_appliedNormalImpulse = 0;
158 m_appliedNormalImpulse = sum;
162 // if (!m_collideStatic)
164 // std::cout << "m_appliedNormalImpulse: " << m_appliedNormalImpulse << '\n';
165 // std::cout << "deltaImpulse: " << deltaImpulse << '\n';
168 // residual is the nodal normal velocity change in current iteration
169 btScalar residualSquare = deltaImpulse * m_normalImpulseFactor; // get residual
170 residualSquare *= residualSquare;
173 // apply Coulomb friction (based on delta velocity, |dv_t| = |dv_n * friction|)
174 btScalar deltaImpulse_tangent = 0;
175 btScalar deltaImpulse_tangent2 = 0;
177 // calculate how much impulse is needed
178 // btScalar deltaV_rel_tangent = btDot(deltaV_rel, m_contactTangent);
179 // btScalar impulse_changed = deltaV_rel_tangent * m_tangentImpulseFactorInv;
180 // deltaImpulse_tangent = m_rhs_tangent - impulse_changed;
182 // btScalar sum = m_appliedTangentImpulse + deltaImpulse_tangent;
183 btScalar lower_limit = - m_appliedNormalImpulse * m_friction;
184 btScalar upper_limit = m_appliedNormalImpulse * m_friction;
185 // if (sum > upper_limit)
187 // deltaImpulse_tangent = upper_limit - m_appliedTangentImpulse;
188 // m_appliedTangentImpulse = upper_limit;
190 // else if (sum < lower_limit)
192 // deltaImpulse_tangent = lower_limit - m_appliedTangentImpulse;
193 // m_appliedTangentImpulse = lower_limit;
197 // m_appliedTangentImpulse = sum;
200 calculateTangentialImpulse(deltaImpulse_tangent, m_appliedTangentImpulse, m_rhs_tangent,
201 m_tangentImpulseFactorInv, m_contactTangent, lower_limit, upper_limit, deltaV_rel);
203 if (m_collideMultibody)
205 calculateTangentialImpulse(deltaImpulse_tangent2, m_appliedTangentImpulse2, m_rhs_tangent2,
206 m_tangentImpulseFactorInv2, m_contactTangent2, lower_limit, upper_limit, deltaV_rel);
210 if (!m_collideStatic)
212 // std::cout << "m_contactTangent: " << m_contactTangent[0] << "\t" << m_contactTangent[1] << "\t" << m_contactTangent[2] << "\n";
213 // std::cout << "deltaV_rel_tangent: " << deltaV_rel_tangent << '\n';
214 // std::cout << "deltaImpulseTangent: " << deltaImpulse_tangent << '\n';
215 // std::cout << "m_appliedTangentImpulse: " << m_appliedTangentImpulse << '\n';
219 // get the total impulse vector
220 btVector3 impulse_normal = deltaImpulse * m_contactNormalA;
221 btVector3 impulse_tangent = deltaImpulse_tangent * (-m_contactTangent);
222 btVector3 impulse_tangent2 = deltaImpulse_tangent2 * (-m_contactTangent2);
223 btVector3 impulse = impulse_normal + impulse_tangent + impulse_tangent2;
225 applyImpulse(impulse);
227 // apply impulse to the rigid/multibodies involved and change their velocities
228 if (!m_collideStatic)
230 // std::cout << "linear_component: " << m_linearComponentNormal[0] << '\t'
231 // << m_linearComponentNormal[1] << '\t'
232 // << m_linearComponentNormal[2] << '\n';
233 // std::cout << "angular_component: " << m_angularComponentNormal[0] << '\t'
234 // << m_angularComponentNormal[1] << '\t'
235 // << m_angularComponentNormal[2] << '\n';
237 if (!m_collideMultibody) // collision with rigid body
239 // std::cout << "rigid impulse applied!!\n";
240 // std::cout << "delta Linear: " << m_solverBody->getDeltaLinearVelocity()[0] << '\t'
241 // << m_solverBody->getDeltaLinearVelocity()[1] << '\t'
242 // << m_solverBody->getDeltaLinearVelocity()[2] << '\n';
243 // std::cout << "delta Angular: " << m_solverBody->getDeltaAngularVelocity()[0] << '\t'
244 // << m_solverBody->getDeltaAngularVelocity()[1] << '\t'
245 // << m_solverBody->getDeltaAngularVelocity()[2] << '\n';
247 m_solverBody->internalApplyImpulse(m_linearComponentNormal, m_angularComponentNormal, deltaImpulse);
248 m_solverBody->internalApplyImpulse(m_linearComponentTangent, m_angularComponentTangent, deltaImpulse_tangent);
250 // std::cout << "after\n";
251 // std::cout << "rigid impulse applied!!\n";
252 // std::cout << "delta Linear: " << m_solverBody->getDeltaLinearVelocity()[0] << '\t'
253 // << m_solverBody->getDeltaLinearVelocity()[1] << '\t'
254 // << m_solverBody->getDeltaLinearVelocity()[2] << '\n';
255 // std::cout << "delta Angular: " << m_solverBody->getDeltaAngularVelocity()[0] << '\t'
256 // << m_solverBody->getDeltaAngularVelocity()[1] << '\t'
257 // << m_solverBody->getDeltaAngularVelocity()[2] << '\n';
259 else // collision with multibody
261 btMultiBodyLinkCollider* multibodyLinkCol = 0;
262 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(m_contact->m_cti.m_colObj);
263 if (multibodyLinkCol)
265 const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
266 // apply normal component of the impulse
267 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, -deltaImpulse);
269 // const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
270 // std::cout << "deltaV_normal: ";
271 // for (int i = 0; i < ndof; ++i)
273 // std::cout << i << "\t" << deltaV_normal[i] << '\n';
276 if (impulse_tangent.norm() > SIMD_EPSILON)
278 // apply tangential component of the impulse
279 const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
280 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, deltaImpulse_tangent);
281 const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
282 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, deltaImpulse_tangent2);
287 return residualSquare;
290 void btReducedDeformableRigidContactConstraint::calculateTangentialImpulse(btScalar& deltaImpulse_tangent,
291 btScalar& appliedImpulse,
292 const btScalar rhs_tangent,
293 const btScalar tangentImpulseFactorInv,
294 const btVector3& tangent,
295 const btScalar lower_limit,
296 const btScalar upper_limit,
297 const btVector3& deltaV_rel)
299 btScalar deltaV_rel_tangent = btDot(deltaV_rel, tangent);
300 btScalar impulse_changed = deltaV_rel_tangent * tangentImpulseFactorInv;
301 deltaImpulse_tangent = rhs_tangent - m_cfm_friction * appliedImpulse - impulse_changed;
303 btScalar sum = appliedImpulse + deltaImpulse_tangent;
304 if (sum > upper_limit)
306 deltaImpulse_tangent = upper_limit - appliedImpulse;
307 appliedImpulse = upper_limit;
309 else if (sum < lower_limit)
311 deltaImpulse_tangent = lower_limit - appliedImpulse;
312 appliedImpulse = lower_limit;
316 appliedImpulse = sum;
320 // ================= node vs rigid constraints ===================
321 btReducedDeformableNodeRigidContactConstraint::btReducedDeformableNodeRigidContactConstraint(
322 btReducedDeformableBody* rsb,
323 const btSoftBody::DeformableNodeRigidContact& contact,
324 const btContactSolverInfo& infoGlobal,
326 : m_node(contact.m_node), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
328 m_contactNormalA = contact.m_cti.m_normal;
329 m_contactNormalB = -contact.m_cti.m_normal;
331 if (contact.m_node->index < rsb->m_nodes.size())
333 m_nodeQueryIndex = contact.m_node->index;
337 m_nodeQueryIndex = m_node->index - rsb->m_nodeIndexOffset;
340 if (m_contact->m_cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
342 m_relPosA = contact.m_c1;
346 m_relPosA = btVector3(0,0,0);
348 m_relPosB = m_node->m_x - m_rsb->getRigidTransform().getOrigin();
350 if (m_collideStatic) // colliding with static object, only consider reduced deformable body's impulse factor
352 m_impulseFactor = m_rsb->getImpulseFactor(m_nodeQueryIndex);
354 else // colliding with dynamic object, consider both reduced deformable and rigid body's impulse factors
356 m_impulseFactor = m_rsb->getImpulseFactor(m_nodeQueryIndex) + contact.m_c0;
359 m_normalImpulseFactor = (m_impulseFactor * m_contactNormalA).dot(m_contactNormalA);
360 m_tangentImpulseFactor = 0;
365 void btReducedDeformableNodeRigidContactConstraint::warmStarting()
367 btVector3 va = getVa();
368 btVector3 vb = getVb();
369 m_bufferVelocityA = va;
370 m_bufferVelocityB = vb;
372 // we define the (+) direction of errors to be the outward surface normal of the rigid object
373 btVector3 v_rel = vb - va;
374 // get tangent direction of the relative velocity
375 btVector3 v_tangent = v_rel - v_rel.dot(m_contactNormalA) * m_contactNormalA;
376 if (v_tangent.norm() < SIMD_EPSILON)
378 m_contactTangent = btVector3(0, 0, 0);
379 // tangent impulse factor
380 m_tangentImpulseFactor = 0;
381 m_tangentImpulseFactorInv = 0;
385 if (!m_collideMultibody)
387 m_contactTangent = v_tangent.normalized();
388 m_contactTangent2.setZero();
389 // tangent impulse factor 1
390 m_tangentImpulseFactor = (m_impulseFactor * m_contactTangent).dot(m_contactTangent);
391 m_tangentImpulseFactorInv = btScalar(1) / m_tangentImpulseFactor;
392 // tangent impulse factor 2
393 m_tangentImpulseFactor2 = 0;
394 m_tangentImpulseFactorInv2 = 0;
396 else // multibody requires 2 contact directions
398 m_contactTangent = m_contact->t1;
399 m_contactTangent2 = m_contact->t2;
401 // tangent impulse factor 1
402 m_tangentImpulseFactor = (m_impulseFactor * m_contactTangent).dot(m_contactTangent);
403 m_tangentImpulseFactorInv = btScalar(1) / m_tangentImpulseFactor;
404 // tangent impulse factor 2
405 m_tangentImpulseFactor2 = (m_impulseFactor * m_contactTangent2).dot(m_contactTangent2);
406 m_tangentImpulseFactorInv2 = btScalar(1) / m_tangentImpulseFactor2;
411 // initial guess for normal impulse
413 btScalar velocity_error = btDot(v_rel, m_contactNormalA); // magnitude of relative velocity
414 btScalar position_error = 0;
415 if (m_penetration > 0)
417 velocity_error += m_penetration / m_dt;
421 // add penetration correction vel
422 position_error = m_penetration * m_erp / m_dt;
424 // get the initial estimate of impulse magnitude to be applied
425 m_rhs = -(velocity_error + position_error) / m_normalImpulseFactor;
428 // initial guess for tangential impulse
430 btScalar velocity_error = btDot(v_rel, m_contactTangent);
431 m_rhs_tangent = velocity_error * m_tangentImpulseFactorInv;
433 if (m_collideMultibody)
435 btScalar velocity_error2 = btDot(v_rel, m_contactTangent2);
436 m_rhs_tangent2 = velocity_error2 * m_tangentImpulseFactorInv2;
441 // applyImpulse(m_rhs * m_contactNormalA);
442 // if (!m_collideStatic)
444 // const btSoftBody::sCti& cti = m_contact->m_cti;
445 // if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
447 // m_solverBody->internalApplyImpulse(m_linearComponentNormal, m_angularComponentNormal, -m_rhs);
452 btVector3 btReducedDeformableNodeRigidContactConstraint::getVb() const
457 btVector3 btReducedDeformableNodeRigidContactConstraint::getDeltaVa() const
459 btVector3 deltaVa(0, 0, 0);
460 if (!m_collideStatic)
462 if (!m_collideMultibody) // for rigid body
464 deltaVa = m_solverBody->internalGetDeltaLinearVelocity() + m_solverBody->internalGetDeltaAngularVelocity().cross(m_relPosA);
466 else // for multibody
468 btMultiBodyLinkCollider* multibodyLinkCol = 0;
469 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(m_contact->m_cti.m_colObj);
470 if (multibodyLinkCol)
472 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
473 const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
474 const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
475 const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
476 const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
477 // add in the normal component of the va
479 for (int k = 0; k < ndof; ++k)
481 vel += local_dv[k] * J_n[k];
483 deltaVa = m_contact->m_cti.m_normal * vel;
485 // add in the tangential components of the va
487 for (int k = 0; k < ndof; ++k)
489 vel += local_dv[k] * J_t1[k];
491 deltaVa += m_contact->t1 * vel;
494 for (int k = 0; k < ndof; ++k)
496 vel += local_dv[k] * J_t2[k];
498 deltaVa += m_contact->t2 * vel;
505 btVector3 btReducedDeformableNodeRigidContactConstraint::getDeltaVb() const
507 // std::cout << "node: " << m_node->index << '\n';
508 return m_rsb->internalComputeNodeDeltaVelocity(m_rsb->getInterpolationWorldTransform(), m_nodeQueryIndex);
511 btVector3 btReducedDeformableNodeRigidContactConstraint::getSplitVb() const
513 return m_node->m_splitv;
516 btVector3 btReducedDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
518 return m_total_normal_dv + m_total_tangent_dv;
521 void btReducedDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
523 m_rsb->internalApplyFullSpaceImpulse(impulse, m_relPosB, m_nodeQueryIndex, m_dt);
524 // m_rsb->applyFullSpaceImpulse(impulse, m_relPosB, m_node->index, m_dt);
525 // m_rsb->mapToFullVelocity(m_rsb->getInterpolationWorldTransform());
526 // if (!m_collideStatic)
528 // // std::cout << "impulse applied: " << impulse[0] << '\t' << impulse[1] << '\t' << impulse[2] << '\n';
529 // // std::cout << "node: " << m_node->index << " vel: " << m_node->m_v[0] << '\t' << m_node->m_v[1] << '\t' << m_node->m_v[2] << '\n';
530 // btVector3 v_after = getDeltaVb() + m_node->m_v;
531 // // std::cout << "vel after: " << v_after[0] << '\t' << v_after[1] << '\t' << v_after[2] << '\n';
533 // std::cout << "node: " << m_node->index << " pos: " << m_node->m_x[0] << '\t' << m_node->m_x[1] << '\t' << m_node->m_x[2] << '\n';
536 // ================= face vs rigid constraints ===================
537 btReducedDeformableFaceRigidContactConstraint::btReducedDeformableFaceRigidContactConstraint(
538 btReducedDeformableBody* rsb,
539 const btSoftBody::DeformableFaceRigidContact& contact,
540 const btContactSolverInfo& infoGlobal,
542 bool useStrainLimiting)
543 : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
546 btVector3 btReducedDeformableFaceRigidContactConstraint::getVb() const
548 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
549 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];
553 btVector3 btReducedDeformableFaceRigidContactConstraint::getSplitVb() const
555 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
556 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];
560 btVector3 btReducedDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
562 btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
563 const btSoftBody::DeformableFaceRigidContact* contact = getContact();
564 if (m_face->m_n[0] == node)
566 return face_dv * contact->m_weights[0];
568 if (m_face->m_n[1] == node)
570 return face_dv * contact->m_weights[1];
572 btAssert(node == m_face->m_n[2]);
573 return face_dv * contact->m_weights[2];
576 void btReducedDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)