Bullet Collision Detection & Physics Library
btMultiBodyDynamicsWorld.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 
18 #include "btMultiBody.h"
21 #include "LinearMath/btQuickprof.h"
22 #include "btMultiBodyConstraint.h"
25 
26 
27 void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
28 {
30 
31 }
32 
34 {
35  m_multiBodies.remove(body);
36 }
37 
39 {
40  BT_PROFILE("calculateSimulationIslands");
41 
43 
44  {
45  //merge islands based on speculative contact manifolds too
46  for (int i=0;i<this->m_predictiveManifolds.size();i++)
47  {
49 
50  const btCollisionObject* colObj0 = manifold->getBody0();
51  const btCollisionObject* colObj1 = manifold->getBody1();
52 
53  if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
54  ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
55  {
56  getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
57  }
58  }
59  }
60 
61  {
62  int i;
63  int numConstraints = int(m_constraints.size());
64  for (i=0;i< numConstraints ; i++ )
65  {
66  btTypedConstraint* constraint = m_constraints[i];
67  if (constraint->isEnabled())
68  {
69  const btRigidBody* colObj0 = &constraint->getRigidBodyA();
70  const btRigidBody* colObj1 = &constraint->getRigidBodyB();
71 
72  if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
73  ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
74  {
75  getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
76  }
77  }
78  }
79  }
80 
81  //merge islands linked by Featherstone link colliders
82  for (int i=0;i<m_multiBodies.size();i++)
83  {
84  btMultiBody* body = m_multiBodies[i];
85  {
87 
88  for (int b=0;b<body->getNumLinks();b++)
89  {
91 
92  if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
93  ((prev) && (!(prev)->isStaticOrKinematicObject())))
94  {
95  int tagPrev = prev->getIslandTag();
96  int tagCur = cur->getIslandTag();
97  getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
98  }
99  if (cur && !cur->isStaticOrKinematicObject())
100  prev = cur;
101 
102  }
103  }
104  }
105 
106  //merge islands linked by multibody constraints
107  {
108  for (int i=0;i<this->m_multiBodyConstraints.size();i++)
109  {
111  int tagA = c->getIslandIdA();
112  int tagB = c->getIslandIdB();
113  if (tagA>=0 && tagB>=0)
115  }
116  }
117 
118  //Store the island id in each body
120 
121 }
122 
123 
125 {
126  BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
127 
128 
129 
130  for ( int i=0;i<m_multiBodies.size();i++)
131  {
132  btMultiBody* body = m_multiBodies[i];
133  if (body)
134  {
135  body->checkMotionAndSleepIfRequired(timeStep);
136  if (!body->isAwake())
137  {
139  if (col && col->getActivationState() == ACTIVE_TAG)
140  {
142  col->setDeactivationTime(0.f);
143  }
144  for (int b=0;b<body->getNumLinks();b++)
145  {
147  if (col && col->getActivationState() == ACTIVE_TAG)
148  {
150  col->setDeactivationTime(0.f);
151  }
152  }
153  } else
154  {
156  if (col && col->getActivationState() != DISABLE_DEACTIVATION)
158 
159  for (int b=0;b<body->getNumLinks();b++)
160  {
162  if (col && col->getActivationState() != DISABLE_DEACTIVATION)
164  }
165  }
166 
167  }
168  }
169 
171 }
172 
173 
175 {
176  int islandId;
177 
178  const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
179  const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
180  islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
181  return islandId;
182 
183 }
184 
185 
187 {
188  public:
189 
190  bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
191  {
192  int rIslandId0,lIslandId0;
193  rIslandId0 = btGetConstraintIslandId2(rhs);
194  lIslandId0 = btGetConstraintIslandId2(lhs);
195  return lIslandId0 < rIslandId0;
196  }
197 };
198 
199 
200 
202 {
203  int islandId;
204 
205  int islandTagA = lhs->getIslandIdA();
206  int islandTagB = lhs->getIslandIdB();
207  islandId= islandTagA>=0?islandTagA:islandTagB;
208  return islandId;
209 
210 }
211 
212 
214 {
215  public:
216 
217  bool operator() ( const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs ) const
218  {
219  int rIslandId0,lIslandId0;
220  rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
221  lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
222  return lIslandId0 < rIslandId0;
223  }
224 };
225 
227 {
232 
237 
242 
243 
245  btDispatcher* dispatcher)
246  :m_solverInfo(NULL),
247  m_solver(solver),
248  m_multiBodySortedConstraints(NULL),
249  m_numConstraints(0),
250  m_debugDrawer(NULL),
251  m_dispatcher(dispatcher)
252  {
253 
254  }
255 
257  {
258  btAssert(0);
259  (void)other;
260  return *this;
261  }
262 
263  SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
264  {
265  btAssert(solverInfo);
266  m_solverInfo = solverInfo;
267 
268  m_multiBodySortedConstraints = sortedMultiBodyConstraints;
269  m_numMultiBodyConstraints = numMultiBodyConstraints;
270  m_sortedConstraints = sortedConstraints;
271  m_numConstraints = numConstraints;
272 
273  m_debugDrawer = debugDrawer;
274  m_bodies.resize (0);
275  m_manifolds.resize (0);
276  m_constraints.resize (0);
277  m_multiBodyConstraints.resize(0);
278  }
279 
281  {
282  m_solver = solver;
283  }
284 
285  virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
286  {
287  if (islandId<0)
288  {
290  m_solver->solveMultiBodyGroup( bodies,numBodies,manifolds, numManifolds,m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
291  } else
292  {
293  //also add all non-contact constraints/joints for this island
294  btTypedConstraint** startConstraint = 0;
295  btMultiBodyConstraint** startMultiBodyConstraint = 0;
296 
297  int numCurConstraints = 0;
298  int numCurMultiBodyConstraints = 0;
299 
300  int i;
301 
302  //find the first constraint for this island
303 
304  for (i=0;i<m_numConstraints;i++)
305  {
306  if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
307  {
308  startConstraint = &m_sortedConstraints[i];
309  break;
310  }
311  }
312  //count the number of constraints in this island
313  for (;i<m_numConstraints;i++)
314  {
315  if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
316  {
317  numCurConstraints++;
318  }
319  }
320 
321  for (i=0;i<m_numMultiBodyConstraints;i++)
322  {
323  if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
324  {
325 
326  startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
327  break;
328  }
329  }
330  //count the number of multi body constraints in this island
331  for (;i<m_numMultiBodyConstraints;i++)
332  {
333  if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
334  {
335  numCurMultiBodyConstraints++;
336  }
337  }
338 
339  //if (m_solverInfo->m_minimumSolverBatchSize<=1)
340  //{
341  // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
342  //} else
343  {
344 
345  for (i=0;i<numBodies;i++)
346  m_bodies.push_back(bodies[i]);
347  for (i=0;i<numManifolds;i++)
348  m_manifolds.push_back(manifolds[i]);
349  for (i=0;i<numCurConstraints;i++)
350  m_constraints.push_back(startConstraint[i]);
351 
352  for (i=0;i<numCurMultiBodyConstraints;i++)
353  m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
354 
355  if ((m_multiBodyConstraints.size()+m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
356  {
357  processConstraints();
358  } else
359  {
360  //printf("deferred\n");
361  }
362  }
363  }
364  }
366  {
367 
368  btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
369  btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
370  btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
371  btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
372 
373  //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
374 
375  m_solver->solveMultiBodyGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo,m_debugDrawer,m_dispatcher);
376  m_bodies.resize(0);
377  m_manifolds.resize(0);
378  m_constraints.resize(0);
379  m_multiBodyConstraints.resize(0);
380  }
381 
382 };
383 
384 
385 
387  :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
388  m_multiBodyConstraintSolver(constraintSolver)
389 {
390  //split impulse is not yet supported for Featherstone hierarchies
391 // getSolverInfo().m_splitImpulse = false;
394 }
395 
397 {
399 }
400 
402 {
406 }
407 
409 {
410  if (solver->getSolverType()==BT_MULTIBODY_SOLVER)
411  {
413  }
415 }
416 
418 {
419 
420  for (int b=0;b<m_multiBodies.size();b++)
421  {
422  btMultiBody* bod = m_multiBodies[b];
424  }
425 }
427 {
429 
430 
431 
432  BT_PROFILE("solveConstraints");
433 
435 
437  int i;
438  for (i=0;i<getNumConstraints();i++)
439  {
441  }
443  btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
444 
446  for (i=0;i<m_multiBodyConstraints.size();i++)
447  {
449  }
451 
452  btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
453 
454 
455  m_solverMultiBodyIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),sortedMultiBodyConstraints,m_sortedMultiBodyConstraints.size(), getDebugDrawer());
457 
458 
459 #ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
460  {
461  BT_PROFILE("btMultiBody addForce");
462  for (int i=0;i<this->m_multiBodies.size();i++)
463  {
464  btMultiBody* bod = m_multiBodies[i];
465 
466  bool isSleeping = false;
467 
469  {
470  isSleeping = true;
471  }
472  for (int b=0;b<bod->getNumLinks();b++)
473  {
475  isSleeping = true;
476  }
477 
478  if (!isSleeping)
479  {
480  //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
481  m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
482  m_scratch_v.resize(bod->getNumLinks()+1);
483  m_scratch_m.resize(bod->getNumLinks()+1);
484 
485  bod->addBaseForce(m_gravity * bod->getBaseMass());
486 
487  for (int j = 0; j < bod->getNumLinks(); ++j)
488  {
489  bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
490  }
491  }//if (!isSleeping)
492  }
493  }
494 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
495 
496 
497  {
498  BT_PROFILE("btMultiBody stepVelocities");
499  for (int i=0;i<this->m_multiBodies.size();i++)
500  {
501  btMultiBody* bod = m_multiBodies[i];
502 
503  bool isSleeping = false;
504 
506  {
507  isSleeping = true;
508  }
509  for (int b=0;b<bod->getNumLinks();b++)
510  {
512  isSleeping = true;
513  }
514 
515  if (!isSleeping)
516  {
517  //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
518  m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
519  m_scratch_v.resize(bod->getNumLinks()+1);
520  m_scratch_m.resize(bod->getNumLinks()+1);
521  bool doNotUpdatePos = false;
522 
523  {
524  if(!bod->isUsingRK4Integration())
525  {
527  }
528  else
529  {
530  //
531  int numDofs = bod->getNumDofs() + 6;
532  int numPosVars = bod->getNumPosVars() + 7;
533  btAlignedObjectArray<btScalar> scratch_r2; scratch_r2.resize(2*numPosVars + 8*numDofs);
534  //convenience
535  btScalar *pMem = &scratch_r2[0];
536  btScalar *scratch_q0 = pMem; pMem += numPosVars;
537  btScalar *scratch_qx = pMem; pMem += numPosVars;
538  btScalar *scratch_qd0 = pMem; pMem += numDofs;
539  btScalar *scratch_qd1 = pMem; pMem += numDofs;
540  btScalar *scratch_qd2 = pMem; pMem += numDofs;
541  btScalar *scratch_qd3 = pMem; pMem += numDofs;
542  btScalar *scratch_qdd0 = pMem; pMem += numDofs;
543  btScalar *scratch_qdd1 = pMem; pMem += numDofs;
544  btScalar *scratch_qdd2 = pMem; pMem += numDofs;
545  btScalar *scratch_qdd3 = pMem; pMem += numDofs;
546  btAssert((pMem - (2*numPosVars + 8*numDofs)) == &scratch_r2[0]);
547 
549  //copy q0 to scratch_q0 and qd0 to scratch_qd0
550  scratch_q0[0] = bod->getWorldToBaseRot().x();
551  scratch_q0[1] = bod->getWorldToBaseRot().y();
552  scratch_q0[2] = bod->getWorldToBaseRot().z();
553  scratch_q0[3] = bod->getWorldToBaseRot().w();
554  scratch_q0[4] = bod->getBasePos().x();
555  scratch_q0[5] = bod->getBasePos().y();
556  scratch_q0[6] = bod->getBasePos().z();
557  //
558  for(int link = 0; link < bod->getNumLinks(); ++link)
559  {
560  for(int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
561  scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
562  }
563  //
564  for(int dof = 0; dof < numDofs; ++dof)
565  scratch_qd0[dof] = bod->getVelocityVector()[dof];
567  struct
568  {
569  btMultiBody *bod;
570  btScalar *scratch_qx, *scratch_q0;
571 
572  void operator()()
573  {
574  for(int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
575  scratch_qx[dof] = scratch_q0[dof];
576  }
577  } pResetQx = {bod, scratch_qx, scratch_q0};
578  //
579  struct
580  {
581  void operator()(btScalar dt, const btScalar *pDer, const btScalar *pCurVal, btScalar *pVal, int size)
582  {
583  for(int i = 0; i < size; ++i)
584  pVal[i] = pCurVal[i] + dt * pDer[i];
585  }
586 
587  } pEulerIntegrate;
588  //
589  struct
590  {
591  void operator()(btMultiBody *pBody, const btScalar *pData)
592  {
593  btScalar *pVel = const_cast<btScalar*>(pBody->getVelocityVector());
594 
595  for(int i = 0; i < pBody->getNumDofs() + 6; ++i)
596  pVel[i] = pData[i];
597 
598  }
599  } pCopyToVelocityVector;
600  //
601  struct
602  {
603  void operator()(const btScalar *pSrc, btScalar *pDst, int start, int size)
604  {
605  for(int i = 0; i < size; ++i)
606  pDst[i] = pSrc[start + i];
607  }
608  } pCopy;
609  //
610 
611  btScalar h = solverInfo.m_timeStep;
612  #define output &m_scratch_r[bod->getNumDofs()]
613  //calc qdd0 from: q0 & qd0
615  pCopy(output, scratch_qdd0, 0, numDofs);
616  //calc q1 = q0 + h/2 * qd0
617  pResetQx();
618  bod->stepPositionsMultiDof(btScalar(.5)*h, scratch_qx, scratch_qd0);
619  //calc qd1 = qd0 + h/2 * qdd0
620  pEulerIntegrate(btScalar(.5)*h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
621  //
622  //calc qdd1 from: q1 & qd1
623  pCopyToVelocityVector(bod, scratch_qd1);
625  pCopy(output, scratch_qdd1, 0, numDofs);
626  //calc q2 = q0 + h/2 * qd1
627  pResetQx();
628  bod->stepPositionsMultiDof(btScalar(.5)*h, scratch_qx, scratch_qd1);
629  //calc qd2 = qd0 + h/2 * qdd1
630  pEulerIntegrate(btScalar(.5)*h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
631  //
632  //calc qdd2 from: q2 & qd2
633  pCopyToVelocityVector(bod, scratch_qd2);
635  pCopy(output, scratch_qdd2, 0, numDofs);
636  //calc q3 = q0 + h * qd2
637  pResetQx();
638  bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
639  //calc qd3 = qd0 + h * qdd2
640  pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
641  //
642  //calc qdd3 from: q3 & qd3
643  pCopyToVelocityVector(bod, scratch_qd3);
645  pCopy(output, scratch_qdd3, 0, numDofs);
646 
647  //
648  //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
649  //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
650  btAlignedObjectArray<btScalar> delta_q; delta_q.resize(numDofs);
651  btAlignedObjectArray<btScalar> delta_qd; delta_qd.resize(numDofs);
652  for(int i = 0; i < numDofs; ++i)
653  {
654  delta_q[i] = h/btScalar(6.)*(scratch_qd0[i] + 2*scratch_qd1[i] + 2*scratch_qd2[i] + scratch_qd3[i]);
655  delta_qd[i] = h/btScalar(6.)*(scratch_qdd0[i] + 2*scratch_qdd1[i] + 2*scratch_qdd2[i] + scratch_qdd3[i]);
656  //delta_q[i] = h*scratch_qd0[i];
657  //delta_qd[i] = h*scratch_qdd0[i];
658  }
659  //
660  pCopyToVelocityVector(bod, scratch_qd0);
661  bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
662  //
663  if(!doNotUpdatePos)
664  {
665  btScalar *pRealBuf = const_cast<btScalar *>(bod->getVelocityVector());
666  pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs()*bod->getNumDofs();
667 
668  for(int i = 0; i < numDofs; ++i)
669  pRealBuf[i] = delta_q[i];
670 
671  //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
672  bod->setPosUpdated(true);
673  }
674 
675  //ugly hack which resets the cached data to t0 (needed for constraint solver)
676  {
677  for(int link = 0; link < bod->getNumLinks(); ++link)
678  bod->getLink(link).updateCacheMultiDof();
680  }
681 
682  }
683  }
684 
685 #ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
686  bod->clearForcesAndTorques();
687 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
688  }//if (!isSleeping)
689  }
690  }
691 
694 
695 
697 
699 
700  {
701  BT_PROFILE("btMultiBody stepVelocities");
702  for (int i=0;i<this->m_multiBodies.size();i++)
703  {
704  btMultiBody* bod = m_multiBodies[i];
705 
706  bool isSleeping = false;
707 
709  {
710  isSleeping = true;
711  }
712  for (int b=0;b<bod->getNumLinks();b++)
713  {
715  isSleeping = true;
716  }
717 
718  if (!isSleeping)
719  {
720  //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
721  m_scratch_r.resize(bod->getNumLinks()+1); //multidof? ("Y"s use it and it is used to store qdd)
722  m_scratch_v.resize(bod->getNumLinks()+1);
723  m_scratch_m.resize(bod->getNumLinks()+1);
724 
725 
726  {
727  if(!bod->isUsingRK4Integration())
728  {
729  bool isConstraintPass = true;
731  }
732  }
733  }
734  }
735  }
736 
737  for (int i=0;i<this->m_multiBodies.size();i++)
738  {
739  btMultiBody* bod = m_multiBodies[i];
741  }
742 
743 }
744 
746 {
748 
749  {
750  BT_PROFILE("btMultiBody stepPositions");
751  //integrate and update the Featherstone hierarchies
752 
753  for (int b=0;b<m_multiBodies.size();b++)
754  {
755  btMultiBody* bod = m_multiBodies[b];
756  bool isSleeping = false;
758  {
759  isSleeping = true;
760  }
761  for (int b=0;b<bod->getNumLinks();b++)
762  {
764  isSleeping = true;
765  }
766 
767 
768  if (!isSleeping)
769  {
770  int nLinks = bod->getNumLinks();
771 
773 
774 
775  {
776  if(!bod->isPosUpdated())
777  bod->stepPositionsMultiDof(timeStep);
778  else
779  {
780  btScalar *pRealBuf = const_cast<btScalar *>(bod->getVelocityVector());
781  pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs()*bod->getNumDofs();
782 
783  bod->stepPositionsMultiDof(1, 0, pRealBuf);
784  bod->setPosUpdated(false);
785  }
786  }
787 
789  m_scratch_local_origin.resize(nLinks+1);
790 
792 
793  } else
794  {
795  bod->clearVelocities();
796  }
797  }
798  }
799 }
800 
801 
802 
804 {
805  m_multiBodyConstraints.push_back(constraint);
806 }
807 
809 {
810  m_multiBodyConstraints.remove(constraint);
811 }
812 
814 {
815  constraint->debugDraw(getDebugDrawer());
816 }
817 
818 
820 {
821  BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
822 
824 
825  bool drawConstraints = false;
826  if (getDebugDrawer())
827  {
828  int mode = getDebugDrawer()->getDebugMode();
830  {
831  drawConstraints = true;
832  }
833 
834  if (drawConstraints)
835  {
836  BT_PROFILE("btMultiBody debugDrawWorld");
837 
838 
839  for (int c=0;c<m_multiBodyConstraints.size();c++)
840  {
842  debugDrawMultiBodyConstraint(constraint);
843  }
844 
845  for (int b = 0; b<m_multiBodies.size(); b++)
846  {
847  btMultiBody* bod = m_multiBodies[b];
849 
850  if (mode & btIDebugDraw::DBG_DrawFrames)
851  {
853  }
854 
855  for (int m = 0; m<bod->getNumLinks(); m++)
856  {
857 
858  const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
859  if (mode & btIDebugDraw::DBG_DrawFrames)
860  {
861  getDebugDrawer()->drawTransform(tr, 0.1);
862  }
863  //draw the joint axis
865  {
866  btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_topVec)*0.1;
867 
868  btVector4 color(0,0,0,1);//1,1,1);
869  btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
870  btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
871  getDebugDrawer()->drawLine(from,to,color);
872  }
874  {
875  btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec)*0.1;
876 
877  btVector4 color(0,0,0,1);//1,1,1);
878  btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
879  btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
880  getDebugDrawer()->drawLine(from,to,color);
881  }
883  {
884  btVector3 vec = quatRotate(tr.getRotation(),bod->getLink(m).m_axes[0].m_bottomVec)*0.1;
885 
886  btVector4 color(0,0,0,1);//1,1,1);
887  btVector3 from = vec+tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
888  btVector3 to = tr.getOrigin()-quatRotate(tr.getRotation(),bod->getLink(m).m_dVector);
889  getDebugDrawer()->drawLine(from,to,color);
890  }
891 
892  }
893  }
894  }
895  }
896 
897 
898 }
899 
900 
901 
903 {
905 #ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
906  BT_PROFILE("btMultiBody addGravity");
907  for (int i=0;i<this->m_multiBodies.size();i++)
908  {
909  btMultiBody* bod = m_multiBodies[i];
910 
911  bool isSleeping = false;
912 
914  {
915  isSleeping = true;
916  }
917  for (int b=0;b<bod->getNumLinks();b++)
918  {
920  isSleeping = true;
921  }
922 
923  if (!isSleeping)
924  {
925  bod->addBaseForce(m_gravity * bod->getBaseMass());
926 
927  for (int j = 0; j < bod->getNumLinks(); ++j)
928  {
929  bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
930  }
931  }//if (!isSleeping)
932  }
933 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
934 }
935 
937 {
938  for (int i=0;i<this->m_multiBodies.size();i++)
939  {
940  btMultiBody* bod = m_multiBodies[i];
941  bod->clearConstraintForces();
942  }
943 }
945 {
946  {
947  // BT_PROFILE("clearMultiBodyForces");
948  for (int i=0;i<this->m_multiBodies.size();i++)
949  {
950  btMultiBody* bod = m_multiBodies[i];
951 
952  bool isSleeping = false;
953 
955  {
956  isSleeping = true;
957  }
958  for (int b=0;b<bod->getNumLinks();b++)
959  {
961  isSleeping = true;
962  }
963 
964  if (!isSleeping)
965  {
966  btMultiBody* bod = m_multiBodies[i];
967  bod->clearForcesAndTorques();
968  }
969  }
970  }
971 
972 }
974 {
976 
977 #ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
979 #endif
980 }
981 
982 
983 
984 
986 {
987 
988  serializer->startSerialization();
989 
990  serializeDynamicsWorldInfo( serializer);
991 
992  serializeMultiBodies(serializer);
993 
994  serializeRigidBodies(serializer);
995 
996  serializeCollisionObjects(serializer);
997 
998  serializeContactManifolds(serializer);
999 
1000  serializer->finishSerialization();
1001 }
1002 
1004 {
1005  int i;
1006  //serialize all collision objects
1007  for (i=0;i<m_multiBodies.size();i++)
1008  {
1009  btMultiBody* mb = m_multiBodies[i];
1010  {
1011  int len = mb->calculateSerializeBufferSize();
1012  btChunk* chunk = serializer->allocate(len,1);
1013  const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
1014  serializer->finalizeChunk(chunk,structType,BT_MULTIBODY_CODE,mb);
1015  }
1016  }
1017 
1018  //serialize all multibody links (collision objects)
1019  for (i=0;i<m_collisionObjects.size();i++)
1020  {
1023  {
1024  int len = colObj->calculateSerializeBufferSize();
1025  btChunk* chunk = serializer->allocate(len,1);
1026  const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
1027  serializer->finalizeChunk(chunk,structType,BT_MB_LINKCOLLIDER_CODE,colObj);
1028  }
1029  }
1030 
1031 }
virtual void setConstraintSolver(btConstraintSolver *solver)
MultiBodyInplaceSolverIslandCallback & operator=(MultiBodyInplaceSolverIslandCallback &other)
virtual void finishSerialization()=0
void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver *solver)
void serializeDynamicsWorldInfo(btSerializer *serializer)
#define ACTIVE_TAG
btAlignedObjectArray< btTypedConstraint * > m_constraints
virtual void clearForces()
the forces on each rigidbody is accumulating together with gravity. clear this after each timestep...
void serializeCollisionObjects(btSerializer *serializer)
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
virtual void updateActivationState(btScalar timeStep)
virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint *constraint)
void clearConstraintForces()
void push_back(const T &_Val)
const btMultibodyLink & getLink(int index) const
Definition: btMultiBody.h:119
void serializeContactManifolds(btSerializer *serializer)
virtual void serialize(btSerializer *serializer)
Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see B...
btQuaternion getRotation() const
Return a quaternion representing the rotation.
Definition: btTransform.h:122
btSimulationIslandManager * m_islandManager
bool isAwake() const
Definition: btMultiBody.h:472
#define BT_MULTIBODY_CODE
Definition: btSerializer.h:118
int getNumLinks() const
Definition: btMultiBody.h:164
virtual void clearForces()
the forces on each rigidbody is accumulating together with gravity. clear this after each timestep...
btAlignedObjectArray< btTypedConstraint * > m_sortedConstraints
void stepPositionsMultiDof(btScalar dt, btScalar *pq=0, btScalar *pqd=0)
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
virtual void startSerialization()=0
int getInternalType() const
reserved for Bullet internal usage
const btScalar & z() const
Return the z value.
Definition: btQuadWord.h:120
virtual int calculateSerializeBufferSize() const
#define BT_MB_LINKCOLLIDER_CODE
Definition: btSerializer.h:119
btTransform getBaseWorldTransform() const
Definition: btMultiBody.h:209
btDiscreteDynamicsWorld provides discrete rigid body simulation those classes replace the obsolete Cc...
void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m, bool isConstraintPass=false)
virtual int calculateSerializeBufferSize() const
virtual void addMultiBody(btMultiBody *body, int group=btBroadphaseProxy::DefaultFilter, int mask=btBroadphaseProxy::AllFilter)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btScalar getBaseMass() const
Definition: btMultiBody.h:167
btAlignedObjectArray< btScalar > m_scratch_r
#define btAssert(x)
Definition: btScalar.h:131
btCollisionConfiguration allows to configure Bullet collision detection stack allocator size...
void buildAndProcessIslands(btDispatcher *dispatcher, btCollisionWorld *collisionWorld, IslandCallback *callback)
btSimulationIslandManager * getSimulationIslandManager()
#define SIMD_FORCE_INLINE
Definition: btScalar.h:81
int getNumCollisionObjects() const
void addLinkForce(int i, const btVector3 &f)
const btCollisionObject * getBody0() const
const btScalar & y() const
Return the y value.
Definition: btQuadWord.h:118
virtual void integrateTransforms(btScalar timeStep)
bool isPosUpdated() const
Definition: btMultiBody.h:556
int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint *lhs)
void updateCollisionObjectWorldTransforms(btAlignedObjectArray< btQuaternion > &scratch_q, btAlignedObjectArray< btVector3 > &scratch_m)
virtual void updateActivationState(btCollisionWorld *colWorld, btDispatcher *dispatcher)
btAlignedObjectArray< btVector3 > m_scratch_local_origin
virtual void debugDraw(class btIDebugDraw *drawer)=0
void applyDeltaVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
Definition: btMultiBody.h:400
#define ISLAND_SLEEPING
const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:122
btContactSolverInfo m_solverInfo
btMultiBodyConstraintSolver * m_multiBodyConstraintSolver
void clearForcesAndTorques()
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
Definition: btQuaternion.h:937
virtual int getIslandIdB() const =0
virtual const char * serialize(void *dataBuffer, class btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
MultiBodyInplaceSolverIslandCallback * m_solverMultiBodyIslandCallback
btCollisionWorld * getCollisionWorld()
int getNumPosVars() const
Definition: btMultiBody.h:166
void forwardKinematics(btAlignedObjectArray< btQuaternion > &scratch_q, btAlignedObjectArray< btVector3 > &scratch_m)
btAlignedObjectArray< btCollisionObject * > m_bodies
void setActivationState(int newState) const
btAlignedObjectArray< btVector3 > m_scratch_v
virtual void processIsland(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifolds, int numManifolds, int islandId)
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)
btIDebugDraw * m_debugDrawer
virtual btIDebugDraw * getDebugDrawer()
virtual void removeMultiBodyConstraint(btMultiBodyConstraint *constraint)
#define output
btAlignedObjectArray< btPersistentManifold * > m_manifolds
bool isStaticOrKinematicObject() const
btCollisionObject can be used to manage collision detection objects.
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:29
btAlignedObjectArray< btMultiBodyConstraint * > m_multiBodyConstraints
btAlignedObjectArray< btPersistentManifold * > m_predictiveManifolds
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:62
virtual void applyGravity()
apply gravity, call this once per timestep
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs...
void setDeactivationTime(btScalar time)
btDispatcher * getDispatcher()
void clearVelocities()
virtual void solveConstraints(btContactSolverInfo &solverInfo)
MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver *solver, btDispatcher *dispatcher)
virtual btConstraintSolverType getSolverType() const =0
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
void checkMotionAndSleepIfRequired(btScalar timestep)
virtual void applyGravity()
apply gravity, call this once per timestep
bool isEnabled() const
btAlignedObjectArray< btMultiBody * > m_multiBodies
virtual int getIslandIdA() const =0
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btAlignedObjectArray< btMultiBodyConstraint * > m_multiBodyConstraints
btMultiBodyDynamicsWorld(btDispatcher *dispatcher, btBroadphaseInterface *pairCache, btMultiBodyConstraintSolver *constraintSolver, btCollisionConfiguration *collisionConfiguration)
btScalar getLinkMass(int i) const
virtual void serializeMultiBodies(btSerializer *serializer)
#define BT_PROFILE(name)
Definition: btQuickprof.h:216
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
void addBaseForce(const btVector3 &f)
Definition: btMultiBody.h:308
virtual int getNumConstraints() const
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
virtual void allSolved(const btContactSolverInfo &, class btIDebugDraw *)
btAlignedObjectArray< btMultiBodyConstraint * > m_sortedMultiBodyConstraints
int getIslandTag() const
virtual void prepareSolve(int, int)
#define WANTS_DEACTIVATION
void remove(const T &key)
virtual void drawTransform(const btTransform &transform, btScalar orthoLen)
Definition: btIDebugDraw.h:166
TypedConstraint is the baseclass for Bullet constraints and vehicles.
void resize(int newsize, const T &fillData=T())
virtual void integrateTransforms(btScalar timeStep)
const btRigidBody & getRigidBodyA() const
virtual int getDebugMode() const =0
btAlignedObjectArray< btCollisionObject * > m_collisionObjects
btAlignedObjectArray< btQuaternion > m_scratch_world_to_local1
void setPosUpdated(bool updated)
Definition: btMultiBody.h:560
void setup(btContactSolverInfo *solverInfo, btTypedConstraint **sortedConstraints, int numConstraints, btMultiBodyConstraint **sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw *debugDrawer)
virtual void storeIslandActivationState(btCollisionWorld *world)
#define DISABLE_DEACTIVATION
virtual void removeMultiBody(btMultiBody *body)
bool isUsingRK4Integration() const
Definition: btMultiBody.h:552
const btScalar & x() const
Return the x value.
Definition: btQuadWord.h:116
btAlignedObjectArray< btMatrix3x3 > m_scratch_m
btConstraintSolver * m_constraintSolver
const btMultiBodyLinkCollider * getBaseCollider() const
Definition: btMultiBody.h:134
btAlignedObjectArray< btQuaternion > m_scratch_world_to_local
void serializeRigidBodies(btSerializer *serializer)
const btQuaternion & getWorldToBaseRot() const
Definition: btMultiBody.h:191
virtual void updateActivationState(btScalar timeStep)
btAlignedObjectArray< btVector3 > m_scratch_local_origin1
void unite(int p, int q)
Definition: btUnionFind.h:81
const btVector3 & getBasePos() const
Definition: btMultiBody.h:186
virtual void addMultiBodyConstraint(btMultiBodyConstraint *constraint)
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
void * m_oldPtr
Definition: btSerializer.h:56
int getActivationState() const
virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver *solver)
btContactSolverInfo & getSolverInfo()
const btRigidBody & getRigidBodyB() const
int getNumDofs() const
Definition: btMultiBody.h:165
const btCollisionObject * getBody1() const
virtual btChunk * allocate(size_t size, int numElements)=0
virtual const char * serialize(void *dataBuffer, class btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btScalar * getVelocityVector() const
Definition: btMultiBody.h:258
void processDeltaVeeMultiDof2()
Definition: btMultiBody.h:390
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
void quickSort(const L &CompareFunc)
int btGetConstraintIslandId2(const btTypedConstraint *lhs)
virtual void setConstraintSolver(btConstraintSolver *solver)
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591
btAlignedObjectArray< btTypedConstraint * > m_constraints