Bullet Collision Detection & Physics Library
btDiscreteDynamicsWorld.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 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 
18 
19 //collision detection
26 #include "LinearMath/btQuickprof.h"
27 
28 //rigidbody & constraints
40 
41 
44 
45 
47 #include "LinearMath/btQuickprof.h"
49 
51 
52 #if 0
55 int startHit=2;
56 int firstHit=startHit;
57 #endif
58 
60 {
61  int islandId;
62 
63  const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
64  const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
65  islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
66  return islandId;
67 
68 }
69 
70 
72 {
73  public:
74 
75  bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
76  {
77  int rIslandId0,lIslandId0;
78  rIslandId0 = btGetConstraintIslandId(rhs);
79  lIslandId0 = btGetConstraintIslandId(lhs);
80  return lIslandId0 < rIslandId0;
81  }
82 };
83 
85 {
92 
96 
97 
99  btConstraintSolver* solver,
100  btStackAlloc* stackAlloc,
101  btDispatcher* dispatcher)
102  :m_solverInfo(NULL),
103  m_solver(solver),
104  m_sortedConstraints(NULL),
105  m_numConstraints(0),
106  m_debugDrawer(NULL),
107  m_dispatcher(dispatcher)
108  {
109 
110  }
111 
113  {
114  btAssert(0);
115  (void)other;
116  return *this;
117  }
118 
119  SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
120  {
121  btAssert(solverInfo);
122  m_solverInfo = solverInfo;
123  m_sortedConstraints = sortedConstraints;
124  m_numConstraints = numConstraints;
125  m_debugDrawer = debugDrawer;
126  m_bodies.resize (0);
127  m_manifolds.resize (0);
128  m_constraints.resize (0);
129  }
130 
131 
132  virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
133  {
134  if (islandId<0)
135  {
137  m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
138  } else
139  {
140  //also add all non-contact constraints/joints for this island
141  btTypedConstraint** startConstraint = 0;
142  int numCurConstraints = 0;
143  int i;
144 
145  //find the first constraint for this island
146  for (i=0;i<m_numConstraints;i++)
147  {
148  if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
149  {
150  startConstraint = &m_sortedConstraints[i];
151  break;
152  }
153  }
154  //count the number of constraints in this island
155  for (;i<m_numConstraints;i++)
156  {
157  if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
158  {
159  numCurConstraints++;
160  }
161  }
162 
164  {
165  m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
166  } else
167  {
168 
169  for (i=0;i<numBodies;i++)
170  m_bodies.push_back(bodies[i]);
171  for (i=0;i<numManifolds;i++)
172  m_manifolds.push_back(manifolds[i]);
173  for (i=0;i<numCurConstraints;i++)
174  m_constraints.push_back(startConstraint[i]);
176  {
178  } else
179  {
180  //printf("deferred\n");
181  }
182  }
183  }
184  }
186  {
187 
188  btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
189  btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
190  btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
191 
193  m_bodies.resize(0);
194  m_manifolds.resize(0);
196 
197  }
198 
199 };
200 
201 
202 
204 :btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
205 m_sortedConstraints (),
206 m_solverIslandCallback ( NULL ),
207 m_constraintSolver(constraintSolver),
208 m_gravity(0,-10,0),
209 m_localTime(0),
210 m_fixedTimeStep(0),
211 m_synchronizeAllMotionStates(false),
212 m_applySpeculativeContactRestitution(false),
213 m_profileTimings(0),
214 m_latencyMotionStateInterpolation(true)
215 
216 {
217  if (!m_constraintSolver)
218  {
219  void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
221  m_ownsConstraintSolver = true;
222  } else
223  {
224  m_ownsConstraintSolver = false;
225  }
226 
227  {
228  void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
230  }
231 
232  m_ownsIslandManager = true;
233 
234  {
235  void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
237  }
238 }
239 
240 
242 {
243  //only delete it when we created it
245  {
248  }
250  {
251  m_solverIslandCallback->~InplaceSolverIslandCallback();
253  }
255  {
256 
259  }
260 }
261 
263 {
267  for (int i=0;i<m_collisionObjects.size();i++)
268  {
270  btRigidBody* body = btRigidBody::upcast(colObj);
271  if (body && body->getActivationState() != ISLAND_SLEEPING)
272  {
273  if (body->isKinematicObject())
274  {
275  //to calculate velocities next frame
276  body->saveKinematicState(timeStep);
277  }
278  }
279  }
280 
281 }
282 
284 {
285  BT_PROFILE("debugDrawWorld");
286 
288 
289  bool drawConstraints = false;
290  if (getDebugDrawer())
291  {
292  int mode = getDebugDrawer()->getDebugMode();
294  {
295  drawConstraints = true;
296  }
297  }
298  if(drawConstraints)
299  {
300  for(int i = getNumConstraints()-1; i>=0 ;i--)
301  {
302  btTypedConstraint* constraint = getConstraint(i);
303  debugDrawConstraint(constraint);
304  }
305  }
306 
307 
308 
310  {
311  int i;
312 
313  if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
314  {
315  for (i=0;i<m_actions.size();i++)
316  {
317  m_actions[i]->debugDraw(m_debugDrawer);
318  }
319  }
320  }
321  if (getDebugDrawer())
323 
324 }
325 
327 {
329  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
330  {
332  //need to check if next line is ok
333  //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
334  body->clearForces();
335  }
336 }
337 
340 {
342  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
343  {
345  if (body->isActive())
346  {
347  body->applyGravity();
348  }
349  }
350 }
351 
352 
354 {
355  btAssert(body);
356 
357  if (body->getMotionState() && !body->isStaticOrKinematicObject())
358  {
359  //we need to call the update at least once, even for sleeping objects
360  //otherwise the 'graphics' transform never updates properly
362  //if (body->getActivationState() != ISLAND_SLEEPING)
363  {
364  btTransform interpolatedTransform;
368  interpolatedTransform);
369  body->getMotionState()->setWorldTransform(interpolatedTransform);
370  }
371  }
372 }
373 
374 
376 {
377 // BT_PROFILE("synchronizeMotionStates");
379  {
380  //iterate over all collision objects
381  for ( int i=0;i<m_collisionObjects.size();i++)
382  {
384  btRigidBody* body = btRigidBody::upcast(colObj);
385  if (body)
387  }
388  } else
389  {
390  //iterate over all active rigid bodies
391  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
392  {
394  if (body->isActive())
396  }
397  }
398 }
399 
400 
401 int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
402 {
403  startProfiling(timeStep);
404 
405 
406  int numSimulationSubSteps = 0;
407 
408  if (maxSubSteps)
409  {
410  //fixed timestep with interpolation
411  m_fixedTimeStep = fixedTimeStep;
412  m_localTime += timeStep;
413  if (m_localTime >= fixedTimeStep)
414  {
415  numSimulationSubSteps = int( m_localTime / fixedTimeStep);
416  m_localTime -= numSimulationSubSteps * fixedTimeStep;
417  }
418  } else
419  {
420  //variable timestep
421  fixedTimeStep = timeStep;
423  m_fixedTimeStep = 0;
424  if (btFuzzyZero(timeStep))
425  {
426  numSimulationSubSteps = 0;
427  maxSubSteps = 0;
428  } else
429  {
430  numSimulationSubSteps = 1;
431  maxSubSteps = 1;
432  }
433  }
434 
435  //process some debugging flags
436  if (getDebugDrawer())
437  {
438  btIDebugDraw* debugDrawer = getDebugDrawer ();
440  }
441  if (numSimulationSubSteps)
442  {
443 
444  //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
445  int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
446 
447  saveKinematicState(fixedTimeStep*clampedSimulationSteps);
448 
449  applyGravity();
450 
451 
452 
453  for (int i=0;i<clampedSimulationSteps;i++)
454  {
455  internalSingleStepSimulation(fixedTimeStep);
457  }
458 
459  } else
460  {
462  }
463 
464  clearForces();
465 
466 #ifndef BT_NO_PROFILE
468 #endif //BT_NO_PROFILE
469 
470  return numSimulationSubSteps;
471 }
472 
474 {
475 
476  BT_PROFILE("internalSingleStepSimulation");
477 
478  if(0 != m_internalPreTickCallback) {
479  (*m_internalPreTickCallback)(this, timeStep);
480  }
481 
483  predictUnconstraintMotion(timeStep);
484 
485  btDispatcherInfo& dispatchInfo = getDispatchInfo();
486 
487  dispatchInfo.m_timeStep = timeStep;
488  dispatchInfo.m_stepCount = 0;
489  dispatchInfo.m_debugDraw = getDebugDrawer();
490 
491 
492  createPredictiveContacts(timeStep);
493 
496 
498 
499 
500  getSolverInfo().m_timeStep = timeStep;
501 
502 
503 
506 
508 
510 
511  integrateTransforms(timeStep);
512 
514  updateActions(timeStep);
515 
516  updateActivationState( timeStep );
517 
518  if(0 != m_internalTickCallback) {
519  (*m_internalTickCallback)(this, timeStep);
520  }
521 }
522 
524 {
525  m_gravity = gravity;
526  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
527  {
529  if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
530  {
531  body->setGravity(gravity);
532  }
533  }
534 }
535 
537 {
538  return m_gravity;
539 }
540 
541 void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
542 {
543  btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
544 }
545 
547 {
548  btRigidBody* body = btRigidBody::upcast(collisionObject);
549  if (body)
550  removeRigidBody(body);
551  else
553 }
554 
556 {
559 }
560 
561 
563 {
564  if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
565  {
566  body->setGravity(m_gravity);
567  }
568 
569  if (body->getCollisionShape())
570  {
571  if (!body->isStaticObject())
572  {
574  } else
575  {
577  }
578 
579  bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
580  int collisionFilterGroup = isDynamic? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
581  int collisionFilterMask = isDynamic? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
582 
583  addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
584  }
585 }
586 
587 void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
588 {
589  if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
590  {
591  body->setGravity(m_gravity);
592  }
593 
594  if (body->getCollisionShape())
595  {
596  if (!body->isStaticObject())
597  {
599  }
600  else
601  {
603  }
604  addCollisionObject(body,group,mask);
605  }
606 }
607 
608 
610 {
611  BT_PROFILE("updateActions");
612 
613  for ( int i=0;i<m_actions.size();i++)
614  {
615  m_actions[i]->updateAction( this, timeStep);
616  }
617 }
618 
619 
621 {
622  BT_PROFILE("updateActivationState");
623 
624  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
625  {
627  if (body)
628  {
629  body->updateDeactivation(timeStep);
630 
631  if (body->wantsSleeping())
632  {
633  if (body->isStaticOrKinematicObject())
634  {
636  } else
637  {
638  if (body->getActivationState() == ACTIVE_TAG)
640  if (body->getActivationState() == ISLAND_SLEEPING)
641  {
642  body->setAngularVelocity(btVector3(0,0,0));
643  body->setLinearVelocity(btVector3(0,0,0));
644  }
645 
646  }
647  } else
648  {
651  }
652  }
653  }
654 }
655 
656 void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
657 {
658  m_constraints.push_back(constraint);
659  //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
660  btAssert(&constraint->getRigidBodyA()!=&constraint->getRigidBodyB());
661 
662  if (disableCollisionsBetweenLinkedBodies)
663  {
664  constraint->getRigidBodyA().addConstraintRef(constraint);
665  constraint->getRigidBodyB().addConstraintRef(constraint);
666  }
667 }
668 
670 {
671  m_constraints.remove(constraint);
672  constraint->getRigidBodyA().removeConstraintRef(constraint);
673  constraint->getRigidBodyB().removeConstraintRef(constraint);
674 }
675 
677 {
678  m_actions.push_back(action);
679 }
680 
682 {
683  m_actions.remove(action);
684 }
685 
686 
688 {
689  addAction(vehicle);
690 }
691 
693 {
694  removeAction(vehicle);
695 }
696 
698 {
699  addAction(character);
700 }
701 
703 {
704  removeAction(character);
705 }
706 
707 
708 
709 
711 {
712  BT_PROFILE("solveConstraints");
713 
715  int i;
716  for (i=0;i<getNumConstraints();i++)
717  {
719  }
720 
721 // btAssert(0);
722 
723 
724 
726 
727  btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
728 
729  m_solverIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer());
731 
734 
736 
738 }
739 
740 
742 {
743  BT_PROFILE("calculateSimulationIslands");
744 
746 
747  {
748  //merge islands based on speculative contact manifolds too
749  for (int i=0;i<this->m_predictiveManifolds.size();i++)
750  {
752 
753  const btCollisionObject* colObj0 = manifold->getBody0();
754  const btCollisionObject* colObj1 = manifold->getBody1();
755 
756  if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
757  ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
758  {
759  getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
760  }
761  }
762  }
763 
764  {
765  int i;
766  int numConstraints = int(m_constraints.size());
767  for (i=0;i< numConstraints ; i++ )
768  {
769  btTypedConstraint* constraint = m_constraints[i];
770  if (constraint->isEnabled())
771  {
772  const btRigidBody* colObj0 = &constraint->getRigidBodyA();
773  const btRigidBody* colObj1 = &constraint->getRigidBodyB();
774 
775  if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
776  ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
777  {
778  getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
779  }
780  }
781  }
782  }
783 
784  //Store the island id in each body
786 
787 
788 }
789 
790 
791 
792 
794 {
795 public:
796 
801 
802 public:
805  m_me(me),
806  m_allowedPenetration(0.0f),
807  m_pairCache(pairCache),
808  m_dispatcher(dispatcher)
809  {
810  }
811 
812  virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
813  {
814  if (convexResult.m_hitCollisionObject == m_me)
815  return 1.0f;
816 
817  //ignore result if there is no contact response
818  if(!convexResult.m_hitCollisionObject->hasContactResponse())
819  return 1.0f;
820 
821  btVector3 linVelA,linVelB;
823  linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
824 
825  btVector3 relativeVelocity = (linVelA-linVelB);
826  //don't report time of impact for motion away from the contact normal (or causes minor penetration)
827  if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
828  return 1.f;
829 
830  return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
831  }
832 
833  virtual bool needsCollision(btBroadphaseProxy* proxy0) const
834  {
835  //don't collide with itself
836  if (proxy0->m_clientObject == m_me)
837  return false;
838 
840  if (!ClosestConvexResultCallback::needsCollision(proxy0))
841  return false;
842 
843  btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
844 
845  //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
846  if (m_dispatcher->needsResponse(m_me,otherObj))
847  {
848 #if 0
851  btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
852  if (collisionPair)
853  {
854  if (collisionPair->m_algorithm)
855  {
856  manifoldArray.resize(0);
857  collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
858  for (int j=0;j<manifoldArray.size();j++)
859  {
860  btPersistentManifold* manifold = manifoldArray[j];
861  if (manifold->getNumContacts()>0)
862  return false;
863  }
864  }
865  }
866 #endif
867  return true;
868  }
869 
870  return false;
871  }
872 
873 
874 };
875 
878 
879 
881 {
882  btTransform predictedTrans;
883  for ( int i=0;i<numBodies;i++)
884  {
885  btRigidBody* body = bodies[i];
886  body->setHitFraction(1.f);
887 
888  if (body->isActive() && (!body->isStaticOrKinematicObject()))
889  {
890 
891  body->predictIntegratedTransform(timeStep, predictedTrans);
892 
893  btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
894 
896  {
897  BT_PROFILE("predictive convexSweepTest");
898  if (body->getCollisionShape()->isConvex())
899  {
901 #ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
902  class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
903  {
904  public:
905 
906  StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
907  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
908  {
909  }
910 
911  virtual bool needsCollision(btBroadphaseProxy* proxy0) const
912  {
913  btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
914  if (!otherObj->isStaticOrKinematicObject())
915  return false;
917  }
918  };
919 
920  StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
921 #else
923 #endif
924  //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
925  btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
926  sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
927 
928  sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
929  sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
930  btTransform modifiedPredictedTrans = predictedTrans;
931  modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
932 
933  convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
934  if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
935  {
936 
937  btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
938  btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
939 
940 
941  btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
945 
946  btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
947  btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
948 
949  btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
950 
951  bool isPredictive = true;
952  int index = manifold->addManifoldPoint(newPoint, isPredictive);
953  btManifoldPoint& pt = manifold->getContactPoint(index);
954  pt.m_combinedRestitution = 0;
955  pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject);
957  pt.m_positionWorldOnB = worldPointB;
958 
959  }
960  }
961  }
962  }
963  }
964 }
965 
967 {
968  BT_PROFILE( "release predictive contact manifolds" );
969 
970  for ( int i = 0; i < m_predictiveManifolds.size(); i++ )
971  {
973  this->m_dispatcher1->releaseManifold( manifold );
974  }
976 }
977 
979 {
980  BT_PROFILE("createPredictiveContacts");
982  if (m_nonStaticRigidBodies.size() > 0)
983  {
985  }
986 }
987 
989 {
990  btTransform predictedTrans;
991  for (int i=0;i<numBodies;i++)
992  {
993  btRigidBody* body = bodies[i];
994  body->setHitFraction(1.f);
995 
996  if (body->isActive() && (!body->isStaticOrKinematicObject()))
997  {
998 
999  body->predictIntegratedTransform(timeStep, predictedTrans);
1000 
1001  btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
1002 
1003 
1004 
1006  {
1007  BT_PROFILE("CCD motion clamping");
1008  if (body->getCollisionShape()->isConvex())
1009  {
1011 #ifdef USE_STATIC_ONLY
1012  class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
1013  {
1014  public:
1015 
1016  StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
1017  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
1018  {
1019  }
1020 
1021  virtual bool needsCollision(btBroadphaseProxy* proxy0) const
1022  {
1023  btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
1024  if (!otherObj->isStaticOrKinematicObject())
1025  return false;
1027  }
1028  };
1029 
1030  StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
1031 #else
1033 #endif
1034  //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
1035  btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
1036  sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
1037 
1038  sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
1039  sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
1040  btTransform modifiedPredictedTrans = predictedTrans;
1041  modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
1042 
1043  convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
1044  if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
1045  {
1046 
1047  //printf("clamped integration to hit fraction = %f\n",fraction);
1048  body->setHitFraction(sweepResults.m_closestHitFraction);
1049  body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
1050  body->setHitFraction(0.f);
1051  body->proceedToTransform( predictedTrans);
1052 
1053 #if 0
1054  btVector3 linVel = body->getLinearVelocity();
1055 
1057  btScalar maxSpeedSqr = maxSpeed*maxSpeed;
1058  if (linVel.length2()>maxSpeedSqr)
1059  {
1060  linVel.normalize();
1061  linVel*= maxSpeed;
1062  body->setLinearVelocity(linVel);
1063  btScalar ms2 = body->getLinearVelocity().length2();
1064  body->predictIntegratedTransform(timeStep, predictedTrans);
1065 
1066  btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
1067  btScalar smt = body->getCcdSquareMotionThreshold();
1068  printf("sm2=%f\n",sm2);
1069  }
1070 #else
1071 
1072  //don't apply the collision response right now, it will happen next frame
1073  //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
1074  //btScalar appliedImpulse = 0.f;
1075  //btScalar depth = 0.f;
1076  //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
1077 
1078 
1079 #endif
1080 
1081  continue;
1082  }
1083  }
1084  }
1085 
1086 
1087  body->proceedToTransform( predictedTrans);
1088 
1089  }
1090 
1091  }
1092 
1093 }
1094 
1096 {
1097  BT_PROFILE("integrateTransforms");
1098  if (m_nonStaticRigidBodies.size() > 0)
1099  {
1101  }
1102 
1105  {
1106  BT_PROFILE("apply speculative contact restitution");
1107  for (int i=0;i<m_predictiveManifolds.size();i++)
1108  {
1112 
1113  for (int p=0;p<manifold->getNumContacts();p++)
1114  {
1115  const btManifoldPoint& pt = manifold->getContactPoint(p);
1116  btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1);
1117 
1118  if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
1119  //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
1120  {
1121  btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
1122 
1123  const btVector3& pos1 = pt.getPositionWorldOnA();
1124  const btVector3& pos2 = pt.getPositionWorldOnB();
1125 
1126  btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
1127  btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
1128 
1129  if (body0)
1130  body0->applyImpulse(imp,rel_pos0);
1131  if (body1)
1132  body1->applyImpulse(-imp,rel_pos1);
1133  }
1134  }
1135  }
1136  }
1137 }
1138 
1139 
1140 
1141 
1142 
1144 {
1145  BT_PROFILE("predictUnconstraintMotion");
1146  for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
1147  {
1149  if (!body->isStaticOrKinematicObject())
1150  {
1151  //don't integrate/update velocities here, it happens in the constraint solver
1152 
1153  body->applyDamping(timeStep);
1154 
1156  }
1157  }
1158 }
1159 
1160 
1162 {
1163  (void)timeStep;
1164 
1165 #ifndef BT_NO_PROFILE
1167 #endif //BT_NO_PROFILE
1168 
1169 }
1170 
1171 
1172 
1173 
1174 
1175 
1177 {
1178  bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
1179  bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
1180  btScalar dbgDrawSize = constraint->getDbgDrawSize();
1181  if(dbgDrawSize <= btScalar(0.f))
1182  {
1183  return;
1184  }
1185 
1186  switch(constraint->getConstraintType())
1187  {
1189  {
1190  btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
1191  btTransform tr;
1192  tr.setIdentity();
1193  btVector3 pivot = p2pC->getPivotInA();
1194  pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
1195  tr.setOrigin(pivot);
1196  getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1197  // that ideally should draw the same frame
1198  pivot = p2pC->getPivotInB();
1199  pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
1200  tr.setOrigin(pivot);
1201  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1202  }
1203  break;
1204  case HINGE_CONSTRAINT_TYPE:
1205  {
1206  btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
1207  btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
1208  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1209  tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
1210  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1211  btScalar minAng = pHinge->getLowerLimit();
1212  btScalar maxAng = pHinge->getUpperLimit();
1213  if(minAng == maxAng)
1214  {
1215  break;
1216  }
1217  bool drawSect = true;
1218  if(!pHinge->hasLimit())
1219  {
1220  minAng = btScalar(0.f);
1221  maxAng = SIMD_2_PI;
1222  drawSect = false;
1223  }
1224  if(drawLimits)
1225  {
1226  btVector3& center = tr.getOrigin();
1227  btVector3 normal = tr.getBasis().getColumn(2);
1228  btVector3 axis = tr.getBasis().getColumn(0);
1229  getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
1230  }
1231  }
1232  break;
1234  {
1235  btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
1237  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1238  tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
1239  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1240  if(drawLimits)
1241  {
1242  //const btScalar length = btScalar(5);
1243  const btScalar length = dbgDrawSize;
1244  static int nSegments = 8*4;
1245  btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
1246  btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
1247  pPrev = tr * pPrev;
1248  for (int i=0; i<nSegments; i++)
1249  {
1250  fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
1251  btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
1252  pCur = tr * pCur;
1253  getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
1254 
1255  if (i%(nSegments/8) == 0)
1256  getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
1257 
1258  pPrev = pCur;
1259  }
1260  btScalar tws = pCT->getTwistSpan();
1261  btScalar twa = pCT->getTwistAngle();
1262  bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
1263  if(useFrameB)
1264  {
1265  tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
1266  }
1267  else
1268  {
1269  tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
1270  }
1271  btVector3 pivot = tr.getOrigin();
1272  btVector3 normal = tr.getBasis().getColumn(0);
1273  btVector3 axis1 = tr.getBasis().getColumn(1);
1274  getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
1275 
1276  }
1277  }
1278  break;
1280  case D6_CONSTRAINT_TYPE:
1281  {
1282  btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
1283  btTransform tr = p6DOF->getCalculatedTransformA();
1284  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1285  tr = p6DOF->getCalculatedTransformB();
1286  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1287  if(drawLimits)
1288  {
1289  tr = p6DOF->getCalculatedTransformA();
1290  const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
1291  btVector3 up = tr.getBasis().getColumn(2);
1292  btVector3 axis = tr.getBasis().getColumn(0);
1293  btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
1294  btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
1295  btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
1296  btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
1297  getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
1298  axis = tr.getBasis().getColumn(1);
1299  btScalar ay = p6DOF->getAngle(1);
1300  btScalar az = p6DOF->getAngle(2);
1301  btScalar cy = btCos(ay);
1302  btScalar sy = btSin(ay);
1303  btScalar cz = btCos(az);
1304  btScalar sz = btSin(az);
1305  btVector3 ref;
1306  ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
1307  ref[1] = -sz*axis[0] + cz*axis[1];
1308  ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
1309  tr = p6DOF->getCalculatedTransformB();
1310  btVector3 normal = -tr.getBasis().getColumn(0);
1311  btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
1312  btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
1313  if(minFi > maxFi)
1314  {
1315  getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
1316  }
1317  else if(minFi < maxFi)
1318  {
1319  getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
1320  }
1321  tr = p6DOF->getCalculatedTransformA();
1324  getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
1325  }
1326  }
1327  break;
1330  {
1331  {
1333  btTransform tr = p6DOF->getCalculatedTransformA();
1334  if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1335  tr = p6DOF->getCalculatedTransformB();
1336  if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1337  if (drawLimits)
1338  {
1339  tr = p6DOF->getCalculatedTransformA();
1340  const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
1341  btVector3 up = tr.getBasis().getColumn(2);
1342  btVector3 axis = tr.getBasis().getColumn(0);
1343  btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
1344  btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
1345  btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
1346  btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
1347  getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
1348  axis = tr.getBasis().getColumn(1);
1349  btScalar ay = p6DOF->getAngle(1);
1350  btScalar az = p6DOF->getAngle(2);
1351  btScalar cy = btCos(ay);
1352  btScalar sy = btSin(ay);
1353  btScalar cz = btCos(az);
1354  btScalar sz = btSin(az);
1355  btVector3 ref;
1356  ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
1357  ref[1] = -sz*axis[0] + cz*axis[1];
1358  ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
1359  tr = p6DOF->getCalculatedTransformB();
1360  btVector3 normal = -tr.getBasis().getColumn(0);
1361  btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
1362  btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
1363  if (minFi > maxFi)
1364  {
1365  getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
1366  }
1367  else if (minFi < maxFi)
1368  {
1369  getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
1370  }
1371  tr = p6DOF->getCalculatedTransformA();
1374  getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
1375  }
1376  }
1377  break;
1378  }
1380  {
1381  btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
1382  btTransform tr = pSlider->getCalculatedTransformA();
1383  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1384  tr = pSlider->getCalculatedTransformB();
1385  if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1386  if(drawLimits)
1387  {
1389  btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
1390  btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
1391  getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
1392  btVector3 normal = tr.getBasis().getColumn(0);
1393  btVector3 axis = tr.getBasis().getColumn(1);
1394  btScalar a_min = pSlider->getLowerAngLimit();
1395  btScalar a_max = pSlider->getUpperAngLimit();
1396  const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
1397  getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
1398  }
1399  }
1400  break;
1401  default :
1402  break;
1403  }
1404  return;
1405 }
1406 
1407 
1408 
1409 
1410 
1412 {
1414  {
1416  }
1417  m_ownsConstraintSolver = false;
1418  m_constraintSolver = solver;
1419  m_solverIslandCallback->m_solver = solver;
1420 }
1421 
1423 {
1424  return m_constraintSolver;
1425 }
1426 
1427 
1429 {
1430  return int(m_constraints.size());
1431 }
1433 {
1434  return m_constraints[index];
1435 }
1437 {
1438  return m_constraints[index];
1439 }
1440 
1441 
1442 
1444 {
1445  int i;
1446  //serialize all collision objects
1447  for (i=0;i<m_collisionObjects.size();i++)
1448  {
1451  {
1452  int len = colObj->calculateSerializeBufferSize();
1453  btChunk* chunk = serializer->allocate(len,1);
1454  const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
1455  serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
1456  }
1457  }
1458 
1459  for (i=0;i<m_constraints.size();i++)
1460  {
1461  btTypedConstraint* constraint = m_constraints[i];
1462  int size = constraint->calculateSerializeBufferSize();
1463  btChunk* chunk = serializer->allocate(size,1);
1464  const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
1465  serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
1466  }
1467 }
1468 
1469 
1470 
1471 
1473 {
1474 #ifdef BT_USE_DOUBLE_PRECISION
1475  int len = sizeof(btDynamicsWorldDoubleData);
1476  btChunk* chunk = serializer->allocate(len,1);
1478 #else//BT_USE_DOUBLE_PRECISION
1479  int len = sizeof(btDynamicsWorldFloatData);
1480  btChunk* chunk = serializer->allocate(len,1);
1482 #endif//BT_USE_DOUBLE_PRECISION
1483 
1484  memset(worldInfo ,0x00,len);
1485 
1486  m_gravity.serialize(worldInfo->m_gravity);
1487  worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
1491 
1494  worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
1495  worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
1496 
1497  worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
1501 
1506 
1511 
1513 
1514  // Fill padding with zeros to appease msan.
1515  memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
1516 
1517 #ifdef BT_USE_DOUBLE_PRECISION
1518  const char* structType = "btDynamicsWorldDoubleData";
1519 #else//BT_USE_DOUBLE_PRECISION
1520  const char* structType = "btDynamicsWorldFloatData";
1521 #endif//BT_USE_DOUBLE_PRECISION
1522  serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
1523 }
1524 
1526 {
1527 
1528  serializer->startSerialization();
1529 
1530  serializeDynamicsWorldInfo(serializer);
1531 
1532  serializeCollisionObjects(serializer);
1533 
1534  serializeRigidBodies(serializer);
1535 
1536  serializer->finishSerialization();
1537 }
1538 
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
virtual void setConstraintSolver(btConstraintSolver *solver)
virtual void internalSingleStepSimulation(btScalar timeStep)
virtual void finishSerialization()=0
static const btRigidBody * upcast(const btCollisionObject *colObj)
to keep collision detection and dynamics separate we don't store a rigidbody pointer but a rigidbody ...
Definition: btRigidBody.h:203
void serializeDynamicsWorldInfo(btSerializer *serializer)
const btRigidBody & getRigidBodyA() const
void startProfiling(btScalar timeStep)
#define ACTIVE_TAG
virtual void releaseManifold(btPersistentManifold *manifold)=0
virtual void clearForces()
the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
void serializeCollisionObjects(btSerializer *serializer)
btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:886
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
const btVector3 & getInterpolationAngularVelocity() const
void setup(btContactSolverInfo *solverInfo, btTypedConstraint **sortedConstraints, int numConstraints, btIDebugDraw *debugDrawer)
void push_back(const T &_Val)
btScalar getUpperLimit() const
virtual void addAction(btActionInterface *)
virtual void solveConstraints(btContactSolverInfo &solverInfo)
point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocke...
bool operator()(const btTypedConstraint *lhs, const btTypedConstraint *rhs) const
void applyGravity()
virtual void addConstraint(btTypedConstraint *constraint, bool disableCollisionsBetweenLinkedBodies=false)
virtual void removeVehicle(btActionInterface *vehicle)
obsolete, use removeAction instead
virtual const char * serialize(void *dataBuffer, class btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btRigidBody & getRigidBodyB() const
int btGetConstraintIslandId(const btTypedConstraint *lhs)
const btVector3 & getPositionWorldOnA() const
const btVector3 & getPivotInA() const
#define BT_CONSTRAINT_CODE
Definition: btSerializer.h:121
const btTransform & getBFrame() const
btSimulationIslandManager * m_islandManager
const btTransform & getCalculatedTransformA() const
btScalar getLowerLimit() const
const btTransform & getCalculatedTransformB() const
btAlignedObjectArray< btRigidBody * > m_nonStaticRigidBodies
bool isConvex() const
void predictIntegratedTransform(btScalar step, btTransform &predictedTransform)
continuous collision detection needs prediction
virtual void addRigidBody(btRigidBody *body)
btScalar btSin(btScalar x)
Definition: btScalar.h:477
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
const btVector3 & getPivotInB() const
btScalar m_loLimit
limit_parameters
virtual void addCollisionObject(btCollisionObject *collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter)
virtual void setGravity(const btVector3 &gravity)
virtual void addCollisionObject(btCollisionObject *collisionObject, int collisionFilterGroup=btBroadphaseProxy::StaticFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter)
const btTransform & getCenterOfMassTransform() const
Definition: btRigidBody.h:359
btAlignedObjectArray< btTypedConstraint * > m_sortedConstraints
btScalar m_combinedRestitution
virtual void removeCharacter(btActionInterface *character)
obsolete, use removeAction instead
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
void setBasis(const btMatrix3x3 &basis)
Set the rotational element by btMatrix3x3.
Definition: btTransform.h:159
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
const btRigidBody & getRigidBodyB() const
virtual void startSerialization()=0
btTranslationalLimitMotor * getTranslationalLimitMotor()
Retrieves the limit informacion.
void integrateTransformsInternal(btRigidBody **bodies, int numBodies, btScalar timeStep)
bool wantsSleeping()
Definition: btRigidBody.h:438
btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis locatio...
bool gDisableDeactivation
Definition: btRigidBody.cpp:26
virtual void drawBox(const btVector3 &bbMin, const btVector3 &bbMax, const btVector3 &color)
Definition: btIDebugDraw.h:306
const btRigidBody & getRigidBodyA() const
SimulationIslandManager creates and handles simulation islands, using btUnionFind.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btScalar m_appliedImpulse
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
btInternalTickCallback m_internalTickCallback
#define btAssert(x)
Definition: btScalar.h:131
The btDynamicsWorld is the interface class for several dynamics implementation, basic,...
btCollisionConfiguration allows to configure Bullet collision detection stack allocator size,...
void buildAndProcessIslands(btDispatcher *dispatcher, btCollisionWorld *collisionWorld, IslandCallback *callback)
virtual btVector3 getGravity() const
btAlignedObjectArray< btActionInterface * > m_actions
virtual void processIsland(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifolds, int numManifolds, int islandId)
void setHitFraction(btScalar hitFraction)
#define BT_DYNAMICSWORLD_CODE
Definition: btSerializer.h:129
bool isKinematicObject() const
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
btScalar m_singleAxisRollingFrictionThreshold
btSimulationIslandManager * getSimulationIslandManager()
virtual void removeCollisionObject(btCollisionObject *collisionObject)
removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise ca...
#define SIMD_FORCE_INLINE
Definition: btScalar.h:81
virtual void removeAction(btActionInterface *)
The btSphereShape implements an implicit sphere, centered around a local origin with radius.
Definition: btSphereShape.h:22
virtual void drawArc(const btVector3 &center, const btVector3 &normal, const btVector3 &axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, const btVector3 &color, bool drawSect, btScalar stepDegrees=btScalar(10.f))
Definition: btIDebugDraw.h:174
Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWor...
btVector3 m_upperLimit
the constraint upper limits
ManifoldContactPoint collects and maintains persistent contactpoints.
int getActivationState() const
btDispatcher * m_dispatcher1
class btIDebugDraw * m_debugDraw
Definition: btDispatcher.h:58
virtual void updateActivationState(btCollisionWorld *colWorld, btDispatcher *dispatcher)
const btRigidBody & getRigidBodyB() const
const btTransform & getCalculatedTransformA() const
const btTransform & getAFrame() const
#define ISLAND_SLEEPING
bool isStaticOrKinematicObject() const
btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in lo...
btVector3FloatData m_gravity
btScalar getTwistAngle() const
The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
Definition: btStackAlloc.h:34
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:309
int getNumCollisionObjects() const
const btCollisionShape * getCollisionShape() const
Definition: btRigidBody.h:254
const btVector3 & getInterpolationLinearVelocity() const
const btTransform & getCalculatedTransformA() const
Gets the global transform of the offset for body A.
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
const btManifoldPoint & getContactPoint(int index) const
The btOverlappingPairCache provides an interface for overlapping pair management (add,...
btContactSolverInfoFloatData m_solverInfo
void updateDeactivation(btScalar timeStep)
Definition: btRigidBody.h:421
const btCollisionObject * m_hitCollisionObject
virtual void drawSpherePatch(const btVector3 &center, const btVector3 &up, const btVector3 &axis, btScalar radius, btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3 &color, btScalar stepDegrees=btScalar(10.f), bool drawCenter=true)
Definition: btIDebugDraw.h:199
btVector3 getColumn(int i) const
Get a column of the matrix as a vector.
Definition: btMatrix3x3.h:134
virtual btOverlappingPairCache * getOverlappingPairCache()=0
btCollisionWorld * getCollisionWorld()
#define SIMD_PI
Definition: btScalar.h:504
btTransform & getWorldTransform()
btVector3 m_normalWorldOnB
#define SIMD_2_PI
Definition: btScalar.h:505
btVector3 m_positionWorldOnB
btTranslationalLimitMotor2 * getTranslationalLimitMotor()
btInternalTickCallback m_internalPreTickCallback
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
btBroadphaseProxy * getBroadphaseHandle()
virtual void serialize(btSerializer *serializer)
Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see B...
const btVector3 & getLinearVelocity() const
Definition: btRigidBody.h:362
btIDebugDraw * m_debugDrawer
const btTransform & getCalculatedTransformB() const
Gets the global transform of the offset for body B.
btAlignedObjectArray< btCollisionObject * > m_bodies
virtual btIDebugDraw * getDebugDrawer()
btScalar getCcdSquareMotionThreshold() const
const btVector3 & getPositionWorldOnB() const
const btCollisionObject * getBody0() const
bool isEnabled() const
virtual btBroadphasePair * findPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1)=0
void addConstraintRef(btTypedConstraint *c)
bool isStaticObject() const
btScalar getInvMass() const
Definition: btRigidBody.h:273
const btBroadphaseProxy * getBroadphaseProxy() const
Definition: btRigidBody.h:460
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
ClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld)
virtual void predictUnconstraintMotion(btScalar timeStep)
const btTransform & getCalculatedTransformB() const
#define btAlignedFree(ptr)
btCollisionObject can be used to manage collision detection objects.
virtual void saveKinematicState(btScalar timeStep)
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
bool hasContactResponse() const
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:29
void setLinearVelocity(const btVector3 &lin_vel)
Definition: btRigidBody.h:370
const btTransform & getInterpolationWorldTransform() const
virtual void flushLines()
Definition: btIDebugDraw.h:476
btAlignedObjectArray< btPersistentManifold * > m_predictiveManifolds
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:62
btVector3 m_positionWorldOnA
m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
virtual void removeCollisionObject(btCollisionObject *collisionObject)
btVector3 m_lowerLimit
the constraint lower limits
int getFlags() const
Definition: btRigidBody.h:533
void clearForces()
Definition: btRigidBody.h:346
virtual btPersistentManifold * getNewManifold(const btCollisionObject *b0, const btCollisionObject *b1)=0
static void Reset(void)
virtual int calculateSerializeBufferSize() const
btRotationalLimitMotor2 * getRotationalLimitMotor(int index)
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
void proceedToTransform(const btTransform &newTrans)
btDispatcher * getDispatcher()
virtual btConstraintSolver * getConstraintSolver()
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace)
int gNumClampedCcdMotions
internal debugging variable. this value shouldn't be too high
btAlignedObjectArray< btPersistentManifold * > m_manifolds
The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
virtual int stepSimulation(btScalar timeStep, int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))
if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
virtual void createPredictiveContacts(btScalar timeStep)
btCollisionAlgorithm * m_algorithm
virtual void applyGravity()
apply gravity, call this once per timestep
The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (...
InplaceSolverIslandCallback(btConstraintSolver *solver, btStackAlloc *stackAlloc, btDispatcher *dispatcher)
static btScalar calculateCombinedFriction(const btCollisionObject *body0, const btCollisionObject *body1)
User can override this material combiner by implementing gContactAddedCallback and setting body0->m_c...
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
const btTransform & getAFrame() const
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)=0
static void integrateTransform(const btTransform &curTrans, const btVector3 &linvel, const btVector3 &angvel, btScalar timeStep, btTransform &predictedTransform)
int size() const
return the number of elements in the array
virtual void debugDrawConstraint(btTypedConstraint *constraint)
#define BT_PROFILE(name)
Definition: btQuickprof.h:215
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
void serialize(struct btVector3Data &dataOut) const
Definition: btVector3.h:1351
btScalar getCcdMotionThreshold() const
virtual void removeConstraint(btTypedConstraint *constraint)
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
static void Increment_Frame_Counter(void)
btScalar m_hiLimit
joint limit
CollisionWorld is interface and container for the collision detection.
virtual void allSolved(const btContactSolverInfo &, class btIDebugDraw *)
void updateActions(btScalar timeStep)
void applyDamping(btScalar timeStep)
applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
virtual btTypedConstraint * getConstraint(int index)
void convexSweepTest(const btConvexShape *castShape, const btTransform &from, const btTransform &to, ConvexResultCallback &resultCallback, btScalar allowedCcdPenetration=btScalar(0.)) const
convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultC...
int getIslandTag() const
btScalar getAngle(int axis_index) const
btDispatcherInfo & getDispatchInfo()
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
btScalar getHitFraction() const
virtual void prepareSolve(int, int)
#define WANTS_DEACTIVATION
void remove(const T &key)
btScalar m_allowedCcdPenetration
Definition: btDispatcher.h:62
virtual void drawTransform(const btTransform &transform, btScalar orthoLen)
Definition: btIDebugDraw.h:166
TypedConstraint is the baseclass for Bullet constraints and vehicles.
void synchronizeSingleMotionState(btRigidBody *body)
this can be useful to synchronize a single rigid body -> graphics object
void saveKinematicState(btScalar step)
void resize(int newsize, const T &fillData=T())
bool btFuzzyZero(btScalar x)
Definition: btScalar.h:550
virtual void integrateTransforms(btScalar timeStep)
const btCollisionObject * getBody1() const
btRotationalLimitMotor * getRotationalLimitMotor(int index)
Retrieves the angular limit informacion.
int getInternalType() const
reserved for Bullet internal usage
void btMutexUnlock(btSpinMutex *mutex)
Definition: btThreads.h:78
void setAngularVelocity(const btVector3 &ang_vel)
Definition: btRigidBody.h:376
virtual int getDebugMode() const =0
btClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &fromA, const btVector3 &toA, btOverlappingPairCache *pairCache, btDispatcher *dispatcher)
btAlignedObjectArray< btCollisionObject * > m_collisionObjects
btDiscreteDynamicsWorld(btDispatcher *dispatcher, btBroadphaseInterface *pairCache, btConstraintSolver *constraintSolver, btCollisionConfiguration *collisionConfiguration)
this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete thos...
#define BT_RIGIDBODY_CODE
Definition: btSerializer.h:120
virtual void storeIslandActivationState(btCollisionWorld *world)
virtual bool needsResponse(const btCollisionObject *body0, const btCollisionObject *body1)=0
#define DISABLE_DEACTIVATION
virtual void performDiscreteCollisionDetection()
btScalar m_combinedFriction
void btMutexLock(btSpinMutex *mutex)
Definition: btThreads.h:71
InplaceSolverIslandCallback * m_solverIslandCallback
virtual void addCharacter(btActionInterface *character)
obsolete, use addAction instead
#define btAlignedAlloc(size, alignment)
virtual int calculateSerializeBufferSize() const
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
btConstraintSolver * m_constraintSolver
btMotionState * getMotionState()
Definition: btRigidBody.h:474
btTypedConstraintType getConstraintType() const
void applyImpulse(const btVector3 &impulse, const btVector3 &rel_pos)
Definition: btRigidBody.h:334
void serializeRigidBodies(btSerializer *serializer)
virtual void updateActivationState(btScalar timeStep)
btScalar getAngle(int axis_index) const
Get the relative Euler angle.
btAlignedObjectArray< btTypedConstraint * > m_constraints
btScalar m_timeStep
Definition: btDispatcher.h:53
btScalar getCcdSweptSphereRadius() const
Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
void createPredictiveContactsInternal(btRigidBody **bodies, int numBodies, btScalar timeStep)
void unite(int p, int q)
Definition: btUnionFind.h:81
virtual void addVehicle(btActionInterface *vehicle)
obsolete, use addAction instead
InplaceSolverIslandCallback & operator=(InplaceSolverIslandCallback &other)
virtual bool needsCollision(btBroadphaseProxy *proxy0) const
virtual void removeRigidBody(btRigidBody *body)
virtual void debugDrawWorld()
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:75
void removeConstraintRef(btTypedConstraint *c)
const btRigidBody & getRigidBodyA() const
static btScalar calculateCombinedRestitution(const btCollisionObject *body0, const btCollisionObject *body1)
in the future we can let the user override the methods to combine restitution and friction
void * m_oldPtr
Definition: btSerializer.h:56
btContactSolverInfo & getSolverInfo()
const btBroadphaseInterface * getBroadphase() const
virtual void setWorldTransform(const btTransform &worldTrans)=0
void setActivationState(int newState) const
int addManifoldPoint(const btManifoldPoint &newPoint, bool isPredictive=false)
virtual btChunk * allocate(size_t size, int numElements)=0
const btTransform & getBFrame() const
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)
btScalar btCos(btScalar x)
Definition: btScalar.h:476
btAlignedObjectArray< btTypedConstraint * > m_constraints
void setGravity(const btVector3 &acceleration)
btTypedConstraint ** m_sortedConstraints
The btBroadphasePair class contains a pair of aabb-overlapping objects.