Bullet Collision Detection & Physics Library
btSimulationIslandManagerMt.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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 
17 #include "LinearMath/btScalar.h"
18 #include "LinearMath/btThreads.h"
25 #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h" // for s_minimumContactManifoldsForBatching
26 
27 //#include <stdio.h>
28 #include "LinearMath/btQuickprof.h"
29 
30 
31 SIMD_FORCE_INLINE int calcBatchCost( int bodies, int manifolds, int constraints )
32 {
33  // rough estimate of the cost of a batch, used for merging
34  int batchCost = bodies + 8 * manifolds + 4 * constraints;
35  return batchCost;
36 }
37 
38 
40 {
41  return calcBatchCost( island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size() );
42 }
43 
44 
46 {
50  m_batchIsland = NULL;
51 }
52 
53 
55 {
56  for ( int i = 0; i < m_allocatedIslands.size(); ++i )
57  {
58  delete m_allocatedIslands[ i ];
59  }
62  m_freeIslands.resize( 0 );
63 }
64 
65 
66 inline int getIslandId(const btPersistentManifold* lhs)
67 {
68  const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
69  const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
70  int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
71  return islandId;
72 }
73 
74 
76 {
77  const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
78  const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
79  int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
80  return islandId;
81 }
82 
85 {
86 public:
87  bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
88  {
89  int lCost = calcBatchCost( lhs );
90  int rCost = calcBatchCost( rhs );
91  return lCost > rCost;
92  }
93 };
94 
95 
97 {
98 public:
99  bool operator() ( const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs ) const
100  {
101  return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
102  }
103 };
104 
105 
107 {
108  // append bodies
109  for ( int i = 0; i < other.bodyArray.size(); ++i )
110  {
111  bodyArray.push_back( other.bodyArray[ i ] );
112  }
113  // append manifolds
114  for ( int i = 0; i < other.manifoldArray.size(); ++i )
115  {
116  manifoldArray.push_back( other.manifoldArray[ i ] );
117  }
118  // append constraints
119  for ( int i = 0; i < other.constraintArray.size(); ++i )
120  {
121  constraintArray.push_back( other.constraintArray[ i ] );
122  }
123 }
124 
125 
127 {
128  for ( int i = 0; i < island.bodyArray.size(); ++i )
129  {
130  if ( island.bodyArray[ i ] == obj )
131  {
132  return true;
133  }
134  }
135  return false;
136 }
137 
138 
140 {
141  // reset island pools
142  int numElem = getUnionFind().getNumElements();
143  m_lookupIslandFromId.resize( numElem );
144  for ( int i = 0; i < m_lookupIslandFromId.size(); ++i )
145  {
146  m_lookupIslandFromId[ i ] = NULL;
147  }
148  m_activeIslands.resize( 0 );
149  m_freeIslands.resize( 0 );
150  // check whether allocated islands are sorted by body capacity (largest to smallest)
151  int lastCapacity = 0;
152  bool isSorted = true;
153  for ( int i = 0; i < m_allocatedIslands.size(); ++i )
154  {
155  Island* island = m_allocatedIslands[ i ];
156  int cap = island->bodyArray.capacity();
157  if ( cap > lastCapacity )
158  {
159  isSorted = false;
160  break;
161  }
162  lastCapacity = cap;
163  }
164  if ( !isSorted )
165  {
167  }
168 
169  m_batchIsland = NULL;
170  // mark all islands free (but avoid deallocation)
171  for ( int i = 0; i < m_allocatedIslands.size(); ++i )
172  {
173  Island* island = m_allocatedIslands[ i ];
174  island->bodyArray.resize( 0 );
175  island->manifoldArray.resize( 0 );
176  island->constraintArray.resize( 0 );
177  island->id = -1;
178  island->isSleeping = true;
179  m_freeIslands.push_back( island );
180  }
181 }
182 
183 
185 {
186  Island* island = m_lookupIslandFromId[ id ];
187  if ( island == NULL )
188  {
189  // search for existing island
190  for ( int i = 0; i < m_activeIslands.size(); ++i )
191  {
192  if ( m_activeIslands[ i ]->id == id )
193  {
194  island = m_activeIslands[ i ];
195  break;
196  }
197  }
198  m_lookupIslandFromId[ id ] = island;
199  }
200  return island;
201 }
202 
203 
205 {
206  Island* island = NULL;
207  int allocSize = numBodies;
208  if ( numBodies < m_batchIslandMinBodyCount )
209  {
210  if ( m_batchIsland )
211  {
212  island = m_batchIsland;
213  m_lookupIslandFromId[ id ] = island;
214  // if we've made a large enough batch,
215  if ( island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount )
216  {
217  // next time start a new batch
218  m_batchIsland = NULL;
219  }
220  return island;
221  }
222  else
223  {
224  // need to allocate a batch island
225  allocSize = m_batchIslandMinBodyCount * 2;
226  }
227  }
229 
230  // search for free island
231  if ( freeIslands.size() > 0 )
232  {
233  // try to reuse a previously allocated island
234  int iFound = freeIslands.size();
235  // linear search for smallest island that can hold our bodies
236  for ( int i = freeIslands.size() - 1; i >= 0; --i )
237  {
238  if ( freeIslands[ i ]->bodyArray.capacity() >= allocSize )
239  {
240  iFound = i;
241  island = freeIslands[ i ];
242  island->id = id;
243  break;
244  }
245  }
246  // if found, shrink array while maintaining ordering
247  if ( island )
248  {
249  int iDest = iFound;
250  int iSrc = iDest + 1;
251  while ( iSrc < freeIslands.size() )
252  {
253  freeIslands[ iDest++ ] = freeIslands[ iSrc++ ];
254  }
255  freeIslands.pop_back();
256  }
257  }
258  if ( island == NULL )
259  {
260  // no free island found, allocate
261  island = new Island(); // TODO: change this to use the pool allocator
262  island->id = id;
263  island->bodyArray.reserve( allocSize );
264  m_allocatedIslands.push_back( island );
265  }
266  m_lookupIslandFromId[ id ] = island;
267  if ( numBodies < m_batchIslandMinBodyCount )
268  {
269  m_batchIsland = island;
270  }
271  m_activeIslands.push_back( island );
272  return island;
273 }
274 
275 
277 {
278 
279  BT_PROFILE("buildIslands");
280 
281  btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
282 
283  //we are going to sort the unionfind array, and store the element id in the size
284  //afterwards, we clean unionfind, to make sure no-one uses it anymore
285 
287  int numElem = getUnionFind().getNumElements();
288 
289  int endIslandIndex=1;
290  int startIslandIndex;
291 
292  //update the sleeping state for bodies, if all are sleeping
293  for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
294  {
295  int islandId = getUnionFind().getElement(startIslandIndex).m_id;
296  for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
297  {
298  }
299 
300  //int numSleeping = 0;
301 
302  bool allSleeping = true;
303 
304  int idx;
305  for (idx=startIslandIndex;idx<endIslandIndex;idx++)
306  {
307  int i = getUnionFind().getElement(idx).m_sz;
308 
309  btCollisionObject* colObj0 = collisionObjects[i];
310  if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
311  {
312 // printf("error in island management\n");
313  }
314 
315  btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
316  if (colObj0->getIslandTag() == islandId)
317  {
318  if (colObj0->getActivationState()== ACTIVE_TAG ||
320  {
321  allSleeping = false;
322  break;
323  }
324  }
325  }
326 
327  if (allSleeping)
328  {
329  int idx;
330  for (idx=startIslandIndex;idx<endIslandIndex;idx++)
331  {
332  int i = getUnionFind().getElement(idx).m_sz;
333  btCollisionObject* colObj0 = collisionObjects[i];
334  if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
335  {
336 // printf("error in island management\n");
337  }
338 
339  btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
340 
341  if (colObj0->getIslandTag() == islandId)
342  {
344  }
345  }
346  } else
347  {
348 
349  int idx;
350  for (idx=startIslandIndex;idx<endIslandIndex;idx++)
351  {
352  int i = getUnionFind().getElement(idx).m_sz;
353 
354  btCollisionObject* colObj0 = collisionObjects[i];
355  if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
356  {
357 // printf("error in island management\n");
358  }
359 
360  btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
361 
362  if (colObj0->getIslandTag() == islandId)
363  {
364  if ( colObj0->getActivationState() == ISLAND_SLEEPING)
365  {
367  colObj0->setDeactivationTime(0.f);
368  }
369  }
370  }
371  }
372  }
373 }
374 
375 
377 {
378  btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
379  int endIslandIndex = 1;
380  int startIslandIndex;
381  int numElem = getUnionFind().getNumElements();
382 
383  // create explicit islands and add bodies to each
384  for ( startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex )
385  {
386  int islandId = getUnionFind().getElement( startIslandIndex ).m_id;
387 
388  // find end index
389  for ( endIslandIndex = startIslandIndex; ( endIslandIndex < numElem ) && ( getUnionFind().getElement( endIslandIndex ).m_id == islandId ); endIslandIndex++ )
390  {
391  }
392  // check if island is sleeping
393  bool islandSleeping = true;
394  for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
395  {
396  int i = getUnionFind().getElement( iElem ).m_sz;
397  btCollisionObject* colObj = collisionObjects[ i ];
398  if ( colObj->isActive() )
399  {
400  islandSleeping = false;
401  }
402  }
403  if ( !islandSleeping )
404  {
405  // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
406  int numBodies = endIslandIndex - startIslandIndex;
407  Island* island = allocateIsland( islandId, numBodies );
408  island->isSleeping = false;
409 
410  // add bodies to island
411  for ( int iElem = startIslandIndex; iElem < endIslandIndex; iElem++ )
412  {
413  int i = getUnionFind().getElement( iElem ).m_sz;
414  btCollisionObject* colObj = collisionObjects[ i ];
415  island->bodyArray.push_back( colObj );
416  }
417  }
418  }
419 
420 }
421 
422 
424 {
425  // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
426  int maxNumManifolds = dispatcher->getNumManifolds();
427  for ( int i = 0; i < maxNumManifolds; i++ )
428  {
429  btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal( i );
430 
431  const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
432  const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
433 
435  if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
436  ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
437  {
438 
439  //kinematic objects don't merge islands, but wake up all connected objects
440  if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
441  {
442  if ( colObj0->hasContactResponse() )
443  colObj1->activate();
444  }
445  if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
446  {
447  if ( colObj1->hasContactResponse() )
448  colObj0->activate();
449  }
450  //filtering for response
451  if ( dispatcher->needsResponse( colObj0, colObj1 ) )
452  {
453  // scatter manifolds into various islands
454  int islandId = getIslandId( manifold );
455  // if island not sleeping,
456  if ( Island* island = getIsland( islandId ) )
457  {
458  island->manifoldArray.push_back( manifold );
459  }
460  }
461  }
462  }
463 }
464 
465 
467 {
468  // walk constraints
469  for ( int i = 0; i < constraints.size(); i++ )
470  {
471  // scatter constraints into various islands
472  btTypedConstraint* constraint = constraints[ i ];
473  if ( constraint->isEnabled() )
474  {
475  int islandId = btGetConstraintIslandId( constraint );
476  // if island is not sleeping,
477  if ( Island* island = getIsland( islandId ) )
478  {
479  island->constraintArray.push_back( constraint );
480  }
481  }
482  }
483 }
484 
485 
487 {
488  // sort islands in order of decreasing batch size
490 
491  // merge small islands to satisfy minimum batch size
492  // find first small batch island
493  int destIslandIndex = m_activeIslands.size();
494  for ( int i = 0; i < m_activeIslands.size(); ++i )
495  {
496  Island* island = m_activeIslands[ i ];
497  int batchSize = calcBatchCost( island );
498  if ( batchSize < m_minimumSolverBatchSize )
499  {
500  destIslandIndex = i;
501  break;
502  }
503  }
504  int lastIndex = m_activeIslands.size() - 1;
505  while ( destIslandIndex < lastIndex )
506  {
507  // merge islands from the back of the list
508  Island* island = m_activeIslands[ destIslandIndex ];
509  int numBodies = island->bodyArray.size();
510  int numManifolds = island->manifoldArray.size();
511  int numConstraints = island->constraintArray.size();
512  int firstIndex = lastIndex;
513  // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
514  while ( true )
515  {
516  Island* src = m_activeIslands[ firstIndex ];
517  numBodies += src->bodyArray.size();
518  numManifolds += src->manifoldArray.size();
519  numConstraints += src->constraintArray.size();
520  int batchCost = calcBatchCost( numBodies, numManifolds, numConstraints );
521  if ( batchCost >= m_minimumSolverBatchSize )
522  {
523  break;
524  }
525  if ( firstIndex - 1 == destIslandIndex )
526  {
527  break;
528  }
529  firstIndex--;
530  }
531  // reserve space for these pointers to minimize reallocation
532  island->bodyArray.reserve( numBodies );
533  island->manifoldArray.reserve( numManifolds );
534  island->constraintArray.reserve( numConstraints );
535  // merge islands
536  for ( int i = firstIndex; i <= lastIndex; ++i )
537  {
538  island->append( *m_activeIslands[ i ] );
539  }
540  // shrink array to exclude the islands that were merged from
541  m_activeIslands.resize( firstIndex );
542  lastIndex = firstIndex - 1;
543  destIslandIndex++;
544  }
545 }
546 
547 
549 {
550  btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[ 0 ] : NULL;
551  btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[ 0 ] : NULL;
552  solver->solveGroup( &island.bodyArray[ 0 ],
553  island.bodyArray.size(),
554  manifolds,
555  island.manifoldArray.size(),
556  constraintsPtr,
557  island.constraintArray.size(),
558  *solverParams.m_solverInfo,
559  solverParams.m_debugDrawer,
560  solverParams.m_dispatcher
561  );
562 }
563 
564 
566 {
567  BT_PROFILE( "serialIslandDispatch" );
568  // serial dispatch
569  btAlignedObjectArray<Island*>& islands = *islandsPtr;
570  btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
571  for ( int i = 0; i < islands.size(); ++i )
572  {
573  solveIsland(solver, *islands[ i ], solverParams);
574  }
575 }
576 
577 
579 {
582 
584  : m_islandsPtr(islandsPtr), m_solverParams(solverParams)
585  {}
586 
587  void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
588  {
589  btConstraintSolver* solver = m_solverParams.m_solverPool;
590  for ( int i = iBegin; i < iEnd; ++i )
591  {
592  btSimulationIslandManagerMt::Island* island = m_islandsPtr[ i ];
593  btSimulationIslandManagerMt::solveIsland( solver, *island, m_solverParams );
594  }
595  }
596 };
597 
598 
600 {
601  BT_PROFILE( "parallelIslandDispatch" );
602  //
603  // if there are islands with many contacts, it may be faster to submit these
604  // large islands *serially* to a single parallel constraint solver, and then later
605  // submit the remaining smaller islands in parallel to multiple sequential solvers.
606  //
607  // Some task schedulers do not deal well with nested parallelFor loops. One implementation
608  // of OpenMP was actually slower than doing everything single-threaded. Intel TBB
609  // on the other hand, seems to do a pretty respectable job with it.
610  //
611  // When solving islands in parallel, the worst case performance happens when there
612  // is one very large island and then perhaps a smattering of very small
613  // islands -- one worker thread takes the large island and the remaining workers
614  // tear through the smaller islands and then sit idle waiting for the first worker
615  // to finish. Solving islands in parallel works best when there are numerous small
616  // islands, roughly equal in size.
617  //
618  // By contrast, the other approach -- the parallel constraint solver -- is only
619  // able to deliver a worthwhile speedup when the island is large. For smaller islands,
620  // it is difficult to extract a useful amount of parallelism -- the overhead of grouping
621  // the constraints into batches and sending the batches to worker threads can nullify
622  // any gains from parallelism.
623  //
624 
625  UpdateIslandDispatcher dispatcher(*islandsPtr, solverParams);
626  // We take advantage of the fact the islands are sorted in order of decreasing size
627  int iBegin = 0;
628  if (solverParams.m_solverMt)
629  {
630  while ( iBegin < islandsPtr->size() )
631  {
632  btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ iBegin ];
634  {
635  // OK to submit the rest of the array in parallel
636  break;
637  }
638  // serial dispatch to parallel solver for large islands (if any)
639  solveIsland(solverParams.m_solverMt, *island, solverParams);
640  ++iBegin;
641  }
642  }
643  // parallel dispatch to sequential solvers for rest
644  btParallelFor( iBegin, islandsPtr->size(), 1, dispatcher );
645 }
646 
647 
650  btCollisionWorld* collisionWorld,
652  const SolverParams& solverParams
653  )
654 {
655  BT_PROFILE("buildAndProcessIslands");
656  btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
657 
658  buildIslands(dispatcher,collisionWorld);
659 
660  if(!getSplitIslands())
661  {
662  btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
663  int maxNumManifolds = dispatcher->getNumManifolds();
664 
665  for ( int i = 0; i < maxNumManifolds; i++ )
666  {
667  btPersistentManifold* manifold = manifolds[ i ];
668 
669  const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() );
670  const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() );
671 
673  if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) ||
674  ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) )
675  {
676 
677  //kinematic objects don't merge islands, but wake up all connected objects
678  if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING )
679  {
680  if ( colObj0->hasContactResponse() )
681  colObj1->activate();
682  }
683  if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING )
684  {
685  if ( colObj1->hasContactResponse() )
686  colObj0->activate();
687  }
688  }
689  }
690  btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL;
691  btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
692  solver->solveGroup(&collisionObjects[0],
693  collisionObjects.size(),
694  manifolds,
695  maxNumManifolds,
696  constraintsPtr,
697  constraints.size(),
698  *solverParams.m_solverInfo,
699  solverParams.m_debugDrawer,
700  solverParams.m_dispatcher
701  );
702  }
703  else
704  {
705  initIslandPools();
706 
707  //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
708  addBodiesToIslands( collisionWorld );
709  addManifoldsToIslands( dispatcher );
710  addConstraintsToIslands( constraints );
711 
712  // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
713  // have all the necessary bodies, manifolds and constraints.
714 
715  // if we want to merge islands with small batch counts,
716  if ( m_minimumSolverBatchSize > 1 )
717  {
718  mergeIslands();
719  }
720  // dispatch islands to solver
721  m_islandDispatch( &m_activeIslands, solverParams );
722  }
723 }
virtual Island * allocateIsland(int id, int numBodies)
#define ACTIVE_TAG
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void push_back(const T &_Val)
void sortIslands()
this is a special operation, destroying the content of btUnionFind.
Definition: btUnionFind.cpp:64
static void serialIslandDispatch(btAlignedObjectArray< Island * > *islandsPtr, const SolverParams &solverParams)
int getIslandId(const btPersistentManifold *lhs)
btAlignedObjectArray< btPersistentManifold * > manifoldArray
btAlignedObjectArray< Island * > m_freeIslands
static void parallelIslandDispatch(btAlignedObjectArray< Island * > *islandsPtr, const SolverParams &solverParams)
btAlignedObjectArray< Island * > m_lookupIslandFromId
virtual btPersistentManifold * getManifoldByIndexInternal(int index)=0
static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
Definition: bFile.cpp:868
bool btIsBodyInIsland(const btSimulationIslandManagerMt::Island &island, const btCollisionObject *obj)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
#define btAssert(x)
Definition: btScalar.h:131
btElement & getElement(int index)
Definition: btUnionFind.h:61
btCollisionObjectArray & getCollisionObjectArray()
virtual void addBodiesToIslands(btCollisionWorld *collisionWorld)
virtual btScalar solveGroup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &info, class btIDebugDraw *debugDrawer, btDispatcher *dispatcher)=0
solve a group of constraints
#define SIMD_FORCE_INLINE
Definition: btScalar.h:81
const btCollisionObject * getBody0() const
function object that routes calls to operator<
#define ISLAND_SLEEPING
const btSimulationIslandManagerMt::SolverParams & m_solverParams
bool hasContactResponse() const
btAlignedObjectArray< Island * > m_activeIslands
void setActivationState(int newState) const
int size() const
return the number of elements in the array
btAlignedObjectArray< Island * > m_allocatedIslands
#define BT_OVERRIDE
Definition: btThreads.h:28
bool isKinematicObject() const
btAlignedObjectArray< btSimulationIslandManagerMt::Island * > & m_islandsPtr
int btGetConstraintIslandId(const btTypedConstraint *lhs)
virtual void buildAndProcessIslands(btDispatcher *dispatcher, btCollisionWorld *collisionWorld, btAlignedObjectArray< btTypedConstraint * > &constraints, const SolverParams &solverParams)
btCollisionObject can be used to manage collision detection objects.
btAlignedObjectArray< btTypedConstraint * > constraintArray
void setDeactivationTime(btScalar time)
bool isEnabled() const
UpdateIslandDispatcher(btAlignedObjectArray< btSimulationIslandManagerMt::Island * > &islandsPtr, const btSimulationIslandManagerMt::SolverParams &solverParams)
int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
virtual btPersistentManifold ** getInternalManifoldPointer()=0
void activate(bool forceActivation=false) const
virtual void addConstraintsToIslands(btAlignedObjectArray< btTypedConstraint * > &constraints)
virtual int getNumManifolds() const =0
#define BT_PROFILE(name)
Definition: btQuickprof.h:216
static void solveIsland(btConstraintSolver *solver, Island &island, const SolverParams &solverParams)
CollisionWorld is interface and container for the collision detection.
int getIslandTag() const
#define WANTS_DEACTIVATION
TypedConstraint is the baseclass for Bullet constraints and vehicles.
void resize(int newsize, const T &fillData=T())
int calcBatchCost(int bodies, int manifolds, int constraints)
const btRigidBody & getRigidBodyA() const
virtual void buildIslands(btDispatcher *dispatcher, btCollisionWorld *colWorld)
virtual bool needsResponse(const btCollisionObject *body0, const btCollisionObject *body1)=0
#define DISABLE_DEACTIVATION
btAlignedObjectArray< btCollisionObject * > bodyArray
void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody &body)
Definition: btThreads.cpp:429
int getNumElements() const
Definition: btUnionFind.h:52
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
int getActivationState() const
const btRigidBody & getRigidBodyB() const
virtual void addManifoldsToIslands(btDispatcher *dispatcher)
const btCollisionObject * getBody1() const
bool isActive() const
void quickSort(const L &CompareFunc)