Home | History | Annotate | Download | only in Dynamics
      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 
     17 #include "btDiscreteDynamicsWorld.h"
     18 
     19 //collision detection
     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"
     27 
     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/btGeneric6DofSpring2Constraint.h"
     38 #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
     39 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
     40 
     41 
     42 #include "LinearMath/btIDebugDraw.h"
     43 #include "BulletCollision/CollisionShapes/btSphereShape.h"
     44 
     45 
     46 #include "BulletDynamics/Dynamics/btActionInterface.h"
     47 #include "LinearMath/btQuickprof.h"
     48 #include "LinearMath/btMotionState.h"
     49 
     50 #include "LinearMath/btSerializer.h"
     51 
     52 #if 0
     53 btAlignedObjectArray<btVector3> debugContacts;
     54 btAlignedObjectArray<btVector3> debugNormals;
     55 int startHit=2;
     56 int firstHit=startHit;
     57 #endif
     58 
     59 SIMD_FORCE_INLINE	int	btGetConstraintIslandId(const btTypedConstraint* lhs)
     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 
     71 class btSortConstraintOnIslandPredicate
     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 
     84 struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
     85 {
     86 	btContactSolverInfo*	m_solverInfo;
     87 	btConstraintSolver*		m_solver;
     88 	btTypedConstraint**		m_sortedConstraints;
     89 	int						m_numConstraints;
     90 	btIDebugDraw*			m_debugDrawer;
     91 	btDispatcher*			m_dispatcher;
     92 
     93 	btAlignedObjectArray<btCollisionObject*> m_bodies;
     94 	btAlignedObjectArray<btPersistentManifold*> m_manifolds;
     95 	btAlignedObjectArray<btTypedConstraint*> m_constraints;
     96 
     97 
     98 	InplaceSolverIslandCallback(
     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 
    112 	InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
    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 		{
    136 			///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
    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 
    163 			if (m_solverInfo->m_minimumSolverBatchSize<=1)
    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]);
    175 				if ((m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
    176 				{
    177 					processConstraints();
    178 				} else
    179 				{
    180 					//printf("deferred\n");
    181 				}
    182 			}
    183 		}
    184 	}
    185 	void	processConstraints()
    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 
    192 		m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_dispatcher);
    193 		m_bodies.resize(0);
    194 		m_manifolds.resize(0);
    195 		m_constraints.resize(0);
    196 
    197 	}
    198 
    199 };
    200 
    201 
    202 
    203 btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
    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);
    220 		m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
    221 		m_ownsConstraintSolver = true;
    222 	} else
    223 	{
    224 		m_ownsConstraintSolver = false;
    225 	}
    226 
    227 	{
    228 		void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
    229 		m_islandManager = new (mem) btSimulationIslandManager();
    230 	}
    231 
    232 	m_ownsIslandManager = true;
    233 
    234 	{
    235 		void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
    236 		m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, 0, dispatcher);
    237 	}
    238 }
    239 
    240 
    241 btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
    242 {
    243 	//only delete it when we created it
    244 	if (m_ownsIslandManager)
    245 	{
    246 		m_islandManager->~btSimulationIslandManager();
    247 		btAlignedFree( m_islandManager);
    248 	}
    249 	if (m_solverIslandCallback)
    250 	{
    251 		m_solverIslandCallback->~InplaceSolverIslandCallback();
    252 		btAlignedFree(m_solverIslandCallback);
    253 	}
    254 	if (m_ownsConstraintSolver)
    255 	{
    256 
    257 		m_constraintSolver->~btConstraintSolver();
    258 		btAlignedFree(m_constraintSolver);
    259 	}
    260 }
    261 
    262 void	btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
    263 {
    264 ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
    265 ///to switch status _after_ adding kinematic objects to the world
    266 ///fix it for Bullet 3.x release
    267 	for (int i=0;i<m_collisionObjects.size();i++)
    268 	{
    269 		btCollisionObject* colObj = m_collisionObjects[i];
    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 
    283 void	btDiscreteDynamicsWorld::debugDrawWorld()
    284 {
    285 	BT_PROFILE("debugDrawWorld");
    286 
    287 	btCollisionWorld::debugDrawWorld();
    288 
    289 	bool drawConstraints = false;
    290 	if (getDebugDrawer())
    291 	{
    292 		int mode = getDebugDrawer()->getDebugMode();
    293 		if(mode  & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
    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 
    309     if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
    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())
    322         getDebugDrawer()->flushLines();
    323 
    324 }
    325 
    326 void	btDiscreteDynamicsWorld::clearForces()
    327 {
    328 	///@todo: iterate over awake simulation islands!
    329 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    330 	{
    331 		btRigidBody* body = m_nonStaticRigidBodies[i];
    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 
    338 ///apply gravity, call this once per timestep
    339 void	btDiscreteDynamicsWorld::applyGravity()
    340 {
    341 	///@todo: iterate over awake simulation islands!
    342 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    343 	{
    344 		btRigidBody* body = m_nonStaticRigidBodies[i];
    345 		if (body->isActive())
    346 		{
    347 			body->applyGravity();
    348 		}
    349 	}
    350 }
    351 
    352 
    353 void	btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
    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
    361 		///@todo: add 'dirty' flag
    362 		//if (body->getActivationState() != ISLAND_SLEEPING)
    363 		{
    364 			btTransform interpolatedTransform;
    365 			btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
    366 				body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
    367 				(m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
    368 				interpolatedTransform);
    369 			body->getMotionState()->setWorldTransform(interpolatedTransform);
    370 		}
    371 	}
    372 }
    373 
    374 
    375 void	btDiscreteDynamicsWorld::synchronizeMotionStates()
    376 {
    377 	BT_PROFILE("synchronizeMotionStates");
    378 	if (m_synchronizeAllMotionStates)
    379 	{
    380 		//iterate  over all collision objects
    381 		for ( int i=0;i<m_collisionObjects.size();i++)
    382 		{
    383 			btCollisionObject* colObj = m_collisionObjects[i];
    384 			btRigidBody* body = btRigidBody::upcast(colObj);
    385 			if (body)
    386 				synchronizeSingleMotionState(body);
    387 		}
    388 	} else
    389 	{
    390 		//iterate over all active rigid bodies
    391 		for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    392 		{
    393 			btRigidBody* body = m_nonStaticRigidBodies[i];
    394 			if (body->isActive())
    395 				synchronizeSingleMotionState(body);
    396 		}
    397 	}
    398 }
    399 
    400 
    401 int	btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
    402 {
    403 	startProfiling(timeStep);
    404 
    405 	BT_PROFILE("stepSimulation");
    406 
    407 	int numSimulationSubSteps = 0;
    408 
    409 	if (maxSubSteps)
    410 	{
    411 		//fixed timestep with interpolation
    412 		m_fixedTimeStep = fixedTimeStep;
    413 		m_localTime += timeStep;
    414 		if (m_localTime >= fixedTimeStep)
    415 		{
    416 			numSimulationSubSteps = int( m_localTime / fixedTimeStep);
    417 			m_localTime -= numSimulationSubSteps * fixedTimeStep;
    418 		}
    419 	} else
    420 	{
    421 		//variable timestep
    422 		fixedTimeStep = timeStep;
    423 		m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
    424 		m_fixedTimeStep = 0;
    425 		if (btFuzzyZero(timeStep))
    426 		{
    427 			numSimulationSubSteps = 0;
    428 			maxSubSteps = 0;
    429 		} else
    430 		{
    431 			numSimulationSubSteps = 1;
    432 			maxSubSteps = 1;
    433 		}
    434 	}
    435 
    436 	//process some debugging flags
    437 	if (getDebugDrawer())
    438 	{
    439 		btIDebugDraw* debugDrawer = getDebugDrawer ();
    440 		gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
    441 	}
    442 	if (numSimulationSubSteps)
    443 	{
    444 
    445 		//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
    446 		int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
    447 
    448 		saveKinematicState(fixedTimeStep*clampedSimulationSteps);
    449 
    450 		applyGravity();
    451 
    452 
    453 
    454 		for (int i=0;i<clampedSimulationSteps;i++)
    455 		{
    456 			internalSingleStepSimulation(fixedTimeStep);
    457 			synchronizeMotionStates();
    458 		}
    459 
    460 	} else
    461 	{
    462 		synchronizeMotionStates();
    463 	}
    464 
    465 	clearForces();
    466 
    467 #ifndef BT_NO_PROFILE
    468 	CProfileManager::Increment_Frame_Counter();
    469 #endif //BT_NO_PROFILE
    470 
    471 	return numSimulationSubSteps;
    472 }
    473 
    474 void	btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
    475 {
    476 
    477 	BT_PROFILE("internalSingleStepSimulation");
    478 
    479 	if(0 != m_internalPreTickCallback) {
    480 		(*m_internalPreTickCallback)(this, timeStep);
    481 	}
    482 
    483 	///apply gravity, predict motion
    484 	predictUnconstraintMotion(timeStep);
    485 
    486 	btDispatcherInfo& dispatchInfo = getDispatchInfo();
    487 
    488 	dispatchInfo.m_timeStep = timeStep;
    489 	dispatchInfo.m_stepCount = 0;
    490 	dispatchInfo.m_debugDraw = getDebugDrawer();
    491 
    492 
    493     createPredictiveContacts(timeStep);
    494 
    495 	///perform collision detection
    496 	performDiscreteCollisionDetection();
    497 
    498 	calculateSimulationIslands();
    499 
    500 
    501 	getSolverInfo().m_timeStep = timeStep;
    502 
    503 
    504 
    505 	///solve contact and other joint constraints
    506 	solveConstraints(getSolverInfo());
    507 
    508 	///CallbackTriggers();
    509 
    510 	///integrate transforms
    511 
    512 	integrateTransforms(timeStep);
    513 
    514 	///update vehicle simulation
    515 	updateActions(timeStep);
    516 
    517 	updateActivationState( timeStep );
    518 
    519 	if(0 != m_internalTickCallback) {
    520 		(*m_internalTickCallback)(this, timeStep);
    521 	}
    522 }
    523 
    524 void	btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
    525 {
    526 	m_gravity = gravity;
    527 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    528 	{
    529 		btRigidBody* body = m_nonStaticRigidBodies[i];
    530 		if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
    531 		{
    532 			body->setGravity(gravity);
    533 		}
    534 	}
    535 }
    536 
    537 btVector3 btDiscreteDynamicsWorld::getGravity () const
    538 {
    539 	return m_gravity;
    540 }
    541 
    542 void	btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
    543 {
    544 	btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
    545 }
    546 
    547 void	btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
    548 {
    549 	btRigidBody* body = btRigidBody::upcast(collisionObject);
    550 	if (body)
    551 		removeRigidBody(body);
    552 	else
    553 		btCollisionWorld::removeCollisionObject(collisionObject);
    554 }
    555 
    556 void	btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
    557 {
    558 	m_nonStaticRigidBodies.remove(body);
    559 	btCollisionWorld::removeCollisionObject(body);
    560 }
    561 
    562 
    563 void	btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
    564 {
    565 	if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
    566 	{
    567 		body->setGravity(m_gravity);
    568 	}
    569 
    570 	if (body->getCollisionShape())
    571 	{
    572 		if (!body->isStaticObject())
    573 		{
    574 			m_nonStaticRigidBodies.push_back(body);
    575 		} else
    576 		{
    577 			body->setActivationState(ISLAND_SLEEPING);
    578 		}
    579 
    580 		bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
    581 		short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
    582 		short collisionFilterMask = isDynamic? 	short(btBroadphaseProxy::AllFilter) : 	short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
    583 
    584 		addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
    585 	}
    586 }
    587 
    588 void	btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
    589 {
    590 	if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
    591 	{
    592 		body->setGravity(m_gravity);
    593 	}
    594 
    595 	if (body->getCollisionShape())
    596 	{
    597 		if (!body->isStaticObject())
    598 		{
    599 			m_nonStaticRigidBodies.push_back(body);
    600 		}
    601 		 else
    602 		{
    603 			body->setActivationState(ISLAND_SLEEPING);
    604 		}
    605 		addCollisionObject(body,group,mask);
    606 	}
    607 }
    608 
    609 
    610 void	btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
    611 {
    612 	BT_PROFILE("updateActions");
    613 
    614 	for ( int i=0;i<m_actions.size();i++)
    615 	{
    616 		m_actions[i]->updateAction( this, timeStep);
    617 	}
    618 }
    619 
    620 
    621 void	btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
    622 {
    623 	BT_PROFILE("updateActivationState");
    624 
    625 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    626 	{
    627 		btRigidBody* body = m_nonStaticRigidBodies[i];
    628 		if (body)
    629 		{
    630 			body->updateDeactivation(timeStep);
    631 
    632 			if (body->wantsSleeping())
    633 			{
    634 				if (body->isStaticOrKinematicObject())
    635 				{
    636 					body->setActivationState(ISLAND_SLEEPING);
    637 				} else
    638 				{
    639 					if (body->getActivationState() == ACTIVE_TAG)
    640 						body->setActivationState( WANTS_DEACTIVATION );
    641 					if (body->getActivationState() == ISLAND_SLEEPING)
    642 					{
    643 						body->setAngularVelocity(btVector3(0,0,0));
    644 						body->setLinearVelocity(btVector3(0,0,0));
    645 					}
    646 
    647 				}
    648 			} else
    649 			{
    650 				if (body->getActivationState() != DISABLE_DEACTIVATION)
    651 					body->setActivationState( ACTIVE_TAG );
    652 			}
    653 		}
    654 	}
    655 }
    656 
    657 void	btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
    658 {
    659 	m_constraints.push_back(constraint);
    660     //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
    661     btAssert(&constraint->getRigidBodyA()!=&constraint->getRigidBodyB());
    662 
    663 	if (disableCollisionsBetweenLinkedBodies)
    664 	{
    665 		constraint->getRigidBodyA().addConstraintRef(constraint);
    666 		constraint->getRigidBodyB().addConstraintRef(constraint);
    667 	}
    668 }
    669 
    670 void	btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
    671 {
    672 	m_constraints.remove(constraint);
    673 	constraint->getRigidBodyA().removeConstraintRef(constraint);
    674 	constraint->getRigidBodyB().removeConstraintRef(constraint);
    675 }
    676 
    677 void	btDiscreteDynamicsWorld::addAction(btActionInterface* action)
    678 {
    679 	m_actions.push_back(action);
    680 }
    681 
    682 void	btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
    683 {
    684 	m_actions.remove(action);
    685 }
    686 
    687 
    688 void	btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
    689 {
    690 	addAction(vehicle);
    691 }
    692 
    693 void	btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
    694 {
    695 	removeAction(vehicle);
    696 }
    697 
    698 void	btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
    699 {
    700 	addAction(character);
    701 }
    702 
    703 void	btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
    704 {
    705 	removeAction(character);
    706 }
    707 
    708 
    709 
    710 
    711 void	btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
    712 {
    713 	BT_PROFILE("solveConstraints");
    714 
    715 	m_sortedConstraints.resize( m_constraints.size());
    716 	int i;
    717 	for (i=0;i<getNumConstraints();i++)
    718 	{
    719 		m_sortedConstraints[i] = m_constraints[i];
    720 	}
    721 
    722 //	btAssert(0);
    723 
    724 
    725 
    726 	m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
    727 
    728 	btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
    729 
    730 	m_solverIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),getDebugDrawer());
    731 	m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
    732 
    733 	/// solve all the constraints for this island
    734 	m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverIslandCallback);
    735 
    736 	m_solverIslandCallback->processConstraints();
    737 
    738 	m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
    739 }
    740 
    741 
    742 void	btDiscreteDynamicsWorld::calculateSimulationIslands()
    743 {
    744 	BT_PROFILE("calculateSimulationIslands");
    745 
    746 	getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
    747 
    748     {
    749         //merge islands based on speculative contact manifolds too
    750         for (int i=0;i<this->m_predictiveManifolds.size();i++)
    751         {
    752             btPersistentManifold* manifold = m_predictiveManifolds[i];
    753 
    754             const btCollisionObject* colObj0 = manifold->getBody0();
    755             const btCollisionObject* colObj1 = manifold->getBody1();
    756 
    757             if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
    758                 ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
    759             {
    760 				getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
    761             }
    762         }
    763     }
    764 
    765 	{
    766 		int i;
    767 		int numConstraints = int(m_constraints.size());
    768 		for (i=0;i< numConstraints ; i++ )
    769 		{
    770 			btTypedConstraint* constraint = m_constraints[i];
    771 			if (constraint->isEnabled())
    772 			{
    773 				const btRigidBody* colObj0 = &constraint->getRigidBodyA();
    774 				const btRigidBody* colObj1 = &constraint->getRigidBodyB();
    775 
    776 				if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
    777 					((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
    778 				{
    779 					getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
    780 				}
    781 			}
    782 		}
    783 	}
    784 
    785 	//Store the island id in each body
    786 	getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
    787 
    788 
    789 }
    790 
    791 
    792 
    793 
    794 class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
    795 {
    796 public:
    797 
    798 	btCollisionObject* m_me;
    799 	btScalar m_allowedPenetration;
    800 	btOverlappingPairCache* m_pairCache;
    801 	btDispatcher* m_dispatcher;
    802 
    803 public:
    804 	btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
    805 	  btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
    806 		m_me(me),
    807 		m_allowedPenetration(0.0f),
    808 		m_pairCache(pairCache),
    809 		m_dispatcher(dispatcher)
    810 	{
    811 	}
    812 
    813 	virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
    814 	{
    815 		if (convexResult.m_hitCollisionObject == m_me)
    816 			return 1.0f;
    817 
    818 		//ignore result if there is no contact response
    819 		if(!convexResult.m_hitCollisionObject->hasContactResponse())
    820 			return 1.0f;
    821 
    822 		btVector3 linVelA,linVelB;
    823 		linVelA = m_convexToWorld-m_convexFromWorld;
    824 		linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
    825 
    826 		btVector3 relativeVelocity = (linVelA-linVelB);
    827 		//don't report time of impact for motion away from the contact normal (or causes minor penetration)
    828 		if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
    829 			return 1.f;
    830 
    831 		return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
    832 	}
    833 
    834 	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
    835 	{
    836 		//don't collide with itself
    837 		if (proxy0->m_clientObject == m_me)
    838 			return false;
    839 
    840 		///don't do CCD when the collision filters are not matching
    841 		if (!ClosestConvexResultCallback::needsCollision(proxy0))
    842 			return false;
    843 
    844 		btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
    845 
    846 		//call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
    847 		if (m_dispatcher->needsResponse(m_me,otherObj))
    848 		{
    849 #if 0
    850 			///don't do CCD when there are already contact points (touching contact/penetration)
    851 			btAlignedObjectArray<btPersistentManifold*> manifoldArray;
    852 			btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
    853 			if (collisionPair)
    854 			{
    855 				if (collisionPair->m_algorithm)
    856 				{
    857 					manifoldArray.resize(0);
    858 					collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
    859 					for (int j=0;j<manifoldArray.size();j++)
    860 					{
    861 						btPersistentManifold* manifold = manifoldArray[j];
    862 						if (manifold->getNumContacts()>0)
    863 							return false;
    864 					}
    865 				}
    866 			}
    867 #endif
    868 			return true;
    869 		}
    870 
    871 		return false;
    872 	}
    873 
    874 
    875 };
    876 
    877 ///internal debugging variable. this value shouldn't be too high
    878 int gNumClampedCcdMotions=0;
    879 
    880 
    881 void	btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
    882 {
    883 	BT_PROFILE("createPredictiveContacts");
    884 
    885 	{
    886 		BT_PROFILE("release predictive contact manifolds");
    887 
    888 		for (int i=0;i<m_predictiveManifolds.size();i++)
    889 		{
    890 			btPersistentManifold* manifold = m_predictiveManifolds[i];
    891 			this->m_dispatcher1->releaseManifold(manifold);
    892 		}
    893 		m_predictiveManifolds.clear();
    894 	}
    895 
    896 	btTransform predictedTrans;
    897 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    898 	{
    899 		btRigidBody* body = m_nonStaticRigidBodies[i];
    900 		body->setHitFraction(1.f);
    901 
    902 		if (body->isActive() && (!body->isStaticOrKinematicObject()))
    903 		{
    904 
    905 			body->predictIntegratedTransform(timeStep, predictedTrans);
    906 
    907 			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
    908 
    909 			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
    910 			{
    911 				BT_PROFILE("predictive convexSweepTest");
    912 				if (body->getCollisionShape()->isConvex())
    913 				{
    914 					gNumClampedCcdMotions++;
    915 #ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
    916 					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
    917 					{
    918 					public:
    919 
    920 						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
    921 						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
    922 						{
    923 						}
    924 
    925 					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
    926 						{
    927 							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
    928 							if (!otherObj->isStaticOrKinematicObject())
    929 								return false;
    930 							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
    931 						}
    932 					};
    933 
    934 					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
    935 #else
    936 					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
    937 #endif
    938 					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
    939 					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
    940 					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
    941 
    942 					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
    943 					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
    944 					btTransform modifiedPredictedTrans = predictedTrans;
    945 					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
    946 
    947 					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
    948 					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
    949 					{
    950 
    951 						btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
    952 						btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
    953 
    954 
    955 						btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
    956 						m_predictiveManifolds.push_back(manifold);
    957 
    958 						btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
    959 						btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
    960 
    961 						btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
    962 
    963 						bool isPredictive = true;
    964 						int index = manifold->addManifoldPoint(newPoint, isPredictive);
    965 						btManifoldPoint& pt = manifold->getContactPoint(index);
    966 						pt.m_combinedRestitution = 0;
    967 						pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject);
    968 						pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
    969 						pt.m_positionWorldOnB = worldPointB;
    970 
    971 					}
    972 				}
    973 			}
    974 		}
    975 	}
    976 }
    977 void	btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
    978 {
    979 	BT_PROFILE("integrateTransforms");
    980 	btTransform predictedTrans;
    981 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
    982 	{
    983 		btRigidBody* body = m_nonStaticRigidBodies[i];
    984 		body->setHitFraction(1.f);
    985 
    986 		if (body->isActive() && (!body->isStaticOrKinematicObject()))
    987 		{
    988 
    989 			body->predictIntegratedTransform(timeStep, predictedTrans);
    990 
    991 			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
    992 
    993 
    994 
    995 			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
    996 			{
    997 				BT_PROFILE("CCD motion clamping");
    998 				if (body->getCollisionShape()->isConvex())
    999 				{
   1000 					gNumClampedCcdMotions++;
   1001 #ifdef USE_STATIC_ONLY
   1002 					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
   1003 					{
   1004 					public:
   1005 
   1006 						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
   1007 						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
   1008 						{
   1009 						}
   1010 
   1011 					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
   1012 						{
   1013 							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
   1014 							if (!otherObj->isStaticOrKinematicObject())
   1015 								return false;
   1016 							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
   1017 						}
   1018 					};
   1019 
   1020 					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
   1021 #else
   1022 					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
   1023 #endif
   1024 					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
   1025 					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
   1026 					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
   1027 
   1028 					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
   1029 					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
   1030 					btTransform modifiedPredictedTrans = predictedTrans;
   1031 					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
   1032 
   1033 					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
   1034 					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
   1035 					{
   1036 
   1037 						//printf("clamped integration to hit fraction = %f\n",fraction);
   1038 						body->setHitFraction(sweepResults.m_closestHitFraction);
   1039 						body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
   1040 						body->setHitFraction(0.f);
   1041 						body->proceedToTransform( predictedTrans);
   1042 
   1043 #if 0
   1044 						btVector3 linVel = body->getLinearVelocity();
   1045 
   1046 						btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
   1047 						btScalar maxSpeedSqr = maxSpeed*maxSpeed;
   1048 						if (linVel.length2()>maxSpeedSqr)
   1049 						{
   1050 							linVel.normalize();
   1051 							linVel*= maxSpeed;
   1052 							body->setLinearVelocity(linVel);
   1053 							btScalar ms2 = body->getLinearVelocity().length2();
   1054 							body->predictIntegratedTransform(timeStep, predictedTrans);
   1055 
   1056 							btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
   1057 							btScalar smt = body->getCcdSquareMotionThreshold();
   1058 							printf("sm2=%f\n",sm2);
   1059 						}
   1060 #else
   1061 
   1062 						//don't apply the collision response right now, it will happen next frame
   1063 						//if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
   1064 						//btScalar appliedImpulse = 0.f;
   1065 						//btScalar depth = 0.f;
   1066 						//appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
   1067 
   1068 
   1069 #endif
   1070 
   1071         				continue;
   1072 					}
   1073 				}
   1074 			}
   1075 
   1076 
   1077 			body->proceedToTransform( predictedTrans);
   1078 
   1079 		}
   1080 
   1081 	}
   1082 
   1083 	///this should probably be switched on by default, but it is not well tested yet
   1084 	if (m_applySpeculativeContactRestitution)
   1085 	{
   1086 		BT_PROFILE("apply speculative contact restitution");
   1087 		for (int i=0;i<m_predictiveManifolds.size();i++)
   1088 		{
   1089 			btPersistentManifold* manifold = m_predictiveManifolds[i];
   1090 			btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
   1091 			btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
   1092 
   1093 			for (int p=0;p<manifold->getNumContacts();p++)
   1094 			{
   1095 				const btManifoldPoint& pt = manifold->getContactPoint(p);
   1096 				btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1);
   1097 
   1098 				if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
   1099 				//if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
   1100 				{
   1101 					btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
   1102 
   1103 					const btVector3& pos1 = pt.getPositionWorldOnA();
   1104 					const btVector3& pos2 = pt.getPositionWorldOnB();
   1105 
   1106 					btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
   1107 					btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
   1108 
   1109 					if (body0)
   1110 						body0->applyImpulse(imp,rel_pos0);
   1111 					if (body1)
   1112 						body1->applyImpulse(-imp,rel_pos1);
   1113 				}
   1114 			}
   1115 		}
   1116 	}
   1117 
   1118 }
   1119 
   1120 
   1121 
   1122 
   1123 
   1124 
   1125 void	btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
   1126 {
   1127 	BT_PROFILE("predictUnconstraintMotion");
   1128 	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
   1129 	{
   1130 		btRigidBody* body = m_nonStaticRigidBodies[i];
   1131 		if (!body->isStaticOrKinematicObject())
   1132 		{
   1133 			//don't integrate/update velocities here, it happens in the constraint solver
   1134 
   1135 			body->applyDamping(timeStep);
   1136 
   1137 			body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
   1138 		}
   1139 	}
   1140 }
   1141 
   1142 
   1143 void	btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
   1144 {
   1145 	(void)timeStep;
   1146 
   1147 #ifndef BT_NO_PROFILE
   1148 	CProfileManager::Reset();
   1149 #endif //BT_NO_PROFILE
   1150 
   1151 }
   1152 
   1153 
   1154 
   1155 
   1156 
   1157 
   1158 void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
   1159 {
   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))
   1164 	{
   1165 		return;
   1166 	}
   1167 
   1168 	switch(constraint->getConstraintType())
   1169 	{
   1170 		case POINT2POINT_CONSTRAINT_TYPE:
   1171 			{
   1172 				btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
   1173 				btTransform tr;
   1174 				tr.setIdentity();
   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);
   1184 			}
   1185 			break;
   1186 		case HINGE_CONSTRAINT_TYPE:
   1187 			{
   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)
   1196 				{
   1197 					break;
   1198 				}
   1199 				bool drawSect = true;
   1200 				if(!pHinge->hasLimit())
   1201 				{
   1202 					minAng = btScalar(0.f);
   1203 					maxAng = SIMD_2_PI;
   1204 					drawSect = false;
   1205 				}
   1206 				if(drawLimits)
   1207 				{
   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);
   1212 				}
   1213 			}
   1214 			break;
   1215 		case CONETWIST_CONSTRAINT_TYPE:
   1216 			{
   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);
   1222 				if(drawLimits)
   1223 				{
   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);
   1229 					pPrev = tr * pPrev;
   1230 					for (int i=0; i<nSegments; i++)
   1231 					{
   1232 						fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
   1233 						btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
   1234 						pCur = tr * pCur;
   1235 						getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
   1236 
   1237 						if (i%(nSegments/8) == 0)
   1238 							getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
   1239 
   1240 						pPrev = pCur;
   1241 					}
   1242 					btScalar tws = pCT->getTwistSpan();
   1243 					btScalar twa = pCT->getTwistAngle();
   1244 					bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
   1245 					if(useFrameB)
   1246 					{
   1247 						tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
   1248 					}
   1249 					else
   1250 					{
   1251 						tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
   1252 					}
   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);
   1257 
   1258 				}
   1259 			}
   1260 			break;
   1261 		case D6_SPRING_CONSTRAINT_TYPE:
   1262 		case D6_CONSTRAINT_TYPE:
   1263 			{
   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);
   1269 				if(drawLimits)
   1270 				{
   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);
   1287 					btVector3 ref;
   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;
   1295 					if(minFi > maxFi)
   1296 					{
   1297 						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
   1298 					}
   1299 					else if(minFi < maxFi)
   1300 					{
   1301 						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
   1302 					}
   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));
   1307 				}
   1308 			}
   1309 			break;
   1310 		///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
   1311 		case D6_SPRING_2_CONSTRAINT_TYPE:
   1312 		{
   1313 			{
   1314 				btGeneric6DofSpring2Constraint* p6DOF = (btGeneric6DofSpring2Constraint*)constraint;
   1315 				btTransform tr = p6DOF->getCalculatedTransformA();
   1316 				if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
   1317 				tr = p6DOF->getCalculatedTransformB();
   1318 				if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
   1319 				if (drawLimits)
   1320 				{
   1321 					tr = p6DOF->getCalculatedTransformA();
   1322 					const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
   1323 					btVector3 up = tr.getBasis().getColumn(2);
   1324 					btVector3 axis = tr.getBasis().getColumn(0);
   1325 					btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
   1326 					btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
   1327 					btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
   1328 					btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
   1329 					getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
   1330 					axis = tr.getBasis().getColumn(1);
   1331 					btScalar ay = p6DOF->getAngle(1);
   1332 					btScalar az = p6DOF->getAngle(2);
   1333 					btScalar cy = btCos(ay);
   1334 					btScalar sy = btSin(ay);
   1335 					btScalar cz = btCos(az);
   1336 					btScalar sz = btSin(az);
   1337 					btVector3 ref;
   1338 					ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
   1339 					ref[1] = -sz*axis[0] + cz*axis[1];
   1340 					ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
   1341 					tr = p6DOF->getCalculatedTransformB();
   1342 					btVector3 normal = -tr.getBasis().getColumn(0);
   1343 					btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
   1344 					btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
   1345 					if (minFi > maxFi)
   1346 					{
   1347 						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
   1348 					}
   1349 					else if (minFi < maxFi)
   1350 					{
   1351 						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
   1352 					}
   1353 					tr = p6DOF->getCalculatedTransformA();
   1354 					btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
   1355 					btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
   1356 					getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
   1357 				}
   1358 			}
   1359 			break;
   1360 		}
   1361 		case SLIDER_CONSTRAINT_TYPE:
   1362 			{
   1363 				btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
   1364 				btTransform tr = pSlider->getCalculatedTransformA();
   1365 				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
   1366 				tr = pSlider->getCalculatedTransformB();
   1367 				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
   1368 				if(drawLimits)
   1369 				{
   1370 					btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
   1371 					btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
   1372 					btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
   1373 					getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
   1374 					btVector3 normal = tr.getBasis().getColumn(0);
   1375 					btVector3 axis = tr.getBasis().getColumn(1);
   1376 					btScalar a_min = pSlider->getLowerAngLimit();
   1377 					btScalar a_max = pSlider->getUpperAngLimit();
   1378 					const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
   1379 					getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
   1380 				}
   1381 			}
   1382 			break;
   1383 		default :
   1384 			break;
   1385 	}
   1386 	return;
   1387 }
   1388 
   1389 
   1390 
   1391 
   1392 
   1393 void	btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
   1394 {
   1395 	if (m_ownsConstraintSolver)
   1396 	{
   1397 		btAlignedFree( m_constraintSolver);
   1398 	}
   1399 	m_ownsConstraintSolver = false;
   1400 	m_constraintSolver = solver;
   1401 	m_solverIslandCallback->m_solver = solver;
   1402 }
   1403 
   1404 btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
   1405 {
   1406 	return m_constraintSolver;
   1407 }
   1408 
   1409 
   1410 int		btDiscreteDynamicsWorld::getNumConstraints() const
   1411 {
   1412 	return int(m_constraints.size());
   1413 }
   1414 btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
   1415 {
   1416 	return m_constraints[index];
   1417 }
   1418 const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
   1419 {
   1420 	return m_constraints[index];
   1421 }
   1422 
   1423 
   1424 
   1425 void	btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
   1426 {
   1427 	int i;
   1428 	//serialize all collision objects
   1429 	for (i=0;i<m_collisionObjects.size();i++)
   1430 	{
   1431 		btCollisionObject* colObj = m_collisionObjects[i];
   1432 		if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
   1433 		{
   1434 			int len = colObj->calculateSerializeBufferSize();
   1435 			btChunk* chunk = serializer->allocate(len,1);
   1436 			const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
   1437 			serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
   1438 		}
   1439 	}
   1440 
   1441 	for (i=0;i<m_constraints.size();i++)
   1442 	{
   1443 		btTypedConstraint* constraint = m_constraints[i];
   1444 		int size = constraint->calculateSerializeBufferSize();
   1445 		btChunk* chunk = serializer->allocate(size,1);
   1446 		const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
   1447 		serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
   1448 	}
   1449 }
   1450 
   1451 
   1452 
   1453 
   1454 void	btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
   1455 {
   1456 #ifdef BT_USE_DOUBLE_PRECISION
   1457 		int len = sizeof(btDynamicsWorldDoubleData);
   1458 		btChunk* chunk = serializer->allocate(len,1);
   1459 		btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
   1460 #else//BT_USE_DOUBLE_PRECISION
   1461 		int len = sizeof(btDynamicsWorldFloatData);
   1462 		btChunk* chunk = serializer->allocate(len,1);
   1463 		btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
   1464 #endif//BT_USE_DOUBLE_PRECISION
   1465 
   1466 		memset(worldInfo ,0x00,len);
   1467 
   1468 		m_gravity.serialize(worldInfo->m_gravity);
   1469 		worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
   1470 		worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
   1471 		worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
   1472 		worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
   1473 
   1474 		worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
   1475 		worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
   1476 		worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
   1477 		worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
   1478 
   1479 		worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
   1480 		worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
   1481 		worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
   1482 		worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
   1483 
   1484 		worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
   1485 		worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
   1486 		worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
   1487 		worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
   1488 
   1489 		worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
   1490 		worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
   1491 		worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
   1492 		worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
   1493 
   1494 		worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
   1495 
   1496 #ifdef BT_USE_DOUBLE_PRECISION
   1497 		const char* structType = "btDynamicsWorldDoubleData";
   1498 #else//BT_USE_DOUBLE_PRECISION
   1499 		const char* structType = "btDynamicsWorldFloatData";
   1500 #endif//BT_USE_DOUBLE_PRECISION
   1501 		serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
   1502 }
   1503 
   1504 void	btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
   1505 {
   1506 
   1507 	serializer->startSerialization();
   1508 
   1509 	serializeDynamicsWorldInfo(serializer);
   1510 
   1511 	serializeCollisionObjects(serializer);
   1512 
   1513 	serializeRigidBodies(serializer);
   1514 
   1515 	serializer->finishSerialization();
   1516 }
   1517 
   1518