Bullet Collision Detection & Physics Library
btReducedDeformableContactConstraint.cpp
Go to the documentation of this file.
2#include <iostream>
3
4// ================= static constraints ===================
8 const btVector3& ri,
9 const btVector3& x0,
10 const btVector3& dir,
11 const btContactSolverInfo& infoGlobal,
12 btScalar dt)
13 : m_rsb(rsb), m_ri(ri), m_targetPos(x0), m_impulseDirection(dir), m_dt(dt), btDeformableStaticConstraint(node, infoGlobal)
14{
15 m_erp = 0.2;
17
18 // get impulse factor
21
24
25 m_rhs = (vel_error + m_erp * pos_error / m_dt) / m_impulseFactor;
26}
27
29{
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;
35
36 btVector3 impulse = deltaImpulse * m_impulseDirection;
37 applyImpulse(impulse);
38
39 // calculate residual
40 btScalar residualSquare = m_impulseFactor * deltaImpulse;
41 residualSquare *= residualSquare;
42
43 return residualSquare;
44}
45
46// this calls reduced deformable body's internalApplyFullSpaceImpulse
48{
49 // apply full space impulse
51}
52
54{
56}
57
58// ================= base contact constraints ===================
62 const btContactSolverInfo& infoGlobal,
63 btScalar dt)
64 : m_rsb(rsb), m_dt(dt), btDeformableRigidContactConstraint(c, infoGlobal)
65{
69 m_rhs = 0;
70 m_rhs_tangent = 0;
71 m_cfm = infoGlobal.m_deformable_cfm;
73 m_erp = infoGlobal.m_deformable_erp;
75 m_friction = infoGlobal.m_friction;
76
79}
80
82{
84 {
85 m_solverBodyId = bodyId;
86 m_solverBody = &solver_body;
90
92 btVector3 torqueAxisTangent = m_relPosA.cross(m_contactTangent);
94 }
95}
96
98{
99 btVector3 Va(0, 0, 0);
100 if (!m_collideStatic)
101 {
103 }
104 return Va;
105}
106
108{
109 // btVector3 Va = getVa();
110 // btVector3 deltaVa = Va - m_bufferVelocityA;
111 // if (!m_collideStatic)
112 // {
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';
118 // }
119 btVector3 deltaVa = getDeltaVa();
120 btVector3 deltaVb = getDeltaVb();
121
122 // if (!m_collideStatic)
123 // {
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';
126 // }
127
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);
131
132 // if (!m_collideStatic)
133 // {
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';
137 // }
138
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)
142 // {
143 // std::cout << "m_rhs: " << m_rhs << '\t' << "m_appliedNormalImpulse: " << m_appliedNormalImpulse << "\n";
144 // std::cout << "m_normalImpulseFactor: " << m_normalImpulseFactor << '\n';
145 // }
146
147 {
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
151 if (sum < 0)
152 {
153 deltaImpulse = -m_appliedNormalImpulse;
155 }
156 else
157 {
159 }
160 }
161
162 // if (!m_collideStatic)
163 // {
164 // std::cout << "m_appliedNormalImpulse: " << m_appliedNormalImpulse << '\n';
165 // std::cout << "deltaImpulse: " << deltaImpulse << '\n';
166 // }
167
168 // residual is the nodal normal velocity change in current iteration
169 btScalar residualSquare = deltaImpulse * m_normalImpulseFactor; // get residual
170 residualSquare *= residualSquare;
171
172
173 // apply Coulomb friction (based on delta velocity, |dv_t| = |dv_n * friction|)
174 btScalar deltaImpulse_tangent = 0;
175 btScalar deltaImpulse_tangent2 = 0;
176 {
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;
181
182 // btScalar sum = m_appliedTangentImpulse + deltaImpulse_tangent;
185 // if (sum > upper_limit)
186 // {
187 // deltaImpulse_tangent = upper_limit - m_appliedTangentImpulse;
188 // m_appliedTangentImpulse = upper_limit;
189 // }
190 // else if (sum < lower_limit)
191 // {
192 // deltaImpulse_tangent = lower_limit - m_appliedTangentImpulse;
193 // m_appliedTangentImpulse = lower_limit;
194 // }
195 // else
196 // {
197 // m_appliedTangentImpulse = sum;
198 // }
199 //
201 m_tangentImpulseFactorInv, m_contactTangent, lower_limit, upper_limit, deltaV_rel);
202
204 {
206 m_tangentImpulseFactorInv2, m_contactTangent2, lower_limit, upper_limit, deltaV_rel);
207 }
208
209
210 if (!m_collideStatic)
211 {
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';
216 }
217 }
218
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;
224
225 applyImpulse(impulse);
226
227 // apply impulse to the rigid/multibodies involved and change their velocities
228 if (!m_collideStatic)
229 {
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';
236
237 if (!m_collideMultibody) // collision with rigid body
238 {
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';
246
249
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';
258 }
259 else // collision with multibody
260 {
261 btMultiBodyLinkCollider* multibodyLinkCol = 0;
263 if (multibodyLinkCol)
264 {
266 // apply normal component of the impulse
267 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, -deltaImpulse);
268
269 // const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
270 // std::cout << "deltaV_normal: ";
271 // for (int i = 0; i < ndof; ++i)
272 // {
273 // std::cout << i << "\t" << deltaV_normal[i] << '\n';
274 // }
275
276 if (impulse_tangent.norm() > SIMD_EPSILON)
277 {
278 // apply tangential component of the impulse
280 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, deltaImpulse_tangent);
282 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, deltaImpulse_tangent2);
283 }
284 }
285 }
286 }
287 return residualSquare;
288}
289
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)
298{
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;
302
303 btScalar sum = appliedImpulse + deltaImpulse_tangent;
304 if (sum > upper_limit)
305 {
306 deltaImpulse_tangent = upper_limit - appliedImpulse;
307 appliedImpulse = upper_limit;
308 }
309 else if (sum < lower_limit)
310 {
311 deltaImpulse_tangent = lower_limit - appliedImpulse;
312 appliedImpulse = lower_limit;
313 }
314 else
315 {
316 appliedImpulse = sum;
317 }
318}
319
320// ================= node vs rigid constraints ===================
324 const btContactSolverInfo& infoGlobal,
325 btScalar dt)
326 : m_node(contact.m_node), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
327{
330
331 if (contact.m_node->index < rsb->m_nodes.size())
332 {
333 m_nodeQueryIndex = contact.m_node->index;
334 }
335 else
336 {
338 }
339
341 {
342 m_relPosA = contact.m_c1;
343 }
344 else
345 {
346 m_relPosA = btVector3(0,0,0);
347 }
349
350 if (m_collideStatic) // colliding with static object, only consider reduced deformable body's impulse factor
351 {
353 }
354 else // colliding with dynamic object, consider both reduced deformable and rigid body's impulse factors
355 {
357 }
358
361
362 warmStarting();
363}
364
366{
367 btVector3 va = getVa();
368 btVector3 vb = getVb();
371
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)
377 {
378 m_contactTangent = btVector3(0, 0, 0);
379 // tangent impulse factor
382 }
383 else
384 {
386 {
387 m_contactTangent = v_tangent.normalized();
389 // tangent impulse factor 1
392 // tangent impulse factor 2
395 }
396 else // multibody requires 2 contact directions
397 {
400
401 // tangent impulse factor 1
404 // tangent impulse factor 2
407 }
408 }
409
410
411 // initial guess for normal impulse
412 {
413 btScalar velocity_error = btDot(v_rel, m_contactNormalA); // magnitude of relative velocity
414 btScalar position_error = 0;
415 if (m_penetration > 0)
416 {
417 velocity_error += m_penetration / m_dt;
418 }
419 else
420 {
421 // add penetration correction vel
422 position_error = m_penetration * m_erp / m_dt;
423 }
424 // get the initial estimate of impulse magnitude to be applied
425 m_rhs = -(velocity_error + position_error) / m_normalImpulseFactor;
426 }
427
428 // initial guess for tangential impulse
429 {
430 btScalar velocity_error = btDot(v_rel, m_contactTangent);
431 m_rhs_tangent = velocity_error * m_tangentImpulseFactorInv;
432
434 {
435 btScalar velocity_error2 = btDot(v_rel, m_contactTangent2);
436 m_rhs_tangent2 = velocity_error2 * m_tangentImpulseFactorInv2;
437 }
438 }
439
440 // warm starting
441 // applyImpulse(m_rhs * m_contactNormalA);
442 // if (!m_collideStatic)
443 // {
444 // const btSoftBody::sCti& cti = m_contact->m_cti;
445 // if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
446 // {
447 // m_solverBody->internalApplyImpulse(m_linearComponentNormal, m_angularComponentNormal, -m_rhs);
448 // }
449 // }
450}
451
453{
454 return m_node->m_v;
455}
456
458{
459 btVector3 deltaVa(0, 0, 0);
460 if (!m_collideStatic)
461 {
462 if (!m_collideMultibody) // for rigid body
463 {
465 }
466 else // for multibody
467 {
468 btMultiBodyLinkCollider* multibodyLinkCol = 0;
470 if (multibodyLinkCol)
471 {
472 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
476 const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
477 // add in the normal component of the va
478 btScalar vel = 0;
479 for (int k = 0; k < ndof; ++k)
480 {
481 vel += local_dv[k] * J_n[k];
482 }
483 deltaVa = m_contact->m_cti.m_normal * vel;
484
485 // add in the tangential components of the va
486 vel = 0;
487 for (int k = 0; k < ndof; ++k)
488 {
489 vel += local_dv[k] * J_t1[k];
490 }
491 deltaVa += m_contact->t1 * vel;
492
493 vel = 0;
494 for (int k = 0; k < ndof; ++k)
495 {
496 vel += local_dv[k] * J_t2[k];
497 }
498 deltaVa += m_contact->t2 * vel;
499 }
500 }
501 }
502 return deltaVa;
503}
504
506{
507 // std::cout << "node: " << m_node->index << '\n';
509}
510
512{
513 return m_node->m_splitv;
514}
515
517{
519}
520
522{
524 // m_rsb->applyFullSpaceImpulse(impulse, m_relPosB, m_node->index, m_dt);
525 // m_rsb->mapToFullVelocity(m_rsb->getInterpolationWorldTransform());
526 // if (!m_collideStatic)
527 // {
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';
532 // }
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';
534}
535
536// ================= face vs rigid constraints ===================
540 const btContactSolverInfo& infoGlobal,
541 btScalar dt,
542 bool useStrainLimiting)
543 : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
544{}
545
547{
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];
550 return vb;
551}
552
554{
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];
557 return vb;
558}
559
561{
564 if (m_face->m_n[0] == node)
565 {
566 return face_dv * contact->m_weights[0];
567 }
568 if (m_face->m_n[1] == node)
569 {
570 return face_dv * contact->m_weights[1];
571 }
572 btAssert(node == m_face->m_n[2]);
573 return face_dv * contact->m_weights[2];
574}
575
577{
578 //
579}
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:888
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:153
static T sum(const btAlignedObjectArray< T > &items)
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
int size() const
return the number of elements in the array
int getInternalType() const
reserved for Bullet internal usage
bool isStaticObject() const
const btTransform & getInterpolationWorldTransform() const
const btSoftBody::DeformableRigidContact * m_contact
static btMultiBodyLinkCollider * upcast(btCollisionObject *colObj)
const btScalar * getDeltaVelocityVector() const
Definition: btMultiBody.h:307
int getNumDofs() const
Definition: btMultiBody.h:167
void applyDeltaVeeMultiDof2(const btScalar *delta_vee, btScalar multiplier)
Definition: btMultiBody.h:428
virtual btMatrix3x3 getImpulseFactor(int n_node)
const btVector3 internalComputeNodeDeltaVelocity(const btTransform &ref_trans, int n_node) const
void internalApplyFullSpaceImpulse(const btVector3 &impulse, const btVector3 &rel_pos, int n_node, btScalar dt)
virtual btVector3 getDv(const btSoftBody::Node *) const
const btSoftBody::DeformableFaceRigidContact * getContact() const
virtual btVector3 getDv(const btSoftBody::Node *) const
virtual btScalar solveConstraint(const btContactSolverInfo &infoGlobal)
void setSolverBody(const int bodyId, btSolverBody &solver_body)
void calculateTangentialImpulse(btScalar &deltaImpulse_tangent, btScalar &appliedImpulse, const btScalar rhs_tangent, const btScalar tangentImpulseFactorInv, const btVector3 &tangent, const btScalar lower_limit, const btScalar upper_limit, const btVector3 &deltaV_rel)
virtual btVector3 getDeltaVb() const =0
virtual btVector3 getDeltaVa() const =0
virtual void applyImpulse(const btVector3 &impulse)
virtual btScalar solveConstraint(const btContactSolverInfo &infoGlobal)
const btMatrix3x3 & getInvInertiaTensorWorld() const
Definition: btRigidBody.h:265
btMultiBodyJacobianData jacobianData_t1
Definition: btSoftBody.h:372
btMultiBodyJacobianData jacobianData_normal
Definition: btSoftBody.h:371
btMultiBodyJacobianData jacobianData_t2
Definition: btSoftBody.h:373
tNodeArray m_nodes
Definition: btSoftBody.h:814
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:114
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:380
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:949
void setZero()
Definition: btVector3.h:671
btAlignedObjectArray< btScalar > m_deltaVelocitiesUnitImpulse
btAlignedObjectArray< btScalar > m_jacobians
Node * m_n[3]
Definition: btSoftBody.h:307
btVector3 m_x
Definition: btSoftBody.h:269
btVector3 m_splitv
Definition: btSoftBody.h:281
btVector3 m_v
Definition: btSoftBody.h:271
const btCollisionObject * m_colObj
Definition: btSoftBody.h:226
btVector3 m_normal
Definition: btSoftBody.h:227
The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packe...
Definition: btSolverBody.h:105
btVector3 & internalGetDeltaAngularVelocity()
Definition: btSolverBody.h:202
btRigidBody * m_originalBody
Definition: btSolverBody.h:120
btVector3 & internalGetDeltaLinearVelocity()
some internal methods, don't use them
Definition: btSolverBody.h:197
void internalApplyImpulse(const btVector3 &linearComponent, const btVector3 &angularComponent, const btScalar impulseMagnitude)
Definition: btSolverBody.h:243
const btVector3 & internalGetInvMass() const
Definition: btSolverBody.h:212