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"
23 
24 
25 
26 
27 void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short 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),
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);
278  }
279 
280 
281  virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
282  {
283  if (islandId<0)
284  {
287  } else
288  {
289  //also add all non-contact constraints/joints for this island
290  btTypedConstraint** startConstraint = 0;
291  btMultiBodyConstraint** startMultiBodyConstraint = 0;
292 
293  int numCurConstraints = 0;
294  int numCurMultiBodyConstraints = 0;
295 
296  int i;
297 
298  //find the first constraint for this island
299 
300  for (i=0;i<m_numConstraints;i++)
301  {
302  if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
303  {
304  startConstraint = &m_sortedConstraints[i];
305  break;
306  }
307  }
308  //count the number of constraints in this island
309  for (;i<m_numConstraints;i++)
310  {
311  if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
312  {
313  numCurConstraints++;
314  }
315  }
316 
317  for (i=0;i<m_numMultiBodyConstraints;i++)
318  {
320  {
321 
322  startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
323  break;
324  }
325  }
326  //count the number of multi body constraints in this island
327  for (;i<m_numMultiBodyConstraints;i++)
328  {
330  {
331  numCurMultiBodyConstraints++;
332  }
333  }
334 
336  {
337  m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
338  } else
339  {
340 
341  for (i=0;i<numBodies;i++)
342  m_bodies.push_back(bodies[i]);
343  for (i=0;i<numManifolds;i++)
344  m_manifolds.push_back(manifolds[i]);
345  for (i=0;i<numCurConstraints;i++)
346  m_constraints.push_back(startConstraint[i]);
347 
348  for (i=0;i<numCurMultiBodyConstraints;i++)
349  m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
350 
352  {
354  } else
355  {
356  //printf("deferred\n");
357  }
358  }
359  }
360  }
362  {
363 
364  btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
365  btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
366  btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
367  btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
368 
370  m_bodies.resize(0);
371  m_manifolds.resize(0);
374  }
375 
376 };
377 
378 
379 
381  :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
382  m_multiBodyConstraintSolver(constraintSolver)
383 {
384  //split impulse is not yet supported for Featherstone hierarchies
385  getSolverInfo().m_splitImpulse = false;
388 }
389 
391 {
393 }
394 
395 
396 
397 
399 {
400 
404 
405 
406  BT_PROFILE("solveConstraints");
407 
409  int i;
410  for (i=0;i<getNumConstraints();i++)
411  {
413  }
415  btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
416 
418  for (i=0;i<m_multiBodyConstraints.size();i++)
419  {
421  }
423 
424  btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
425 
426 
427  m_solverMultiBodyIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),sortedMultiBodyConstraints,m_sortedMultiBodyConstraints.size(), getDebugDrawer());
429 
432 
433 
434  {
435  BT_PROFILE("btMultiBody addForce and stepVelocities");
436  for (int i=0;i<this->m_multiBodies.size();i++)
437  {
438  btMultiBody* bod = m_multiBodies[i];
439 
440  bool isSleeping = false;
441 
443  {
444  isSleeping = true;
445  }
446  for (int b=0;b<bod->getNumLinks();b++)
447  {
449  isSleeping = true;
450  }
451 
452  if (!isSleeping)
453  {
454  scratch_r.resize(bod->getNumLinks()+1);
455  scratch_v.resize(bod->getNumLinks()+1);
456  scratch_m.resize(bod->getNumLinks()+1);
457 
458  bod->clearForcesAndTorques();
459  bod->addBaseForce(m_gravity * bod->getBaseMass());
460 
461  for (int j = 0; j < bod->getNumLinks(); ++j)
462  {
463  bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
464  }
465 
466  bod->stepVelocities(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m);
467  }
468  }
469  }
470 
472 
474 
475 }
476 
478 {
480 
481  {
482  BT_PROFILE("btMultiBody stepPositions");
483  //integrate and update the Featherstone hierarchies
484  btAlignedObjectArray<btQuaternion> world_to_local;
485  btAlignedObjectArray<btVector3> local_origin;
486 
487  for (int b=0;b<m_multiBodies.size();b++)
488  {
489  btMultiBody* bod = m_multiBodies[b];
490  bool isSleeping = false;
492  {
493  isSleeping = true;
494  }
495  for (int b=0;b<bod->getNumLinks();b++)
496  {
498  isSleeping = true;
499  }
500 
501 
502  if (!isSleeping)
503  {
504  int nLinks = bod->getNumLinks();
505 
507  world_to_local.resize(nLinks+1);
508  local_origin.resize(nLinks+1);
509 
510  bod->stepPositions(timeStep);
511 
512 
513 
514  world_to_local[0] = bod->getWorldToBaseRot();
515  local_origin[0] = bod->getBasePos();
516 
517  if (bod->getBaseCollider())
518  {
519  btVector3 posr = local_origin[0];
520  float pos[4]={posr.x(),posr.y(),posr.z(),1};
521  float quat[4]={-world_to_local[0].x(),-world_to_local[0].y(),-world_to_local[0].z(),world_to_local[0].w()};
522  btTransform tr;
523  tr.setIdentity();
524  tr.setOrigin(posr);
525  tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
526 
528 
529  }
530 
531  for (int k=0;k<bod->getNumLinks();k++)
532  {
533  const int parent = bod->getParent(k);
534  world_to_local[k+1] = bod->getParentToLocalRot(k) * world_to_local[parent+1];
535  local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , bod->getRVector(k)));
536  }
537 
538 
539  for (int m=0;m<bod->getNumLinks();m++)
540  {
542  if (col)
543  {
544  int link = col->m_link;
545  btAssert(link == m);
546 
547  int index = link+1;
548 
549  btVector3 posr = local_origin[index];
550  float pos[4]={posr.x(),posr.y(),posr.z(),1};
551  float quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
552  btTransform tr;
553  tr.setIdentity();
554  tr.setOrigin(posr);
555  tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
556 
557  col->setWorldTransform(tr);
558  }
559  }
560  } else
561  {
562  bod->clearVelocities();
563  }
564  }
565  }
566 }
567 
568 
569 
571 {
572  m_multiBodyConstraints.push_back(constraint);
573 }
574 
576 {
577  m_multiBodyConstraints.remove(constraint);
578 }
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
MultiBodyInplaceSolverIslandCallback & operator=(MultiBodyInplaceSolverIslandCallback &other)
#define ACTIVE_TAG
btAlignedObjectArray< btTypedConstraint * > m_constraints
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
virtual void updateActivationState(btScalar timeStep)
void push_back(const T &_Val)
const btMultibodyLink & getLink(int index) const
Definition: btMultiBody.h:76
btSimulationIslandManager * m_islandManager
bool isAwake() const
Definition: btMultiBody.h:335
int getNumLinks() const
Definition: btMultiBody.h:112
btAlignedObjectArray< btTypedConstraint * > m_sortedConstraints
btDiscreteDynamicsWorld provides discrete rigid body simulation those classes replace the obsolete Cc...
btScalar getBaseMass() const
Definition: btMultiBody.h:113
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
#define btAssert(x)
Definition: btScalar.h:101
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:58
int getNumCollisionObjects() const
void addLinkForce(int i, const btVector3 &f)
const btCollisionObject * getBody0() const
virtual void integrateTransforms(btScalar timeStep)
int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint *lhs)
virtual void updateActivationState(btCollisionWorld *colWorld, btDispatcher *dispatcher)
btQuaternion inverse(const btQuaternion &q)
Return the inverse of a quaternion.
Definition: btQuaternion.h:849
#define ISLAND_SLEEPING
void clearForcesAndTorques()
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
Definition: btQuaternion.h:866
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...
virtual int getIslandIdB() const =0
MultiBodyInplaceSolverIslandCallback * m_solverMultiBodyIslandCallback
btCollisionWorld * getCollisionWorld()
bool operator()(const btMultiBodyConstraint *lhs, const btMultiBodyConstraint *rhs) const
btAlignedObjectArray< btCollisionObject * > m_bodies
void setActivationState(int newState) const
virtual void processIsland(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifolds, int numManifolds, int islandId)
int size() const
return the number of elements in the array
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)
bool operator()(const btTypedConstraint *lhs, const btTypedConstraint *rhs) const
btAlignedObjectArray< btPersistentManifold * > m_manifolds
bool isStaticOrKinematicObject() const
btCollisionObject can be used to manage collision detection objects.
void setRotation(const btQuaternion &q)
Set the rotational element by btQuaternion.
Definition: btTransform.h:165
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:28
const btVector3 & getRVector(int i) const
btAlignedObjectArray< btMultiBodyConstraint * > m_multiBodyConstraints
btAlignedObjectArray< btPersistentManifold * > m_predictiveManifolds
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:59
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs...
void setDeactivationTime(btScalar time)
void setWorldTransform(const btTransform &worldTrans)
btDispatcher * getDispatcher()
void clearVelocities()
virtual void solveConstraints(btContactSolverInfo &solverInfo)
MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver *solver, btDispatcher *dispatcher)
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
void checkMotionAndSleepIfRequired(btScalar 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
#define BT_PROFILE(name)
Definition: btQuickprof.h:191
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:221
virtual int getNumConstraints() const
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 addMultiBody(btMultiBody *body, short group=btBroadphaseProxy::DefaultFilter, short mask=btBroadphaseProxy::AllFilter)
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
void setup(btContactSolverInfo *solverInfo, btTypedConstraint **sortedConstraints, int numConstraints, btMultiBodyConstraint **sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw *debugDrawer)
virtual void storeIslandActivationState(btCollisionWorld *world)
const btQuaternion & getParentToLocalRot(int i) const
#define DISABLE_DEACTIVATION
virtual void removeMultiBody(btMultiBody *body)
btConstraintSolver * m_constraintSolver
const btMultiBodyLinkCollider * getBaseCollider() const
Definition: btMultiBody.h:91
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:48
const btQuaternion & getWorldToBaseRot() const
Definition: btMultiBody.h:136
virtual void updateActivationState(btScalar timeStep)
void stepPositions(btScalar dt)
int getParent(int link_num) const
void unite(int p, int q)
Definition: btUnionFind.h:81
const btVector3 & getBasePos() const
Definition: btMultiBody.h:131
virtual void addMultiBodyConstraint(btMultiBodyConstraint *constraint)
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:69
int getActivationState() const
btContactSolverInfo & getSolverInfo()
const btRigidBody & getRigidBodyB() const
const btCollisionObject * getBody1() const
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
void quickSort(const L &CompareFunc)
int btGetConstraintIslandId2(const btTypedConstraint *lhs)
void stepVelocities(btScalar dt, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m)
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
btAlignedObjectArray< btTypedConstraint * > m_constraints