2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
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:
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.
17 #include "btDiscreteDynamicsWorld.h"
20 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
21 #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
22 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
23 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
24 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
25 #include "LinearMath/btTransformUtil.h"
26 #include "LinearMath/btQuickprof.h"
28 //rigidbody & constraints
29 #include "BulletDynamics/Dynamics/btRigidBody.h"
30 #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
31 #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
32 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
33 #include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
34 #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
35 #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
36 #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
37 #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
38 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
41 #include "LinearMath/btIDebugDraw.h"
42 #include "BulletCollision/CollisionShapes/btSphereShape.h"
45 #include "BulletDynamics/Dynamics/btActionInterface.h"
46 #include "LinearMath/btQuickprof.h"
47 #include "LinearMath/btMotionState.h"
49 #include "LinearMath/btSerializer.h"
52 btAlignedObjectArray<btVector3> debugContacts;
53 btAlignedObjectArray<btVector3> debugNormals;
55 int firstHit=startHit;
58 SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
62 const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
63 const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
64 islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
70 class btSortConstraintOnIslandPredicate
74 bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
76 int rIslandId0,lIslandId0;
77 rIslandId0 = btGetConstraintIslandId(rhs);
78 lIslandId0 = btGetConstraintIslandId(lhs);
79 return lIslandId0 < rIslandId0;
83 struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
85 btContactSolverInfo* m_solverInfo;
86 btConstraintSolver* m_solver;
87 btTypedConstraint** m_sortedConstraints;
89 btIDebugDraw* m_debugDrawer;
90 btStackAlloc* m_stackAlloc;
91 btDispatcher* m_dispatcher;
93 btAlignedObjectArray<btCollisionObject*> m_bodies;
94 btAlignedObjectArray<btPersistentManifold*> m_manifolds;
95 btAlignedObjectArray<btTypedConstraint*> m_constraints;
98 InplaceSolverIslandCallback(
99 btConstraintSolver* solver,
100 btStackAlloc* stackAlloc,
101 btDispatcher* dispatcher)
104 m_sortedConstraints(NULL),
107 m_stackAlloc(stackAlloc),
108 m_dispatcher(dispatcher)
113 InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
120 SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
122 btAssert(solverInfo);
123 m_solverInfo = solverInfo;
124 m_sortedConstraints = sortedConstraints;
125 m_numConstraints = numConstraints;
126 m_debugDrawer = debugDrawer;
128 m_manifolds.resize (0);
129 m_constraints.resize (0);
133 virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
137 ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
138 m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
141 //also add all non-contact constraints/joints for this island
142 btTypedConstraint** startConstraint = 0;
143 int numCurConstraints = 0;
146 //find the first constraint for this island
147 for (i=0;i<m_numConstraints;i++)
149 if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
151 startConstraint = &m_sortedConstraints[i];
155 //count the number of constraints in this island
156 for (;i<m_numConstraints;i++)
158 if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
164 if (m_solverInfo->m_minimumSolverBatchSize<=1)
166 m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
170 for (i=0;i<numBodies;i++)
171 m_bodies.push_back(bodies[i]);
172 for (i=0;i<numManifolds;i++)
173 m_manifolds.push_back(manifolds[i]);
174 for (i=0;i<numCurConstraints;i++)
175 m_constraints.push_back(startConstraint[i]);
176 if ((m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
178 processConstraints();
181 //printf("deferred\n");
186 void processConstraints()
189 btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
190 btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
191 btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
193 m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
195 m_manifolds.resize(0);
196 m_constraints.resize(0);
204 btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
205 :btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
206 m_sortedConstraints (),
207 m_solverIslandCallback ( NULL ),
208 m_constraintSolver(constraintSolver),
211 m_synchronizeAllMotionStates(false),
212 m_applySpeculativeContactRestitution(false),
216 if (!m_constraintSolver)
218 void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
219 m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
220 m_ownsConstraintSolver = true;
223 m_ownsConstraintSolver = false;
227 void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
228 m_islandManager = new (mem) btSimulationIslandManager();
231 m_ownsIslandManager = true;
234 void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
235 m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, m_stackAlloc, dispatcher);
240 btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
242 //only delete it when we created it
243 if (m_ownsIslandManager)
245 m_islandManager->~btSimulationIslandManager();
246 btAlignedFree( m_islandManager);
248 if (m_solverIslandCallback)
250 m_solverIslandCallback->~InplaceSolverIslandCallback();
251 btAlignedFree(m_solverIslandCallback);
253 if (m_ownsConstraintSolver)
256 m_constraintSolver->~btConstraintSolver();
257 btAlignedFree(m_constraintSolver);
261 void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
263 ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
264 ///to switch status _after_ adding kinematic objects to the world
265 ///fix it for Bullet 3.x release
266 for (int i=0;i<m_collisionObjects.size();i++)
268 btCollisionObject* colObj = m_collisionObjects[i];
269 btRigidBody* body = btRigidBody::upcast(colObj);
270 if (body && body->getActivationState() != ISLAND_SLEEPING)
272 if (body->isKinematicObject())
274 //to calculate velocities next frame
275 body->saveKinematicState(timeStep);
282 void btDiscreteDynamicsWorld::debugDrawWorld()
284 BT_PROFILE("debugDrawWorld");
286 btCollisionWorld::debugDrawWorld();
288 bool drawConstraints = false;
289 if (getDebugDrawer())
291 int mode = getDebugDrawer()->getDebugMode();
292 if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
294 drawConstraints = true;
299 for(int i = getNumConstraints()-1; i>=0 ;i--)
301 btTypedConstraint* constraint = getConstraint(i);
302 debugDrawConstraint(constraint);
308 if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
312 if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
314 for (i=0;i<m_actions.size();i++)
316 m_actions[i]->debugDraw(m_debugDrawer);
322 void btDiscreteDynamicsWorld::clearForces()
324 ///@todo: iterate over awake simulation islands!
325 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
327 btRigidBody* body = m_nonStaticRigidBodies[i];
328 //need to check if next line is ok
329 //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
334 ///apply gravity, call this once per timestep
335 void btDiscreteDynamicsWorld::applyGravity()
337 ///@todo: iterate over awake simulation islands!
338 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
340 btRigidBody* body = m_nonStaticRigidBodies[i];
341 if (body->isActive())
343 body->applyGravity();
349 void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
353 if (body->getMotionState() && !body->isStaticOrKinematicObject())
355 //we need to call the update at least once, even for sleeping objects
356 //otherwise the 'graphics' transform never updates properly
357 ///@todo: add 'dirty' flag
358 //if (body->getActivationState() != ISLAND_SLEEPING)
360 btTransform interpolatedTransform;
361 btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
362 body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform);
363 body->getMotionState()->setWorldTransform(interpolatedTransform);
369 void btDiscreteDynamicsWorld::synchronizeMotionStates()
371 BT_PROFILE("synchronizeMotionStates");
372 if (m_synchronizeAllMotionStates)
374 //iterate over all collision objects
375 for ( int i=0;i<m_collisionObjects.size();i++)
377 btCollisionObject* colObj = m_collisionObjects[i];
378 btRigidBody* body = btRigidBody::upcast(colObj);
380 synchronizeSingleMotionState(body);
384 //iterate over all active rigid bodies
385 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
387 btRigidBody* body = m_nonStaticRigidBodies[i];
388 if (body->isActive())
389 synchronizeSingleMotionState(body);
395 int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
397 startProfiling(timeStep);
399 BT_PROFILE("stepSimulation");
401 int numSimulationSubSteps = 0;
405 //fixed timestep with interpolation
406 m_localTime += timeStep;
407 if (m_localTime >= fixedTimeStep)
409 numSimulationSubSteps = int( m_localTime / fixedTimeStep);
410 m_localTime -= numSimulationSubSteps * fixedTimeStep;
415 fixedTimeStep = timeStep;
416 m_localTime = timeStep;
417 if (btFuzzyZero(timeStep))
419 numSimulationSubSteps = 0;
423 numSimulationSubSteps = 1;
428 //process some debugging flags
429 if (getDebugDrawer())
431 btIDebugDraw* debugDrawer = getDebugDrawer ();
432 gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
434 if (numSimulationSubSteps)
437 //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
438 int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
440 saveKinematicState(fixedTimeStep*clampedSimulationSteps);
446 for (int i=0;i<clampedSimulationSteps;i++)
448 internalSingleStepSimulation(fixedTimeStep);
449 synchronizeMotionStates();
454 synchronizeMotionStates();
459 #ifndef BT_NO_PROFILE
460 CProfileManager::Increment_Frame_Counter();
461 #endif //BT_NO_PROFILE
463 return numSimulationSubSteps;
466 void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
469 BT_PROFILE("internalSingleStepSimulation");
471 if(0 != m_internalPreTickCallback) {
472 (*m_internalPreTickCallback)(this, timeStep);
475 ///apply gravity, predict motion
476 predictUnconstraintMotion(timeStep);
478 btDispatcherInfo& dispatchInfo = getDispatchInfo();
480 dispatchInfo.m_timeStep = timeStep;
481 dispatchInfo.m_stepCount = 0;
482 dispatchInfo.m_debugDraw = getDebugDrawer();
485 createPredictiveContacts(timeStep);
487 ///perform collision detection
488 performDiscreteCollisionDetection();
490 calculateSimulationIslands();
493 getSolverInfo().m_timeStep = timeStep;
497 ///solve contact and other joint constraints
498 solveConstraints(getSolverInfo());
500 ///CallbackTriggers();
502 ///integrate transforms
504 integrateTransforms(timeStep);
506 ///update vehicle simulation
507 updateActions(timeStep);
509 updateActivationState( timeStep );
511 if(0 != m_internalTickCallback) {
512 (*m_internalTickCallback)(this, timeStep);
516 void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
519 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
521 btRigidBody* body = m_nonStaticRigidBodies[i];
522 if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
524 body->setGravity(gravity);
529 btVector3 btDiscreteDynamicsWorld::getGravity () const
534 void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
536 btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
539 void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
541 btRigidBody* body = btRigidBody::upcast(collisionObject);
543 removeRigidBody(body);
545 btCollisionWorld::removeCollisionObject(collisionObject);
548 void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
550 m_nonStaticRigidBodies.remove(body);
551 btCollisionWorld::removeCollisionObject(body);
555 void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
557 if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
559 body->setGravity(m_gravity);
562 if (body->getCollisionShape())
564 if (!body->isStaticObject())
566 m_nonStaticRigidBodies.push_back(body);
569 body->setActivationState(ISLAND_SLEEPING);
572 bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
573 short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
574 short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
576 addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
580 void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
582 if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
584 body->setGravity(m_gravity);
587 if (body->getCollisionShape())
589 if (!body->isStaticObject())
591 m_nonStaticRigidBodies.push_back(body);
595 body->setActivationState(ISLAND_SLEEPING);
597 addCollisionObject(body,group,mask);
602 void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
604 BT_PROFILE("updateActions");
606 for ( int i=0;i<m_actions.size();i++)
608 m_actions[i]->updateAction( this, timeStep);
613 void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
615 BT_PROFILE("updateActivationState");
617 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
619 btRigidBody* body = m_nonStaticRigidBodies[i];
622 body->updateDeactivation(timeStep);
624 if (body->wantsSleeping())
626 if (body->isStaticOrKinematicObject())
628 body->setActivationState(ISLAND_SLEEPING);
631 if (body->getActivationState() == ACTIVE_TAG)
632 body->setActivationState( WANTS_DEACTIVATION );
633 if (body->getActivationState() == ISLAND_SLEEPING)
635 body->setAngularVelocity(btVector3(0,0,0));
636 body->setLinearVelocity(btVector3(0,0,0));
642 if (body->getActivationState() != DISABLE_DEACTIVATION)
643 body->setActivationState( ACTIVE_TAG );
649 void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
651 m_constraints.push_back(constraint);
652 if (disableCollisionsBetweenLinkedBodies)
654 constraint->getRigidBodyA().addConstraintRef(constraint);
655 constraint->getRigidBodyB().addConstraintRef(constraint);
659 void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
661 m_constraints.remove(constraint);
662 constraint->getRigidBodyA().removeConstraintRef(constraint);
663 constraint->getRigidBodyB().removeConstraintRef(constraint);
666 void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
668 m_actions.push_back(action);
671 void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
673 m_actions.remove(action);
677 void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
682 void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
684 removeAction(vehicle);
687 void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
689 addAction(character);
692 void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
694 removeAction(character);
700 void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
702 BT_PROFILE("solveConstraints");
704 m_sortedConstraints.resize( m_constraints.size());
706 for (i=0;i<getNumConstraints();i++)
708 m_sortedConstraints[i] = m_constraints[i];
715 m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
717 btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
719 m_solverIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer());
720 m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
722 /// solve all the constraints for this island
723 m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback);
725 m_solverIslandCallback->processConstraints();
727 m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc);
731 void btDiscreteDynamicsWorld::calculateSimulationIslands()
733 BT_PROFILE("calculateSimulationIslands");
735 getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
738 //merge islands based on speculative contact manifolds too
739 for (int i=0;i<this->m_predictiveManifolds.size();i++)
741 btPersistentManifold* manifold = m_predictiveManifolds[i];
743 const btCollisionObject* colObj0 = manifold->getBody0();
744 const btCollisionObject* colObj1 = manifold->getBody1();
746 if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
747 ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
749 if (colObj0->isActive() || colObj1->isActive())
752 getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
753 (colObj1)->getIslandTag());
761 int numConstraints = int(m_constraints.size());
762 for (i=0;i< numConstraints ; i++ )
764 btTypedConstraint* constraint = m_constraints[i];
765 if (constraint->isEnabled())
767 const btRigidBody* colObj0 = &constraint->getRigidBodyA();
768 const btRigidBody* colObj1 = &constraint->getRigidBodyB();
770 if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
771 ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
773 if (colObj0->isActive() || colObj1->isActive())
776 getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
777 (colObj1)->getIslandTag());
784 //Store the island id in each body
785 getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
793 class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
797 btCollisionObject* m_me;
798 btScalar m_allowedPenetration;
799 btOverlappingPairCache* m_pairCache;
800 btDispatcher* m_dispatcher;
803 btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
804 btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
806 m_allowedPenetration(0.0f),
807 m_pairCache(pairCache),
808 m_dispatcher(dispatcher)
812 virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
814 if (convexResult.m_hitCollisionObject == m_me)
817 //ignore result if there is no contact response
818 if(!convexResult.m_hitCollisionObject->hasContactResponse())
821 btVector3 linVelA,linVelB;
822 linVelA = m_convexToWorld-m_convexFromWorld;
823 linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
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)
830 return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
833 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
835 //don't collide with itself
836 if (proxy0->m_clientObject == m_me)
839 ///don't do CCD when the collision filters are not matching
840 if (!ClosestConvexResultCallback::needsCollision(proxy0))
843 btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
845 //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
846 if (m_dispatcher->needsResponse(m_me,otherObj))
849 ///don't do CCD when there are already contact points (touching contact/penetration)
850 btAlignedObjectArray<btPersistentManifold*> manifoldArray;
851 btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
854 if (collisionPair->m_algorithm)
856 manifoldArray.resize(0);
857 collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
858 for (int j=0;j<manifoldArray.size();j++)
860 btPersistentManifold* manifold = manifoldArray[j];
861 if (manifold->getNumContacts()>0)
876 ///internal debugging variable. this value shouldn't be too high
877 int gNumClampedCcdMotions=0;
880 void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
882 BT_PROFILE("createPredictiveContacts");
885 BT_PROFILE("release predictive contact manifolds");
887 for (int i=0;i<m_predictiveManifolds.size();i++)
889 btPersistentManifold* manifold = m_predictiveManifolds[i];
890 this->m_dispatcher1->releaseManifold(manifold);
892 m_predictiveManifolds.clear();
895 btTransform predictedTrans;
896 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
898 btRigidBody* body = m_nonStaticRigidBodies[i];
899 body->setHitFraction(1.f);
901 if (body->isActive() && (!body->isStaticOrKinematicObject()))
904 body->predictIntegratedTransform(timeStep, predictedTrans);
906 btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
908 if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
910 BT_PROFILE("predictive convexSweepTest");
911 if (body->getCollisionShape()->isConvex())
913 gNumClampedCcdMotions++;
914 #ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
915 class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
919 StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
920 btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
924 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
926 btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
927 if (!otherObj->isStaticOrKinematicObject())
929 return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
933 StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
935 btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
937 //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
938 btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
939 sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
941 sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
942 sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
943 btTransform modifiedPredictedTrans = predictedTrans;
944 modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
946 convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
947 if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
950 btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
951 btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
954 btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
955 m_predictiveManifolds.push_back(manifold);
957 btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
958 btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
960 btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
962 bool isPredictive = true;
963 int index = manifold->addManifoldPoint(newPoint, isPredictive);
964 btManifoldPoint& pt = manifold->getContactPoint(index);
965 pt.m_combinedRestitution = 0;
966 pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject);
967 pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
968 pt.m_positionWorldOnB = worldPointB;
976 void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
978 BT_PROFILE("integrateTransforms");
979 btTransform predictedTrans;
980 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
982 btRigidBody* body = m_nonStaticRigidBodies[i];
983 body->setHitFraction(1.f);
985 if (body->isActive() && (!body->isStaticOrKinematicObject()))
988 body->predictIntegratedTransform(timeStep, predictedTrans);
990 btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
994 if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
996 BT_PROFILE("CCD motion clamping");
997 if (body->getCollisionShape()->isConvex())
999 gNumClampedCcdMotions++;
1000 #ifdef USE_STATIC_ONLY
1001 class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
1005 StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
1006 btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
1010 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
1012 btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
1013 if (!otherObj->isStaticOrKinematicObject())
1015 return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
1019 StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
1021 btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
1023 //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
1024 btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
1025 sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
1027 sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
1028 sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
1029 btTransform modifiedPredictedTrans = predictedTrans;
1030 modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
1032 convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
1033 if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
1036 //printf("clamped integration to hit fraction = %f\n",fraction);
1037 body->setHitFraction(sweepResults.m_closestHitFraction);
1038 body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
1039 body->setHitFraction(0.f);
1040 body->proceedToTransform( predictedTrans);
1043 btVector3 linVel = body->getLinearVelocity();
1045 btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
1046 btScalar maxSpeedSqr = maxSpeed*maxSpeed;
1047 if (linVel.length2()>maxSpeedSqr)
1051 body->setLinearVelocity(linVel);
1052 btScalar ms2 = body->getLinearVelocity().length2();
1053 body->predictIntegratedTransform(timeStep, predictedTrans);
1055 btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
1056 btScalar smt = body->getCcdSquareMotionThreshold();
1057 printf("sm2=%f\n",sm2);
1061 //don't apply the collision response right now, it will happen next frame
1062 //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
1063 //btScalar appliedImpulse = 0.f;
1064 //btScalar depth = 0.f;
1065 //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
1076 body->proceedToTransform( predictedTrans);
1082 ///this should probably be switched on by default, but it is not well tested yet
1083 if (m_applySpeculativeContactRestitution)
1085 BT_PROFILE("apply speculative contact restitution");
1086 for (int i=0;i<m_predictiveManifolds.size();i++)
1088 btPersistentManifold* manifold = m_predictiveManifolds[i];
1089 btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
1090 btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
1092 for (int p=0;p<manifold->getNumContacts();p++)
1094 const btManifoldPoint& pt = manifold->getContactPoint(p);
1095 btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1);
1097 if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
1098 //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
1100 btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
1102 const btVector3& pos1 = pt.getPositionWorldOnA();
1103 const btVector3& pos2 = pt.getPositionWorldOnB();
1105 btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
1106 btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
1109 body0->applyImpulse(imp,rel_pos0);
1111 body1->applyImpulse(-imp,rel_pos1);
1124 void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
1126 BT_PROFILE("predictUnconstraintMotion");
1127 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
1129 btRigidBody* body = m_nonStaticRigidBodies[i];
1130 if (!body->isStaticOrKinematicObject())
1132 //don't integrate/update velocities here, it happens in the constraint solver
1135 body->applyDamping(timeStep);
1137 body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
1143 void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
1147 #ifndef BT_NO_PROFILE
1148 CProfileManager::Reset();
1149 #endif //BT_NO_PROFILE
1158 void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
1160 bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
1161 bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
1162 btScalar dbgDrawSize = constraint->getDbgDrawSize();
1163 if(dbgDrawSize <= btScalar(0.f))
1168 switch(constraint->getConstraintType())
1170 case POINT2POINT_CONSTRAINT_TYPE:
1172 btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
1175 btVector3 pivot = p2pC->getPivotInA();
1176 pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
1177 tr.setOrigin(pivot);
1178 getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1179 // that ideally should draw the same frame
1180 pivot = p2pC->getPivotInB();
1181 pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
1182 tr.setOrigin(pivot);
1183 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1186 case HINGE_CONSTRAINT_TYPE:
1188 btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
1189 btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
1190 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1191 tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
1192 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1193 btScalar minAng = pHinge->getLowerLimit();
1194 btScalar maxAng = pHinge->getUpperLimit();
1195 if(minAng == maxAng)
1199 bool drawSect = true;
1202 minAng = btScalar(0.f);
1208 btVector3& center = tr.getOrigin();
1209 btVector3 normal = tr.getBasis().getColumn(2);
1210 btVector3 axis = tr.getBasis().getColumn(0);
1211 getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
1215 case CONETWIST_CONSTRAINT_TYPE:
1217 btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
1218 btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
1219 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1220 tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
1221 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1224 //const btScalar length = btScalar(5);
1225 const btScalar length = dbgDrawSize;
1226 static int nSegments = 8*4;
1227 btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
1228 btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
1230 for (int i=0; i<nSegments; i++)
1232 fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
1233 btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
1235 getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
1237 if (i%(nSegments/8) == 0)
1238 getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
1242 btScalar tws = pCT->getTwistSpan();
1243 btScalar twa = pCT->getTwistAngle();
1244 bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
1247 tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
1251 tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
1253 btVector3 pivot = tr.getOrigin();
1254 btVector3 normal = tr.getBasis().getColumn(0);
1255 btVector3 axis1 = tr.getBasis().getColumn(1);
1256 getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
1261 case D6_SPRING_CONSTRAINT_TYPE:
1262 case D6_CONSTRAINT_TYPE:
1264 btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
1265 btTransform tr = p6DOF->getCalculatedTransformA();
1266 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1267 tr = p6DOF->getCalculatedTransformB();
1268 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1271 tr = p6DOF->getCalculatedTransformA();
1272 const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
1273 btVector3 up = tr.getBasis().getColumn(2);
1274 btVector3 axis = tr.getBasis().getColumn(0);
1275 btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
1276 btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
1277 btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
1278 btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
1279 getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
1280 axis = tr.getBasis().getColumn(1);
1281 btScalar ay = p6DOF->getAngle(1);
1282 btScalar az = p6DOF->getAngle(2);
1283 btScalar cy = btCos(ay);
1284 btScalar sy = btSin(ay);
1285 btScalar cz = btCos(az);
1286 btScalar sz = btSin(az);
1288 ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
1289 ref[1] = -sz*axis[0] + cz*axis[1];
1290 ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
1291 tr = p6DOF->getCalculatedTransformB();
1292 btVector3 normal = -tr.getBasis().getColumn(0);
1293 btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
1294 btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
1297 getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
1299 else if(minFi < maxFi)
1301 getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
1303 tr = p6DOF->getCalculatedTransformA();
1304 btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
1305 btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
1306 getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
1310 case SLIDER_CONSTRAINT_TYPE:
1312 btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
1313 btTransform tr = pSlider->getCalculatedTransformA();
1314 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1315 tr = pSlider->getCalculatedTransformB();
1316 if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
1319 btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
1320 btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
1321 btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
1322 getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
1323 btVector3 normal = tr.getBasis().getColumn(0);
1324 btVector3 axis = tr.getBasis().getColumn(1);
1325 btScalar a_min = pSlider->getLowerAngLimit();
1326 btScalar a_max = pSlider->getUpperAngLimit();
1327 const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
1328 getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
1342 void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
1344 if (m_ownsConstraintSolver)
1346 btAlignedFree( m_constraintSolver);
1348 m_ownsConstraintSolver = false;
1349 m_constraintSolver = solver;
1350 m_solverIslandCallback->m_solver = solver;
1353 btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
1355 return m_constraintSolver;
1359 int btDiscreteDynamicsWorld::getNumConstraints() const
1361 return int(m_constraints.size());
1363 btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
1365 return m_constraints[index];
1367 const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
1369 return m_constraints[index];
1374 void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
1377 //serialize all collision objects
1378 for (i=0;i<m_collisionObjects.size();i++)
1380 btCollisionObject* colObj = m_collisionObjects[i];
1381 if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
1383 int len = colObj->calculateSerializeBufferSize();
1384 btChunk* chunk = serializer->allocate(len,1);
1385 const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
1386 serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
1390 for (i=0;i<m_constraints.size();i++)
1392 btTypedConstraint* constraint = m_constraints[i];
1393 int size = constraint->calculateSerializeBufferSize();
1394 btChunk* chunk = serializer->allocate(size,1);
1395 const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
1396 serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
1403 void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
1405 #ifdef BT_USE_DOUBLE_PRECISION
1406 int len = sizeof(btDynamicsWorldDoubleData);
1407 btChunk* chunk = serializer->allocate(len,1);
1408 btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
1409 #else//BT_USE_DOUBLE_PRECISION
1410 int len = sizeof(btDynamicsWorldFloatData);
1411 btChunk* chunk = serializer->allocate(len,1);
1412 btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
1413 #endif//BT_USE_DOUBLE_PRECISION
1415 memset(worldInfo ,0x00,len);
1417 m_gravity.serialize(worldInfo->m_gravity);
1418 worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
1419 worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
1420 worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
1421 worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
1423 worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
1424 worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
1425 worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
1426 worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
1428 worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
1429 worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
1430 worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
1431 worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
1433 worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
1434 worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
1435 worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
1436 worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
1438 worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
1439 worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
1440 worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
1441 worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
1443 worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
1445 #ifdef BT_USE_DOUBLE_PRECISION
1446 const char* structType = "btDynamicsWorldDoubleData";
1447 #else//BT_USE_DOUBLE_PRECISION
1448 const char* structType = "btDynamicsWorldFloatData";
1449 #endif//BT_USE_DOUBLE_PRECISION
1450 serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
1453 void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
1456 serializer->startSerialization();
1458 serializeDynamicsWorldInfo(serializer);
1460 serializeRigidBodies(serializer);
1462 serializeCollisionObjects(serializer);
1464 serializer->finishSerialization();