Bullet Collision Detection & Physics Library
btMultiBodyConstraintSolver.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
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.
14 */
15 
16 
20 
22 #include "btMultiBodyConstraint.h"
24 
25 #include "LinearMath/btQuickprof.h"
26 
27 btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
28 {
29  btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
30 
31  //solve featherstone non-contact constraints
32 
33  //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
34 
35  for (int j=0;j<m_multiBodyNonContactConstraints.size();j++)
36  {
37  int index = iteration&1? j : m_multiBodyNonContactConstraints.size()-1-j;
38 
40 
41  btScalar residual = resolveSingleConstraintRowGeneric(constraint);
42  leastSquaredResidual = btMax(leastSquaredResidual,residual*residual);
43 
44  if(constraint.m_multiBodyA)
45  constraint.m_multiBodyA->setPosUpdated(false);
46  if(constraint.m_multiBodyB)
47  constraint.m_multiBodyB->setPosUpdated(false);
48  }
49 
50  //solve featherstone normal contact
51  for (int j0=0;j0<m_multiBodyNormalContactConstraints.size();j0++)
52  {
53  int index = j0;//iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
54 
56  btScalar residual = 0.f;
57 
58  if (iteration < infoGlobal.m_numIterations)
59  {
60  residual = resolveSingleConstraintRowGeneric(constraint);
61  }
62 
63  leastSquaredResidual = btMax(leastSquaredResidual,residual*residual);
64 
65  if(constraint.m_multiBodyA)
66  constraint.m_multiBodyA->setPosUpdated(false);
67  if(constraint.m_multiBodyB)
68  constraint.m_multiBodyB->setPosUpdated(false);
69  }
70 
71  //solve featherstone frictional contact
73  {
74  for (int j1 = 0; j1<this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
75  {
76  if (iteration < infoGlobal.m_numIterations)
77  {
78  int index = j1;//iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
79 
81  btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
82  //adjust friction limits here
83  if (totalImpulse>btScalar(0))
84  {
85  frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
86  frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
87  btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
88  leastSquaredResidual = btMax(leastSquaredResidual , residual*residual);
89 
90  if (frictionConstraint.m_multiBodyA)
91  frictionConstraint.m_multiBodyA->setPosUpdated(false);
92  if (frictionConstraint.m_multiBodyB)
93  frictionConstraint.m_multiBodyB->setPosUpdated(false);
94  }
95  }
96  }
97 
98  for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
99  {
100  if (iteration < infoGlobal.m_numIterations)
101  {
102  int index = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
104 
105  btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
106  j1++;
107  int index2 = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
109  btAssert(frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex);
110 
111  if (frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
112  {
113  frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
114  frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
115  frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction*totalImpulse);
116  frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction*totalImpulse;
117  btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
118  leastSquaredResidual = btMax(leastSquaredResidual, residual*residual);
119 
120  if (frictionConstraintB.m_multiBodyA)
121  frictionConstraintB.m_multiBodyA->setPosUpdated(false);
122  if (frictionConstraintB.m_multiBodyB)
123  frictionConstraintB.m_multiBodyB->setPosUpdated(false);
124 
125  if (frictionConstraint.m_multiBodyA)
126  frictionConstraint.m_multiBodyA->setPosUpdated(false);
127  if (frictionConstraint.m_multiBodyB)
128  frictionConstraint.m_multiBodyB->setPosUpdated(false);
129  }
130  }
131  }
132 
133 
134  }
135  else
136  {
137  for (int j1 = 0; j1<this->m_multiBodyFrictionContactConstraints.size(); j1++)
138  {
139  if (iteration < infoGlobal.m_numIterations)
140  {
141  int index = j1;//iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
142 
144  btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
145  //adjust friction limits here
146  if (totalImpulse>btScalar(0))
147  {
148  frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction*totalImpulse);
149  frictionConstraint.m_upperLimit = frictionConstraint.m_friction*totalImpulse;
150  btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
151  leastSquaredResidual = btMax(leastSquaredResidual, residual*residual);
152 
153  if (frictionConstraint.m_multiBodyA)
154  frictionConstraint.m_multiBodyA->setPosUpdated(false);
155  if (frictionConstraint.m_multiBodyB)
156  frictionConstraint.m_multiBodyB->setPosUpdated(false);
157  }
158  }
159  }
160  }
161  return leastSquaredResidual;
162 }
163 
164 btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
165 {
170 
174 
175  for (int i=0;i<numBodies;i++)
176  {
178  if (fcA)
179  {
180  fcA->m_multiBody->setCompanionId(-1);
181  }
182  }
183 
184  btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer);
185 
186  return val;
187 }
188 
189 void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
190 {
191  for (int i = 0; i < ndof; ++i)
192  m_data.m_deltaVelocities[velocityIndex+i] += delta_vee[i] * impulse;
193 }
194 
196 {
197 
198  btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
199  btScalar deltaVelADotn = 0;
200  btScalar deltaVelBDotn = 0;
201  btSolverBody* bodyA = 0;
202  btSolverBody* bodyB = 0;
203  int ndofA = 0;
204  int ndofB = 0;
205 
206  if (c.m_multiBodyA)
207  {
208  ndofA = c.m_multiBodyA->getNumDofs() + 6;
209  for (int i = 0; i < ndofA; ++i)
210  deltaVelADotn += m_data.m_jacobians[c.m_jacAindex + i] * m_data.m_deltaVelocities[c.m_deltaVelAindex + i];
211  }
212  else if (c.m_solverBodyIdA >= 0)
213  {
216  }
217 
218  if (c.m_multiBodyB)
219  {
220  ndofB = c.m_multiBodyB->getNumDofs() + 6;
221  for (int i = 0; i < ndofB; ++i)
222  deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex + i] * m_data.m_deltaVelocities[c.m_deltaVelBindex + i];
223  }
224  else if (c.m_solverBodyIdB >= 0)
225  {
228  }
229 
230 
231  deltaImpulse -= deltaVelADotn*c.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
232  deltaImpulse -= deltaVelBDotn*c.m_jacDiagABInv;
233  const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
234 
235  if (sum < c.m_lowerLimit)
236  {
237  deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
239  }
240  else if (sum > c.m_upperLimit)
241  {
242  deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
244  }
245  else
246  {
247  c.m_appliedImpulse = sum;
248  }
249 
250  if (c.m_multiBodyA)
251  {
253 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
254  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
255  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
257 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
258  }
259  else if (c.m_solverBodyIdA >= 0)
260  {
262 
263  }
264  if (c.m_multiBodyB)
265  {
267 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
268  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
269  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
271 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
272  }
273  else if (c.m_solverBodyIdB >= 0)
274  {
276  }
277  btScalar deltaVel =deltaImpulse/c.m_jacDiagABInv;
278  return deltaVel;
279 }
280 
281 
283 {
284  int ndofA=0;
285  int ndofB=0;
286  btSolverBody* bodyA = 0;
287  btSolverBody* bodyB = 0;
288  btScalar deltaImpulseB = 0.f;
289  btScalar sumB = 0.f;
290  {
291  deltaImpulseB = cB.m_rhs-btScalar(cB.m_appliedImpulse)*cB.m_cfm;
292  btScalar deltaVelADotn=0;
293  btScalar deltaVelBDotn=0;
294  if (cB.m_multiBodyA)
295  {
296  ndofA = cB.m_multiBodyA->getNumDofs() + 6;
297  for (int i = 0; i < ndofA; ++i)
299  } else if(cB.m_solverBodyIdA >= 0)
300  {
303  }
304 
305  if (cB.m_multiBodyB)
306  {
307  ndofB = cB.m_multiBodyB->getNumDofs() + 6;
308  for (int i = 0; i < ndofB; ++i)
310  } else if(cB.m_solverBodyIdB >= 0)
311  {
314  }
315 
316 
317  deltaImpulseB -= deltaVelADotn*cB.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
318  deltaImpulseB -= deltaVelBDotn*cB.m_jacDiagABInv;
319  sumB = btScalar(cB.m_appliedImpulse) + deltaImpulseB;
320  }
321 
322  btScalar deltaImpulseA = 0.f;
323  btScalar sumA = 0.f;
324  const btMultiBodySolverConstraint& cA = cA1;
325  {
326  {
327  deltaImpulseA = cA.m_rhs-btScalar(cA.m_appliedImpulse)*cA.m_cfm;
328  btScalar deltaVelADotn=0;
329  btScalar deltaVelBDotn=0;
330  if (cA.m_multiBodyA)
331  {
332  ndofA = cA.m_multiBodyA->getNumDofs() + 6;
333  for (int i = 0; i < ndofA; ++i)
335  } else if(cA.m_solverBodyIdA >= 0)
336  {
339  }
340 
341  if (cA.m_multiBodyB)
342  {
343  ndofB = cA.m_multiBodyB->getNumDofs() + 6;
344  for (int i = 0; i < ndofB; ++i)
346  } else if(cA.m_solverBodyIdB >= 0)
347  {
350  }
351 
352 
353  deltaImpulseA -= deltaVelADotn*cA.m_jacDiagABInv;//m_jacDiagABInv = 1./denom
354  deltaImpulseA -= deltaVelBDotn*cA.m_jacDiagABInv;
355  sumA = btScalar(cA.m_appliedImpulse) + deltaImpulseA;
356  }
357  }
358 
359  if (sumA*sumA+sumB*sumB>=cA.m_lowerLimit*cB.m_lowerLimit)
360  {
361  btScalar angle = btAtan2(sumA,sumB);
362  btScalar sumAclipped = btFabs(cA.m_lowerLimit*btSin(angle));
363  btScalar sumBclipped = btFabs(cB.m_lowerLimit*btCos(angle));
364 
365 
366  if (sumA < -sumAclipped)
367  {
368  deltaImpulseA = -sumAclipped - cA.m_appliedImpulse;
369  cA.m_appliedImpulse = -sumAclipped;
370  }
371  else if (sumA > sumAclipped)
372  {
373  deltaImpulseA = sumAclipped - cA.m_appliedImpulse;
374  cA.m_appliedImpulse = sumAclipped;
375  }
376  else
377  {
378  cA.m_appliedImpulse = sumA;
379  }
380 
381  if (sumB < -sumBclipped)
382  {
383  deltaImpulseB = -sumBclipped - cB.m_appliedImpulse;
384  cB.m_appliedImpulse = -sumBclipped;
385  }
386  else if (sumB > sumBclipped)
387  {
388  deltaImpulseB = sumBclipped - cB.m_appliedImpulse;
389  cB.m_appliedImpulse = sumBclipped;
390  }
391  else
392  {
393  cB.m_appliedImpulse = sumB;
394  }
395  //deltaImpulseA = sumAclipped-cA.m_appliedImpulse;
396  //cA.m_appliedImpulse = sumAclipped;
397  //deltaImpulseB = sumBclipped-cB.m_appliedImpulse;
398  //cB.m_appliedImpulse = sumBclipped;
399  }
400  else
401  {
402  cA.m_appliedImpulse = sumA;
403  cB.m_appliedImpulse = sumB;
404  }
405 
406  if (cA.m_multiBodyA)
407  {
409 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
410  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
411  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
413 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
414  } else if(cA.m_solverBodyIdA >= 0)
415  {
417 
418  }
419  if (cA.m_multiBodyB)
420  {
422 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
423  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
424  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
426 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
427  } else if(cA.m_solverBodyIdB >= 0)
428  {
430  }
431 
432  if (cB.m_multiBodyA)
433  {
435 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
436  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
437  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
439 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
440  } else if(cB.m_solverBodyIdA >= 0)
441  {
443  }
444  if (cB.m_multiBodyB)
445  {
447 #ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
448  //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
449  //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
451 #endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
452  } else if(cB.m_solverBodyIdB >= 0)
453  {
455  }
456 
457  btScalar deltaVel =deltaImpulseA/cA.m_jacDiagABInv+deltaImpulseB/cB.m_jacDiagABInv;
458  return deltaVel;
459 }
460 
461 
462 
463 
465  const btVector3& contactNormal,
466  btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
467  btScalar& relaxation,
468  bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
469 {
470 
471  BT_PROFILE("setupMultiBodyContactConstraint");
472  btVector3 rel_pos1;
473  btVector3 rel_pos2;
474 
475  btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
476  btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
477 
478  const btVector3& pos1 = cp.getPositionWorldOnA();
479  const btVector3& pos2 = cp.getPositionWorldOnB();
480 
481  btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
482  btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
483 
484  btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
485  btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
486 
487  if (bodyA)
488  rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
489  if (bodyB)
490  rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
491 
492  relaxation = infoGlobal.m_sor;
493 
494  btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
495 
496  //cfm = 1 / ( dt * kp + kd )
497  //erp = dt * kp / ( dt * kp + kd )
498 
499  btScalar cfm;
500  btScalar erp;
501  if (isFriction)
502  {
503  cfm = infoGlobal.m_frictionCFM;
504  erp = infoGlobal.m_frictionERP;
505  } else
506  {
507  cfm = infoGlobal.m_globalCfm;
508  erp = infoGlobal.m_erp2;
509 
511  {
513  cfm = cp.m_contactCFM;
515  erp = cp.m_contactERP;
516  } else
517  {
519  {
521  if (denom < SIMD_EPSILON)
522  {
523  denom = SIMD_EPSILON;
524  }
525  cfm = btScalar(1) / denom;
526  erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
527  }
528  }
529  }
530 
531  cfm *= invTimeStep;
532 
533  if (multiBodyA)
534  {
535  if (solverConstraint.m_linkA<0)
536  {
537  rel_pos1 = pos1 - multiBodyA->getBasePos();
538  } else
539  {
540  rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
541  }
542  const int ndofA = multiBodyA->getNumDofs() + 6;
543 
544  solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
545 
546  if (solverConstraint.m_deltaVelAindex <0)
547  {
548  solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
549  multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
551  } else
552  {
553  btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
554  }
555 
556  solverConstraint.m_jacAindex = m_data.m_jacobians.size();
560 
561  btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
562  multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
563  btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
565 
566  btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
567  solverConstraint.m_relpos1CrossNormal = torqueAxis0;
568  solverConstraint.m_contactNormal1 = contactNormal;
569  } else
570  {
571  btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
572  solverConstraint.m_relpos1CrossNormal = torqueAxis0;
573  solverConstraint.m_contactNormal1 = contactNormal;
574  solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
575  }
576 
577 
578 
579  if (multiBodyB)
580  {
581  if (solverConstraint.m_linkB<0)
582  {
583  rel_pos2 = pos2 - multiBodyB->getBasePos();
584  } else
585  {
586  rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
587  }
588 
589  const int ndofB = multiBodyB->getNumDofs() + 6;
590 
591  solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
592  if (solverConstraint.m_deltaVelBindex <0)
593  {
594  solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
595  multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
597  }
598 
599  solverConstraint.m_jacBindex = m_data.m_jacobians.size();
600 
604 
605  multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
607 
608  btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
609  solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
610  solverConstraint.m_contactNormal2 = -contactNormal;
611 
612  } else
613  {
614  btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
615  solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
616  solverConstraint.m_contactNormal2 = -contactNormal;
617 
618  solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
619  }
620 
621  {
622 
623  btVector3 vec;
624  btScalar denom0 = 0.f;
625  btScalar denom1 = 0.f;
626  btScalar* jacB = 0;
627  btScalar* jacA = 0;
628  btScalar* lambdaA =0;
629  btScalar* lambdaB =0;
630  int ndofA = 0;
631  if (multiBodyA)
632  {
633  ndofA = multiBodyA->getNumDofs() + 6;
634  jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
635  lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
636  for (int i = 0; i < ndofA; ++i)
637  {
638  btScalar j = jacA[i] ;
639  btScalar l =lambdaA[i];
640  denom0 += j*l;
641  }
642  } else
643  {
644  if (rb0)
645  {
646  vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
647  denom0 = rb0->getInvMass() + contactNormal.dot(vec);
648  }
649  }
650  if (multiBodyB)
651  {
652  const int ndofB = multiBodyB->getNumDofs() + 6;
653  jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
654  lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
655  for (int i = 0; i < ndofB; ++i)
656  {
657  btScalar j = jacB[i] ;
658  btScalar l =lambdaB[i];
659  denom1 += j*l;
660  }
661 
662  } else
663  {
664  if (rb1)
665  {
666  vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
667  denom1 = rb1->getInvMass() + contactNormal.dot(vec);
668  }
669  }
670 
671 
672 
673  btScalar d = denom0+denom1+cfm;
674  if (d>SIMD_EPSILON)
675  {
676  solverConstraint.m_jacDiagABInv = relaxation/(d);
677  } else
678  {
679  //disable the constraint row to handle singularity/redundant constraint
680  solverConstraint.m_jacDiagABInv = 0.f;
681  }
682 
683  }
684 
685 
686  //compute rhs and remaining solverConstraint fields
687 
688 
689 
690  btScalar restitution = 0.f;
691  btScalar distance = 0;
692  if (!isFriction)
693  {
694  distance = cp.getDistance()+infoGlobal.m_linearSlop;
695  } else
696  {
698  {
699  distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
700  }
701  }
702 
703 
704  btScalar rel_vel = 0.f;
705  int ndofA = 0;
706  int ndofB = 0;
707  {
708 
709  btVector3 vel1,vel2;
710  if (multiBodyA)
711  {
712  ndofA = multiBodyA->getNumDofs() + 6;
713  btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
714  for (int i = 0; i < ndofA ; ++i)
715  rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
716  } else
717  {
718  if (rb0)
719  {
720  rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
721  (rb0->getTotalTorque()*rb0->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos1)+
722  rb0->getTotalForce()*rb0->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal1);
723  }
724  }
725  if (multiBodyB)
726  {
727  ndofB = multiBodyB->getNumDofs() + 6;
728  btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
729  for (int i = 0; i < ndofB ; ++i)
730  rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
731 
732  } else
733  {
734  if (rb1)
735  {
736  rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2)+
737  (rb1->getTotalTorque()*rb1->getInvInertiaTensorWorld()*infoGlobal.m_timeStep).cross(rel_pos2) +
738  rb1->getTotalForce()*rb1->getInvMass()*infoGlobal.m_timeStep).dot(solverConstraint.m_contactNormal2);
739  }
740  }
741 
742  solverConstraint.m_friction = cp.m_combinedFriction;
743 
744  if(!isFriction)
745  {
746  restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
747  if (restitution <= btScalar(0.))
748  {
749  restitution = 0.f;
750  }
751  }
752  }
753 
754 
756  //disable warmstarting for btMultiBody, it has issues gaining energy (==explosion)
757  if (0)//infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
758  {
759  solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
760 
761  if (solverConstraint.m_appliedImpulse)
762  {
763  if (multiBodyA)
764  {
765  btScalar impulse = solverConstraint.m_appliedImpulse;
766  btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
767  multiBodyA->applyDeltaVeeMultiDof(deltaV,impulse);
768 
769  applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelAindex,ndofA);
770  } else
771  {
772  if (rb0)
773  bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
774  }
775  if (multiBodyB)
776  {
777  btScalar impulse = solverConstraint.m_appliedImpulse;
778  btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
779  multiBodyB->applyDeltaVeeMultiDof(deltaV,impulse);
780  applyDeltaVee(deltaV,impulse,solverConstraint.m_deltaVelBindex,ndofB);
781  } else
782  {
783  if (rb1)
784  bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
785  }
786  }
787  } else
788  {
789  solverConstraint.m_appliedImpulse = 0.f;
790  }
791 
792  solverConstraint.m_appliedPushImpulse = 0.f;
793 
794  {
795 
796  btScalar positionalError = 0.f;
797  btScalar velocityError = restitution - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
798  if (isFriction)
799  {
800  positionalError = -distance * erp/infoGlobal.m_timeStep;
801  } else
802  {
803  if (distance>0)
804  {
805  positionalError = 0;
806  velocityError -= distance / infoGlobal.m_timeStep;
807 
808  } else
809  {
810  positionalError = -distance * erp/infoGlobal.m_timeStep;
811  }
812  }
813 
814  btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
815  btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
816 
817  if(!isFriction)
818  {
819  // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
820  {
821  //combine position and velocity into rhs
822  solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
823  solverConstraint.m_rhsPenetration = 0.f;
824 
825  }
826  /*else
827  {
828  //split position and velocity into rhs and m_rhsPenetration
829  solverConstraint.m_rhs = velocityImpulse;
830  solverConstraint.m_rhsPenetration = penetrationImpulse;
831  }
832  */
833  solverConstraint.m_lowerLimit = 0;
834  solverConstraint.m_upperLimit = 1e10f;
835  }
836  else
837  {
838  solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
839  solverConstraint.m_rhsPenetration = 0.f;
840  solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
841  solverConstraint.m_upperLimit = solverConstraint.m_friction;
842  }
843 
844  solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
845 
846 
847 
848  }
849 
850 }
851 
853  const btVector3& constraintNormal,
854  btManifoldPoint& cp,
855  btScalar combinedTorsionalFriction,
856  const btContactSolverInfo& infoGlobal,
857  btScalar& relaxation,
858  bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
859 {
860 
861  BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
862  btVector3 rel_pos1;
863  btVector3 rel_pos2;
864 
865  btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
866  btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
867 
868  const btVector3& pos1 = cp.getPositionWorldOnA();
869  const btVector3& pos2 = cp.getPositionWorldOnB();
870 
871  btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
872  btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
873 
874  btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
875  btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
876 
877  if (bodyA)
878  rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
879  if (bodyB)
880  rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
881 
882  relaxation = infoGlobal.m_sor;
883 
884  // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
885 
886 
887  if (multiBodyA)
888  {
889  if (solverConstraint.m_linkA<0)
890  {
891  rel_pos1 = pos1 - multiBodyA->getBasePos();
892  } else
893  {
894  rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
895  }
896  const int ndofA = multiBodyA->getNumDofs() + 6;
897 
898  solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
899 
900  if (solverConstraint.m_deltaVelAindex <0)
901  {
902  solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
903  multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
905  } else
906  {
907  btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
908  }
909 
910  solverConstraint.m_jacAindex = m_data.m_jacobians.size();
914 
915  btScalar* jac1=&m_data.m_jacobians[solverConstraint.m_jacAindex];
916  multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0,0,0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
917  btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
919 
920  btVector3 torqueAxis0 = -constraintNormal;
921  solverConstraint.m_relpos1CrossNormal = torqueAxis0;
922  solverConstraint.m_contactNormal1 = btVector3(0,0,0);
923  } else
924  {
925  btVector3 torqueAxis0 = -constraintNormal;
926  solverConstraint.m_relpos1CrossNormal = torqueAxis0;
927  solverConstraint.m_contactNormal1 = btVector3(0,0,0);
928  solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
929  }
930 
931 
932 
933  if (multiBodyB)
934  {
935  if (solverConstraint.m_linkB<0)
936  {
937  rel_pos2 = pos2 - multiBodyB->getBasePos();
938  } else
939  {
940  rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
941  }
942 
943  const int ndofB = multiBodyB->getNumDofs() + 6;
944 
945  solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
946  if (solverConstraint.m_deltaVelBindex <0)
947  {
948  solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
949  multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
951  }
952 
953  solverConstraint.m_jacBindex = m_data.m_jacobians.size();
954 
958 
959  multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0,0,0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
961 
962  btVector3 torqueAxis1 = constraintNormal;
963  solverConstraint.m_relpos2CrossNormal = torqueAxis1;
964  solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
965 
966  } else
967  {
968  btVector3 torqueAxis1 = constraintNormal;
969  solverConstraint.m_relpos2CrossNormal = torqueAxis1;
970  solverConstraint.m_contactNormal2 = -btVector3(0,0,0);
971 
972  solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
973  }
974 
975  {
976 
977  btScalar denom0 = 0.f;
978  btScalar denom1 = 0.f;
979  btScalar* jacB = 0;
980  btScalar* jacA = 0;
981  btScalar* lambdaA =0;
982  btScalar* lambdaB =0;
983  int ndofA = 0;
984  if (multiBodyA)
985  {
986  ndofA = multiBodyA->getNumDofs() + 6;
987  jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
988  lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
989  for (int i = 0; i < ndofA; ++i)
990  {
991  btScalar j = jacA[i] ;
992  btScalar l =lambdaA[i];
993  denom0 += j*l;
994  }
995  } else
996  {
997  if (rb0)
998  {
999  btVector3 iMJaA = rb0?rb0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
1000  denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
1001  }
1002  }
1003  if (multiBodyB)
1004  {
1005  const int ndofB = multiBodyB->getNumDofs() + 6;
1006  jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
1007  lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
1008  for (int i = 0; i < ndofB; ++i)
1009  {
1010  btScalar j = jacB[i] ;
1011  btScalar l =lambdaB[i];
1012  denom1 += j*l;
1013  }
1014 
1015  } else
1016  {
1017  if (rb1)
1018  {
1019  btVector3 iMJaB = rb1?rb1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
1020  denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
1021  }
1022  }
1023 
1024 
1025 
1026  btScalar d = denom0+denom1+infoGlobal.m_globalCfm;
1027  if (d>SIMD_EPSILON)
1028  {
1029  solverConstraint.m_jacDiagABInv = relaxation/(d);
1030  } else
1031  {
1032  //disable the constraint row to handle singularity/redundant constraint
1033  solverConstraint.m_jacDiagABInv = 0.f;
1034  }
1035 
1036  }
1037 
1038 
1039  //compute rhs and remaining solverConstraint fields
1040 
1041 
1042 
1043  btScalar restitution = 0.f;
1044  btScalar penetration = isFriction? 0 : cp.getDistance();
1045 
1046  btScalar rel_vel = 0.f;
1047  int ndofA = 0;
1048  int ndofB = 0;
1049  {
1050 
1051  btVector3 vel1,vel2;
1052  if (multiBodyA)
1053  {
1054  ndofA = multiBodyA->getNumDofs() + 6;
1055  btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
1056  for (int i = 0; i < ndofA ; ++i)
1057  rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
1058  } else
1059  {
1060  if (rb0)
1061  {
1062  btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
1063  rel_vel += solverConstraint.m_contactNormal1.dot(rb0?solverBodyA->m_linearVelocity+solverBodyA->m_externalForceImpulse:btVector3(0,0,0))
1064  + solverConstraint.m_relpos1CrossNormal.dot(rb0?solverBodyA->m_angularVelocity:btVector3(0,0,0));
1065 
1066  }
1067  }
1068  if (multiBodyB)
1069  {
1070  ndofB = multiBodyB->getNumDofs() + 6;
1071  btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
1072  for (int i = 0; i < ndofB ; ++i)
1073  rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
1074 
1075  } else
1076  {
1077  if (rb1)
1078  {
1079  btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
1080  rel_vel += solverConstraint.m_contactNormal2.dot(rb1?solverBodyB->m_linearVelocity+solverBodyB->m_externalForceImpulse:btVector3(0,0,0))
1081  + solverConstraint.m_relpos2CrossNormal.dot(rb1?solverBodyB->m_angularVelocity:btVector3(0,0,0));
1082 
1083  }
1084  }
1085 
1086  solverConstraint.m_friction =combinedTorsionalFriction;
1087 
1088  if(!isFriction)
1089  {
1090  restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
1091  if (restitution <= btScalar(0.))
1092  {
1093  restitution = 0.f;
1094  }
1095  }
1096  }
1097 
1098 
1099  solverConstraint.m_appliedImpulse = 0.f;
1100  solverConstraint.m_appliedPushImpulse = 0.f;
1101 
1102  {
1103 
1104  btScalar velocityError = 0 - rel_vel;// * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
1105 
1106 
1107 
1108  btScalar velocityImpulse = velocityError*solverConstraint.m_jacDiagABInv;
1109 
1110  solverConstraint.m_rhs = velocityImpulse;
1111  solverConstraint.m_rhsPenetration = 0.f;
1112  solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
1113  solverConstraint.m_upperLimit = solverConstraint.m_friction;
1114 
1115  solverConstraint.m_cfm = infoGlobal.m_globalCfm*solverConstraint.m_jacDiagABInv;
1116 
1117 
1118 
1119  }
1120 
1121 }
1122 
1124 {
1125  BT_PROFILE("addMultiBodyFrictionConstraint");
1127  solverConstraint.m_orgConstraint = 0;
1128  solverConstraint.m_orgDofIndex = -1;
1129 
1130  solverConstraint.m_frictionIndex = frictionIndex;
1131  bool isFriction = true;
1132 
1135 
1136  btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
1137  btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
1138 
1139  int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
1140  int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
1141 
1142  solverConstraint.m_solverBodyIdA = solverBodyIdA;
1143  solverConstraint.m_solverBodyIdB = solverBodyIdB;
1144  solverConstraint.m_multiBodyA = mbA;
1145  if (mbA)
1146  solverConstraint.m_linkA = fcA->m_link;
1147 
1148  solverConstraint.m_multiBodyB = mbB;
1149  if (mbB)
1150  solverConstraint.m_linkB = fcB->m_link;
1151 
1152  solverConstraint.m_originalContactPoint = &cp;
1153 
1154  setupMultiBodyContactConstraint(solverConstraint, normalAxis, cp, infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
1155  return solverConstraint;
1156 }
1157 
1159  btScalar combinedTorsionalFriction,
1160  btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
1161 {
1162  BT_PROFILE("addMultiBodyRollingFrictionConstraint");
1163 
1164  bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode&SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
1165 
1167  solverConstraint.m_orgConstraint = 0;
1168  solverConstraint.m_orgDofIndex = -1;
1169 
1170  solverConstraint.m_frictionIndex = frictionIndex;
1171  bool isFriction = true;
1172 
1175 
1176  btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
1177  btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
1178 
1179  int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
1180  int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
1181 
1182  solverConstraint.m_solverBodyIdA = solverBodyIdA;
1183  solverConstraint.m_solverBodyIdB = solverBodyIdB;
1184  solverConstraint.m_multiBodyA = mbA;
1185  if (mbA)
1186  solverConstraint.m_linkA = fcA->m_link;
1187 
1188  solverConstraint.m_multiBodyB = mbB;
1189  if (mbB)
1190  solverConstraint.m_linkB = fcB->m_link;
1191 
1192  solverConstraint.m_originalContactPoint = &cp;
1193 
1194  setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction,infoGlobal,relaxation,isFriction, desiredVelocity, cfmSlip);
1195  return solverConstraint;
1196 }
1197 
1199 {
1202 
1203  btMultiBody* mbA = fcA? fcA->m_multiBody : 0;
1204  btMultiBody* mbB = fcB? fcB->m_multiBody : 0;
1205 
1206  btCollisionObject* colObj0=0,*colObj1=0;
1207 
1208  colObj0 = (btCollisionObject*)manifold->getBody0();
1209  colObj1 = (btCollisionObject*)manifold->getBody1();
1210 
1211  int solverBodyIdA = mbA? -1 : getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
1212  int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
1213 
1214 // btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
1215 // btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
1216 
1217 
1219 // if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
1220  // return;
1221 
1222  //only a single rollingFriction per manifold
1223  int rollingFriction=1;
1224 
1225  for (int j=0;j<manifold->getNumContacts();j++)
1226  {
1227 
1228  btManifoldPoint& cp = manifold->getContactPoint(j);
1229 
1230  if (cp.getDistance() <= manifold->getContactProcessingThreshold())
1231  {
1232 
1233  btScalar relaxation;
1234 
1235  int frictionIndex = m_multiBodyNormalContactConstraints.size();
1236 
1238 
1239  // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
1240  // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
1241  solverConstraint.m_orgConstraint = 0;
1242  solverConstraint.m_orgDofIndex = -1;
1243  solverConstraint.m_solverBodyIdA = solverBodyIdA;
1244  solverConstraint.m_solverBodyIdB = solverBodyIdB;
1245  solverConstraint.m_multiBodyA = mbA;
1246  if (mbA)
1247  solverConstraint.m_linkA = fcA->m_link;
1248 
1249  solverConstraint.m_multiBodyB = mbB;
1250  if (mbB)
1251  solverConstraint.m_linkB = fcB->m_link;
1252 
1253  solverConstraint.m_originalContactPoint = &cp;
1254 
1255  bool isFriction = false;
1256  setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB,cp, infoGlobal, relaxation, isFriction);
1257 
1258 // const btVector3& pos1 = cp.getPositionWorldOnA();
1259 // const btVector3& pos2 = cp.getPositionWorldOnB();
1260 
1262 #define ENABLE_FRICTION
1263 #ifdef ENABLE_FRICTION
1264  solverConstraint.m_frictionIndex = frictionIndex;
1265 
1270 
1281 
1285 
1286  if (rollingFriction > 0 )
1287  {
1288  if (cp.m_combinedSpinningFriction>0)
1289  {
1290  addMultiBodyTorsionalFrictionConstraint(cp.m_normalWorldOnB,manifold,frictionIndex,cp,cp.m_combinedSpinningFriction, colObj0,colObj1, relaxation,infoGlobal);
1291  }
1292  if (cp.m_combinedRollingFriction>0)
1293  {
1294 
1299 
1300  if (cp.m_lateralFrictionDir1.length()>0.001)
1301  addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
1302 
1303  if (cp.m_lateralFrictionDir2.length()>0.001)
1304  addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,cp.m_combinedRollingFriction, colObj0,colObj1, relaxation,infoGlobal);
1305  }
1306  rollingFriction--;
1307  }
1309  {/*
1310  cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
1311  btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
1312  if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
1313  {
1314  cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
1315  if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1316  {
1317  cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
1318  cp.m_lateralFrictionDir2.normalize();//??
1319  applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
1320  applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
1321  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
1322 
1323  }
1324 
1325  applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
1326  applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
1327  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
1328 
1329  } else
1330  */
1331  {
1332 
1333 
1336  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal);
1337 
1338 
1340  {
1343  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal);
1344  }
1345 
1347  {
1349  }
1350  }
1351 
1352  } else
1353  {
1354  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,manifold,frictionIndex,cp,colObj0,colObj1, relaxation,infoGlobal,cp.m_contactMotion1, cp.m_frictionCFM);
1355 
1357  addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,manifold,frictionIndex,cp,colObj0,colObj1, relaxation, infoGlobal,cp.m_contactMotion2, cp.m_frictionCFM);
1358 
1359  //setMultiBodyFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
1360  //todo:
1361  solverConstraint.m_appliedImpulse = 0.f;
1362  solverConstraint.m_appliedPushImpulse = 0.f;
1363  }
1364 
1365 
1366 #endif //ENABLE_FRICTION
1367 
1368  }
1369  }
1370 }
1371 
1372 void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
1373 {
1374  //btPersistentManifold* manifold = 0;
1375 
1376  for (int i=0;i<numManifolds;i++)
1377  {
1378  btPersistentManifold* manifold= manifoldPtr[i];
1381  if (!fcA && !fcB)
1382  {
1383  //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
1384  convertContact(manifold,infoGlobal);
1385  } else
1386  {
1387  convertMultiBodyContact(manifold,infoGlobal);
1388  }
1389  }
1390 
1391  //also convert the multibody constraints, if any
1392 
1393 
1394  for (int i=0;i<m_tmpNumMultiBodyConstraints;i++)
1395  {
1399 
1401  }
1402 
1403 }
1404 
1405 
1406 
1407 btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
1408 {
1409  //printf("btMultiBodyConstraintSolver::solveGroup: numBodies=%d, numConstraints=%d\n", numBodies, numConstraints);
1410  return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
1411 }
1412 
1413 #if 0
1414 static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodySolverConstraint& solverConstraint, int jacIndex, btMultiBody* mb, btScalar appliedImpulse)
1415 {
1416  if (appliedImpulse!=0 && mb->internalNeedsJointFeedback())
1417  {
1418  //todo: get rid of those temporary memory allocations for the joint feedback
1419  btAlignedObjectArray<btScalar> forceVector;
1420  int numDofsPlusBase = 6+mb->getNumDofs();
1421  forceVector.resize(numDofsPlusBase);
1422  for (int i=0;i<numDofsPlusBase;i++)
1423  {
1424  forceVector[i] = data.m_jacobians[jacIndex+i]*appliedImpulse;
1425  }
1427  output.resize(numDofsPlusBase);
1428  bool applyJointFeedback = true;
1429  mb->calcAccelerationDeltasMultiDof(&forceVector[0],&output[0],data.scratch_r,data.scratch_v,applyJointFeedback);
1430  }
1431 }
1432 #endif
1433 
1434 
1436 {
1437 #if 1
1438 
1439  //bod->addBaseForce(m_gravity * bod->getBaseMass());
1440  //bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
1441 
1442  if (c.m_orgConstraint)
1443  {
1445  }
1446 
1447 
1448  if (c.m_multiBodyA)
1449  {
1450 
1452  btVector3 force = c.m_contactNormal1*(c.m_appliedImpulse/deltaTime);
1453  btVector3 torque = c.m_relpos1CrossNormal*(c.m_appliedImpulse/deltaTime);
1454  if (c.m_linkA<0)
1455  {
1458  } else
1459  {
1461  //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
1463  }
1464  }
1465 
1466  if (c.m_multiBodyB)
1467  {
1468  {
1470  btVector3 force = c.m_contactNormal2*(c.m_appliedImpulse/deltaTime);
1471  btVector3 torque = c.m_relpos2CrossNormal*(c.m_appliedImpulse/deltaTime);
1472  if (c.m_linkB<0)
1473  {
1476  } else
1477  {
1478  {
1480  //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
1482  }
1483 
1484  }
1485  }
1486  }
1487 #endif
1488 
1489 #ifndef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
1490 
1491  if (c.m_multiBodyA)
1492  {
1494  }
1495 
1496  if (c.m_multiBodyB)
1497  {
1499  }
1500 #endif
1501 
1502 
1503 
1504 }
1505 
1507 {
1508  BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
1509  int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
1510 
1511 
1512  //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
1513  //or as applied force, so we can measure the joint reaction forces easier
1514  for (int i=0;i<numPoolConstraints;i++)
1515  {
1517  writeBackSolverBodyToMultiBody(solverConstraint,infoGlobal.m_timeStep);
1518 
1520 
1522  {
1524  }
1525  }
1526 
1527 
1528  for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
1529  {
1531  writeBackSolverBodyToMultiBody(solverConstraint,infoGlobal.m_timeStep);
1532  }
1533 
1534 
1535  if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
1536  {
1537  BT_PROFILE("warm starting write back");
1538  for (int j=0;j<numPoolConstraints;j++)
1539  {
1541  btManifoldPoint* pt = (btManifoldPoint*) solverConstraint.m_originalContactPoint;
1542  btAssert(pt);
1543  pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
1544  pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
1545 
1546  //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
1548  {
1549  pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse;
1550  }
1551  //do a callback here?
1552  }
1553  }
1554 #if 0
1555  //multibody joint feedback
1556  {
1557  BT_PROFILE("multi body joint feedback");
1558  for (int j=0;j<numPoolConstraints;j++)
1559  {
1561 
1562  //apply the joint feedback into all links of the btMultiBody
1563  //todo: double-check the signs of the applied impulse
1564 
1565  if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
1566  {
1567  applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
1568  }
1569  if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
1570  {
1571  applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
1572  }
1573 #if 0
1574  if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA->isMultiDof())
1575  {
1576  applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
1577  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacAindex,
1578  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA,
1579  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
1580 
1581  }
1582  if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB->isMultiDof())
1583  {
1584  applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
1585  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacBindex,
1586  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB,
1587  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
1588  }
1589 
1591  {
1592  if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA->isMultiDof())
1593  {
1594  applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
1595  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacAindex,
1596  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA,
1597  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
1598  }
1599 
1600  if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB->isMultiDof())
1601  {
1602  applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
1603  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacBindex,
1604  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB,
1605  m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
1606  }
1607  }
1608 #endif
1609  }
1610 
1611  for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
1612  {
1614  if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
1615  {
1616  applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
1617  }
1618  if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
1619  {
1620  applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
1621  }
1622  }
1623  }
1624 
1625  numPoolConstraints = m_multiBodyNonContactConstraints.size();
1626 
1627 #if 0
1628  //@todo: m_originalContactPoint is not initialized for btMultiBodySolverConstraint
1629  for (int i=0;i<numPoolConstraints;i++)
1630  {
1632 
1634  btJointFeedback* fb = constr->getJointFeedback();
1635  if (fb)
1636  {
1638  fb->m_appliedForceBodyB += c.m_contactNormal2*c.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
1639  fb->m_appliedTorqueBodyA += c.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep;
1640  fb->m_appliedTorqueBodyB += c.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
1641 
1642  }
1643 
1646  {
1647  constr->setEnabled(false);
1648  }
1649 
1650  }
1651 #endif
1652 #endif
1653 
1654  return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies,numBodies,infoGlobal);
1655 }
1656 
1657 
1658 void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
1659 {
1660  //printf("solveMultiBodyGroup: numBodies=%d, numConstraints=%d, numManifolds=%d, numMultiBodyConstraints=%d\n", numBodies, numConstraints, numManifolds, numMultiBodyConstraints);
1661 
1662  //printf("solveMultiBodyGroup start\n");
1663  m_tmpMultiBodyConstraints = multiBodyConstraints;
1664  m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
1665 
1666  btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
1667 
1670 
1671 
1672 }
btScalar getInvMass() const
Definition: btRigidBody.h:273
static T sum(const btAlignedObjectArray< T > &items)
btVector3 m_linearVelocity
Definition: btSolverBody.h:119
btVector3 m_angularVelocity
Definition: btSolverBody.h:120
#define SIMD_EPSILON
Definition: btScalar.h:521
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
static btMultiBodyLinkCollider * upcast(btCollisionObject *colObj)
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
const btMultibodyLink & getLink(int index) const
Definition: btMultiBody.h:119
void setupMultiBodyContactConstraint(btMultiBodySolverConstraint &solverConstraint, const btVector3 &contactNormal, btManifoldPoint &cp, const btContactSolverInfo &infoGlobal, btScalar &relaxation, bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0)
const btVector3 & getTotalForce() const
Definition: btRigidBody.h:287
1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and fr...
btScalar m_combinedContactStiffness1
btVector3 m_lateralFrictionDir1
btAlignedObjectArray< btScalar > scratch_r
btAlignedObjectArray< btScalar > m_deltaVelocities
virtual void createConstraintRows(btMultiBodyConstraintArray &constraintRows, btMultiBodyJacobianData &data, const btContactSolverInfo &infoGlobal)=0
void internalApplyImpulse(const btVector3 &linearComponent, const btVector3 &angularComponent, const btScalar impulseMagnitude)
Definition: btSolverBody.h:255
btAlignedObjectArray< btSolverBody > * m_solverBodyPool
const btVector3 & getAngularFactor() const
Definition: btRigidBody.h:504
btScalar m_appliedImpulseLateral1
virtual btScalar solveSingleIteration(int iteration, btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
btScalar btSin(btScalar x)
Definition: btScalar.h:477
void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint &constraint, btScalar deltaTime)
btScalar m_combinedRestitution
virtual btScalar solveGroup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &info, btIDebugDraw *debugDrawer, btDispatcher *dispatcher)
btSequentialImpulseConstraintSolver Sequentially applies impulses
btMultiBodyConstraint * m_orgConstraint
void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
void btPlaneSpace1(const T &n, T &p, T &q)
Definition: btVector3.h:1284
btScalar m_appliedImpulse
#define btAssert(x)
Definition: btScalar.h:131
void addLinkConstraintForce(int i, const btVector3 &f)
const btVector3 & getTotalTorque() const
Definition: btRigidBody.h:292
btScalar getBreakingImpulseThreshold() const
btScalar resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint &cA1, const btMultiBodySolverConstraint &cB)
virtual btScalar solveSingleIteration(int iteration, btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
bool internalNeedsJointFeedback() const
Definition: btMultiBody.h:566
btScalar m_frictionCFM
ManifoldContactPoint collects and maintains persistent contactpoints.
const btCollisionObject * getBody0() const
btScalar m_contactMotion1
void applyDeltaVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
Definition: btMultiBody.h:400
btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint &c)
btAlignedObjectArray< btMatrix3x3 > scratch_m
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:309
virtual btScalar solveGroup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &info, btIDebugDraw *debugDrawer, btDispatcher *dispatcher)
this method should not be called, it was just used during porting/integration of Featherstone btMulti...
btVector3 getVelocityInLocalPoint(const btVector3 &rel_pos) const
Definition: btRigidBody.h:382
const btJointFeedback * getJointFeedback() const
btMultiBodyConstraintArray m_multiBodyNonContactConstraints
int getOrInitSolverBody(btCollisionObject &body, btScalar timeStep)
btVector3 m_externalForceImpulse
Definition: btSolverBody.h:121
btAlignedObjectArray< btScalar > m_deltaVelocitiesUnitImpulse
void addLinkConstraintTorque(int i, const btVector3 &t)
#define btSimdScalar
Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later...
Definition: btSolverBody.h:104
btScalar m_combinedRollingFriction
btAlignedObjectArray< btSolverBody > m_tmpSolverBodyPool
btMultiBodySolverConstraint & addMultiBodyTorsionalFrictionConstraint(const btVector3 &normalAxis, btPersistentManifold *manifold, int frictionIndex, btManifoldPoint &cp, btScalar combinedTorsionalFriction, btCollisionObject *colObj0, btCollisionObject *colObj1, btScalar relaxation, const btContactSolverInfo &infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0)
btVector3 m_normalWorldOnB
int size() const
return the number of elements in the array
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
virtual void solveMultiBodyGroup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, btMultiBodyConstraint **multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo &info, btIDebugDraw *debugDrawer, btDispatcher *dispatcher)
btVector3 m_appliedForceBodyA
void setCompanionId(int id)
Definition: btMultiBody.h:486
btScalar m_appliedImpulseLateral2
void fillConstraintJacobianMultiDof(int link, const btVector3 &contact_point, const btVector3 &normal_ang, const btVector3 &normal_lin, btScalar *jac, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m) const
#define output
btScalar btAtan2(btScalar x, btScalar y)
Definition: btScalar.h:496
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:389
void convertContacts(btPersistentManifold **manifoldPtr, int numManifolds, const btContactSolverInfo &infoGlobal)
btCollisionObject can be used to manage collision detection objects.
btScalar getContactProcessingThreshold() const
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:29
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:62
btScalar length() const
Return the length of the vector.
Definition: btVector3.h:263
const btManifoldPoint & getContactPoint(int index) const
btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints
btAlignedObjectArray< btScalar > m_jacobians
const btVector3 & internalGetInvMass() const
Definition: btSolverBody.h:223
const btVector3 & getPositionWorldOnB() const
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
void convertContact(btPersistentManifold *manifold, const btContactSolverInfo &infoGlobal)
btAlignedObjectArray< btVector3 > scratch_v
#define BT_PROFILE(name)
Definition: btQuickprof.h:216
void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v) const
btMultiBodySolverConstraint & addMultiBodyFrictionConstraint(const btVector3 &normalAxis, btPersistentManifold *manifold, int frictionIndex, btManifoldPoint &cp, btCollisionObject *colObj0, btCollisionObject *colObj1, btScalar relaxation, const btContactSolverInfo &infoGlobal, btScalar desiredVelocity=0, btScalar cfmSlip=0)
btScalar m_combinedContactDamping1
btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints
The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packe...
Definition: btSolverBody.h:108
int getCompanionId() const
Definition: btMultiBody.h:482
void fillContactJacobianMultiDof(int link, const btVector3 &contact_point, const btVector3 &normal, btScalar *jac, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m) const
Definition: btMultiBody.h:439
TypedConstraint is the baseclass for Bullet constraints and vehicles.
void resize(int newsize, const T &fillData=T())
btRigidBody * m_originalBody
Definition: btSolverBody.h:124
btVector3 & internalGetDeltaLinearVelocity()
some internal methods, don&#39;t use them
Definition: btSolverBody.h:208
const btRigidBody & getRigidBodyA() const
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
void setEnabled(bool enabled)
void convertMultiBodyContact(btPersistentManifold *manifold, const btContactSolverInfo &infoGlobal)
void applyDeltaVeeMultiDof2(const btScalar *delta_vee, btScalar multiplier)
Definition: btMultiBody.h:383
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
void setPosUpdated(bool updated)
Definition: btMultiBody.h:560
void applyDeltaVee(btScalar *deltaV, btScalar impulse, int velocityIndex, int ndof)
btMultiBodyConstraintArray m_multiBodyNormalContactConstraints
btScalar m_contactMotion2
void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint &solverConstraint, const btVector3 &contactNormal, btManifoldPoint &cp, btScalar combinedTorsionalFriction, const btContactSolverInfo &infoGlobal, btScalar &relaxation, bool isFriction, btScalar desiredVelocity=0, btScalar cfmSlip=0)
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:29
const btMatrix3x3 & getInvInertiaTensorWorld() const
Definition: btRigidBody.h:274
btScalar m_combinedFriction
btMultiBodyConstraint ** m_tmpMultiBodyConstraints
const btVector3 & getPositionWorldOnA() const
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:898
const btTransform & getWorldTransform() const
Definition: btSolverBody.h:130
btVector3 & internalGetDeltaAngularVelocity()
Definition: btSolverBody.h:213
void internalSetAppliedImpulse(btScalar appliedImpulse)
internal method used by the constraint solver, don&#39;t use them directly
void addBaseConstraintForce(const btVector3 &f)
Definition: btMultiBody.h:316
btVector3 m_lateralFrictionDir2
btScalar getDistance() const
const btVector3 & getBasePos() const
Definition: btMultiBody.h:186
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
const btVector3 & getLinearFactor() const
Definition: btRigidBody.h:264
void addBaseConstraintTorque(const btVector3 &t)
Definition: btMultiBody.h:320
const btRigidBody & getRigidBodyB() const
static void applyAnisotropicFriction(btCollisionObject *colObj, btVector3 &frictionDirection, int frictionMode)
int getNumDofs() const
Definition: btMultiBody.h:165
const btCollisionObject * getBody1() const
const btScalar * getVelocityVector() const
Definition: btMultiBody.h:258
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
btScalar m_combinedSpinningFriction
btScalar btCos(btScalar x)
Definition: btScalar.h:476
btScalar btFabs(btScalar x)
Definition: btScalar.h:475