void	btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
{
	
	BT_PROFILE("internalSingleStepSimulation");

	if(0 != m_internalPreTickCallback) {
		(*m_internalPreTickCallback)(this, timeStep);
	}	

	///apply gravity, predict motion
	predictUnconstraintMotion(timeStep);

	btDispatcherInfo& dispatchInfo = getDispatchInfo();

	dispatchInfo.m_timeStep = timeStep;
	dispatchInfo.m_stepCount = 0;
	dispatchInfo.m_debugDraw = getDebugDrawer();


	///perform collision detection
	performDiscreteCollisionDetection();

	if (getDispatchInfo().m_useContinuous)
		addSpeculativeContacts(timeStep);


	calculateSimulationIslands();

	
	getSolverInfo().m_timeStep = timeStep;
	


	///solve contact and other joint constraints
	solveConstraints(getSolverInfo());
	
	///CallbackTriggers();

	///integrate transforms
	integrateTransforms(timeStep);

	///update vehicle simulation
	updateActions(timeStep);
	
	updateActivationState( timeStep );

	if(0 != m_internalTickCallback) {
		(*m_internalTickCallback)(this, timeStep);
	}	
}
void	btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
{
		///these should be 'temporal' aabbs!
		updateTemporalAabbs(timeStep);
		
		///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually.
		///so we handle the case moving versus static properly, and we cheat for moving versus moving
		btScalar toi = 1.f;
		
	
		btDispatcherInfo& dispatchInfo = getDispatchInfo();
		dispatchInfo.m_timeStep = timeStep;
		dispatchInfo.m_timeOfImpact = 1.f;
		dispatchInfo.m_stepCount = 0;
		dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS;

		///calculate time of impact for overlapping pairs


		btDispatcher* dispatcher = getDispatcher();
		if (dispatcher)
			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);

		toi = dispatchInfo.m_timeOfImpact;

		dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;

}
void btGpuDemoDynamicsWorld::solveConstraintsCPU2(btContactSolverInfo& solverInfo)
{
	BT_PROFILE("solveConstraints");
	grabData();
	createBatches2();
	btCudaPartProps partProps;
	{
		BT_PROFILE("set constraint data CPU");
		
		partProps.m_mass = 1.0f;
		partProps.m_diameter = m_objRad * 2.0f;
		partProps.m_restCoeff = 1.0f;

		btGpu_clearAccumulationOfLambdaDt(m_hLambdaDtBox, m_totalNumConstraints, m_maxVtxPerObj * 2);

		if(!m_useBulletNarrowphase)
		{
			btGpu_setConstraintData(m_hIds, m_totalNumConstraints - m_numNonContactConstraints, m_numObj + 1, m_hPos, m_hRot,m_hShapeBuffer, m_hShapeIds,
									partProps,	m_hContact);
		}
	}

	btCudaBoxProps boxProps;
	boxProps.minX = m_worldMin[0];
	boxProps.maxX = m_worldMax[0];
	boxProps.minY = m_worldMin[1];
	boxProps.maxY = m_worldMax[1];
	
	{
		BT_PROFILE("btCuda_collisionBatchResolutionBox CPU");
		
		int nIter=getSolverInfo().m_numIterations;
		btDispatcherInfo& dispatchInfo = getDispatchInfo();
		btScalar timeStep = dispatchInfo.m_timeStep;

		for(int i=0;i<nIter;i++){
			btGpu_collisionWithWallBox(m_hPos, m_hVel, m_hRot, m_hAngVel,m_hShapeBuffer, m_hShapeIds,
				m_hInvMass, partProps, boxProps, m_numObj + 1, timeStep);
			int* pBatchIds = m_hBatchIds;
			for(int iBatch=0;iBatch < m_maxBatches;iBatch++)
			{
				int numContConstraints = m_numInBatches[iBatch]; 
				if(!numContConstraints)
				{
					break;
				}
				btGpu_collisionBatchResolutionBox( m_hIds, pBatchIds, numContConstraints, m_numObj + 1,
													m_hPos, m_hVel,
													m_hRot, m_hAngVel,
													m_hLambdaDtBox,
													m_hContact,
													m_hInvMass,
													partProps, iBatch, timeStep);
				pBatchIds += numContConstraints;
			}
		}
	}
	writebackData();
	m_numSimStep++;
} 
Example #4
0
void	btCollisionWorld::performDiscreteCollisionDetection()
{
	btDispatcherInfo& dispatchInfo = getDispatchInfo();

	BEGIN_PROFILE("perform Broadphase Collision Detection");


	//update aabb (of all moved objects)

	btVector3 aabbMin,aabbMax;
	for (int i=0;i<m_collisionObjects.size();i++)
	{
		m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
		m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
	}

	m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
	
	END_PROFILE("perform Broadphase Collision Detection");

	BEGIN_PROFILE("performDiscreteCollisionDetection");

	btDispatcher* dispatcher = getDispatcher();
	if (dispatcher)
		dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);

	END_PROFILE("performDiscreteCollisionDetection");

}
void	btBulletPhysicsEffectsWorld::integrateTransforms(btScalar timeStep)
{
			///integrate transforms
#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
	if (getDispatchInfo().m_enableSPU)
	{
		BT_PROFILE("integrateTransformsSPU");
		int numRemainingObjects = m_nonStaticRigidBodies.size();

		int batchSize = PARALLEL_BATCH_SIZE;
		int startIndex = 0;
		while (numRemainingObjects>0)
		{
			int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects;

			//issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc)
			m_PEGatherScatterProcess->issueTask(
													CMD_SAMPLE_INTEGRATE_BODIES,
													&m_nonStaticRigidBodies[0],
													0,
													0,
													startIndex,
													currentBatchSize);
			numRemainingObjects -= currentBatchSize;
			startIndex += currentBatchSize;
		}
		
		m_PEGatherScatterProcess->flush();
	} else
#endif //USE_PE_GATHER_SCATTER_SPURS_TASK
	{
//		BT_PROFILE("integrateTransforms");
		btDiscreteDynamicsWorld::integrateTransforms(timeStep);
	}
}
void	btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
{
	
	startProfiling(timeStep);
	
	if(0 != m_internalPreTickCallback) {
		(*m_internalPreTickCallback)(this, timeStep);
	}


	///update aabbs information
	updateAabbs();
	//static int frame=0;
//	printf("frame %d\n",frame++);

	///apply gravity, predict motion
	predictUnconstraintMotion(timeStep);

	btDispatcherInfo& dispatchInfo = getDispatchInfo();

	dispatchInfo.m_timeStep = timeStep;
	dispatchInfo.m_stepCount = 0;
	dispatchInfo.m_debugDraw = getDebugDrawer();

	///perform collision detection
	performDiscreteCollisionDetection();

	calculateSimulationIslands();

	
	getSolverInfo().m_timeStep = timeStep;
	


	///solve contact and other joint constraints
	solveConstraints(getSolverInfo());
	
	///CallbackTriggers();
	calculateTimeOfImpacts(timeStep);

	btScalar toi = dispatchInfo.m_timeOfImpact;
//	if (toi < 1.f)
//		printf("toi = %f\n",toi);
	if (toi < 0.f)
		kdPrintf("toi = %f\n",toi);


	///integrate transforms
	integrateTransforms(timeStep * toi);

	///update vehicle simulation
	updateActions(timeStep);

	updateActivationState( timeStep );
	
	if(0 != m_internalTickCallback) {
		(*m_internalTickCallback)(this, timeStep);
	}
}
Example #7
0
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
///it reports one or more contact points (including the one with deepest penetration)
void	btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
{
	btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB);
	if (algorithm)
	{
		btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback);
		//discrete collision detection query
		algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult);

		algorithm->~btCollisionAlgorithm();
		getDispatcher()->freeCollisionAlgorithm(algorithm);
	}

}
void	btBulletPhysicsEffectsWorld::predictUnconstraintMotion(btScalar timeStep)
{
#ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
	if (getDispatchInfo().m_enableSPU)
	{
		BT_PROFILE("predictUnconstraintMotionSPU");
		int numRemainingObjects = m_nonStaticRigidBodies.size();

		int batchSize = PARALLEL_BATCH_SIZE;
		int startIndex=0;
		while (numRemainingObjects>0)
		{
			int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects;

			//issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc)
			m_PEGatherScatterProcess->issueTask(
													CMD_SAMPLE_PREDICT_MOTION_BODIES,
													&m_nonStaticRigidBodies[0],
													0,
													0,
													startIndex,
													currentBatchSize);
			numRemainingObjects -= currentBatchSize;
			startIndex += currentBatchSize;
		}
		
		m_PEGatherScatterProcess->flush();
	}
	else
#endif //USE_PE_GATHER_SCATTER_SPURS_TASK
	{
		btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
	}

	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
	{
		btRigidBody* body = m_nonStaticRigidBodies[i];
		body->setHitFraction(1.f);

		if (body->isActive() && (!body->isStaticOrKinematicObject()))
		{
			syncRigidBodyState(body);
		}
	}
}
int		btSimpleDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep, btScalar fixedSubSteps)
{
	(void)fixedTimeStep;
	(void)maxSubSteps;
	(void)fixedSubSteps;


	///apply gravity, predict motion
	predictUnconstraintMotion(timeStep);

	btDispatcherInfo&	dispatchInfo = getDispatchInfo();
	dispatchInfo.m_timeStep = timeStep;
	dispatchInfo.m_stepCount = 0;
	dispatchInfo.m_debugDraw = getDebugDrawer();

	///perform collision detection
	performDiscreteCollisionDetection();

	///solve contact constraints
	int numManifolds = m_dispatcher1->getNumManifolds();
	if (numManifolds)
	{
		btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
		
		btContactSolverInfo infoGlobal;
		infoGlobal.m_timeStep = timeStep;
		m_constraintSolver->prepareSolve(0, numManifolds);
		m_constraintSolver->solveGroup(&getCollisionObjectArray()[0], getNumCollisionObjects(), manifoldPtr, numManifolds,0,0, infoGlobal, m_debugDrawer, m_dispatcher1);
		m_constraintSolver->allSolved(infoGlobal, m_debugDrawer);
	}

	///integrate transforms
	integrateTransforms(timeStep);
		
	updateAabbs();

	synchronizeMotionStates();

	clearForces();

	return 1;

}
Example #10
0
void	btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
{
	btVector3 minAabb,maxAabb;
	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
	//need to increase the aabb for contact thresholds
	btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
	minAabb -= contactThreshold;
	maxAabb += contactThreshold;

	if(getDispatchInfo().m_convexMaxDistanceUseCPT)
	{
		btVector3 minAabb2,maxAabb2;
		colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
		minAabb2 -= contactThreshold;
		maxAabb2 += contactThreshold;
		minAabb.setMin(minAabb2);
		maxAabb.setMax(maxAabb2);
	}

	btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;

	//moving objects should be moderately sized, probably something wrong if not
	if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
	{
		bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
	} else
	{
		//something went wrong, investigate
		//this assert is unwanted in 3D modelers (danger of loosing work)
		colObj->setActivationState(DISABLE_SIMULATION);

		static bool reportMe = true;
		if (reportMe && m_debugDrawer)
		{
			reportMe = false;
			m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
			m_debugDrawer->reportErrorWarning("If you can reproduce this, please email [email protected]\n");
			m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
			m_debugDrawer->reportErrorWarning("Thanks.\n");
		}
	}
}
Example #11
0
void	btCollisionWorld::performDiscreteCollisionDetection()
{
	BT_PROFILE("performDiscreteCollisionDetection");

	btDispatcherInfo& dispatchInfo = getDispatchInfo();

	updateAabbs();

	{
		BT_PROFILE("calculateOverlappingPairs");
		m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
	}


	btDispatcher* dispatcher = getDispatcher();
	{
		BT_PROFILE("dispatchAllCollisionPairs");
		if (dispatcher)
			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
	}

}
void	btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
{
	BT_PROFILE("integrateTransforms");
	btTransform predictedTrans;
	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
	{
		btRigidBody* body = m_nonStaticRigidBodies[i];
		body->setHitFraction(1.f);

		if (body->isActive() && (!body->isStaticOrKinematicObject()))
		{

			body->predictIntegratedTransform(timeStep, predictedTrans);

			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();



			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
			{
				BT_PROFILE("CCD motion clamping");
				if (body->getCollisionShape()->isConvex())
				{
					gNumClampedCcdMotions++;
#ifdef USE_STATIC_ONLY
					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
					{
					public:

						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
						{
						}

					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
						{
							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
							if (!otherObj->isStaticOrKinematicObject())
								return false;
							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
						}
					};

					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#else
					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#endif
					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;

					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
					btTransform modifiedPredictedTrans = predictedTrans;
					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());

					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
					{

						//printf("clamped integration to hit fraction = %f\n",fraction);
						body->setHitFraction(sweepResults.m_closestHitFraction);
						body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
						body->setHitFraction(0.f);
						body->proceedToTransform( predictedTrans);

#if 0
						btVector3 linVel = body->getLinearVelocity();

						btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
						btScalar maxSpeedSqr = maxSpeed*maxSpeed;
						if (linVel.length2()>maxSpeedSqr)
						{
							linVel.normalize();
							linVel*= maxSpeed;
							body->setLinearVelocity(linVel);
							btScalar ms2 = body->getLinearVelocity().length2();
							body->predictIntegratedTransform(timeStep, predictedTrans);

							btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
							btScalar smt = body->getCcdSquareMotionThreshold();
							printf("sm2=%f\n",sm2);
						}
#else

						//don't apply the collision response right now, it will happen next frame
						//if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
						//btScalar appliedImpulse = 0.f;
						//btScalar depth = 0.f;
						//appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);


#endif

        				continue;
					}
				}
			}


			body->proceedToTransform( predictedTrans);

		}

	}

	///this should probably be switched on by default, but it is not well tested yet
	if (m_applySpeculativeContactRestitution)
	{
		BT_PROFILE("apply speculative contact restitution");
		for (int i=0;i<m_predictiveManifolds.size();i++)
		{
			btPersistentManifold* manifold = m_predictiveManifolds[i];
			btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
			btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());

			for (int p=0;p<manifold->getNumContacts();p++)
			{
				const btManifoldPoint& pt = manifold->getContactPoint(p);
				btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1);

				if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
				//if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
				{
					btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;

					const btVector3& pos1 = pt.getPositionWorldOnA();
					const btVector3& pos2 = pt.getPositionWorldOnB();

					btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
					btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();

					if (body0)
						body0->applyImpulse(imp,rel_pos0);
					if (body1)
						body1->applyImpulse(-imp,rel_pos1);
				}
			}
		}
	}

}
void	btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
{
	BT_PROFILE("createPredictiveContacts");

	{
		BT_PROFILE("release predictive contact manifolds");

		for (int i=0;i<m_predictiveManifolds.size();i++)
		{
			btPersistentManifold* manifold = m_predictiveManifolds[i];
			this->m_dispatcher1->releaseManifold(manifold);
		}
		m_predictiveManifolds.clear();
	}

	btTransform predictedTrans;
	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
	{
		btRigidBody* body = m_nonStaticRigidBodies[i];
		body->setHitFraction(1.f);

		if (body->isActive() && (!body->isStaticOrKinematicObject()))
		{

			body->predictIntegratedTransform(timeStep, predictedTrans);

			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();

			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
			{
				BT_PROFILE("predictive convexSweepTest");
				if (body->getCollisionShape()->isConvex())
				{
					gNumClampedCcdMotions++;
#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
					{
					public:

						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
						{
						}

					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
						{
							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
							if (!otherObj->isStaticOrKinematicObject())
								return false;
							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
						}
					};

					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#else
					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#endif
					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;

					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
					btTransform modifiedPredictedTrans = predictedTrans;
					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());

					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
					{

						btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
						btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);


						btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
						m_predictiveManifolds.push_back(manifold);

						btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
						btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;

						btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);

						bool isPredictive = true;
						int index = manifold->addManifoldPoint(newPoint, isPredictive);
						btManifoldPoint& pt = manifold->getContactPoint(index);
						pt.m_combinedRestitution = 0;
						pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject);
						pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
						pt.m_positionWorldOnB = worldPointB;

					}
				}
			}
		}
	}
}
void	btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
{
	BT_PROFILE("integrateTransforms");
	btTransform predictedTrans;
	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
	{
		btRigidBody* body = m_nonStaticRigidBodies[i];
		body->setHitFraction(1.f);

		if (body->isActive() && (!body->isStaticOrKinematicObject()))
		{

			body->predictIntegratedTransform(timeStep, predictedTrans);
			
			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();

			

			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
			{
				BT_PROFILE("CCD motion clamping");
				if (body->getCollisionShape()->isConvex())
				{
					gNumClampedCcdMotions++;
#ifdef USE_STATIC_ONLY
					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
					{
					public:

						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : 
						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
						{
						}

					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
						{
							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
							if (!otherObj->isStaticOrKinematicObject())
								return false;
							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
						}
					};

					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#else
					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
#endif
					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;

					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
					btTransform modifiedPredictedTrans = predictedTrans;
					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());

					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
					{
						
						//printf("clamped integration to hit fraction = %f\n",fraction);
						body->setHitFraction(sweepResults.m_closestHitFraction);
						body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
						body->setHitFraction(0.f);
						body->proceedToTransform( predictedTrans);

#if 0
						btVector3 linVel = body->getLinearVelocity();

						btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
						btScalar maxSpeedSqr = maxSpeed*maxSpeed;
						if (linVel.length2()>maxSpeedSqr)
						{
							linVel.normalize();
							linVel*= maxSpeed;
							body->setLinearVelocity(linVel);
							btScalar ms2 = body->getLinearVelocity().length2();
							body->predictIntegratedTransform(timeStep, predictedTrans);

							btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
							btScalar smt = body->getCcdSquareMotionThreshold();
							printf("sm2=%f\n",sm2);
						}
#else
						//response  between two dynamic objects without friction, assuming 0 penetration depth
						btScalar appliedImpulse = 0.f;
						btScalar depth = 0.f;
						appliedImpulse = resolveSingleCollision(body,sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
						

#endif

        				continue;
					}
				}
			}
			

			body->proceedToTransform( predictedTrans);
		}
	}
}
void btGpuDemoDynamicsWorld::solveConstraints2(btContactSolverInfo& solverInfo)
{
//#ifdef BT_USE_CUDA
#if 1
	BT_PROFILE("solveConstraints");
	grabData();
	createBatches2();
	copyDataToGPU();

	btCudaPartProps partProps;
	setConstraintData(partProps);

	btCudaBoxProps boxProps;
	boxProps.minX = m_worldMin[0];
	boxProps.maxX = m_worldMax[0];
	boxProps.minY = m_worldMin[1];
	boxProps.maxY = m_worldMax[1];
	btVector3 hParams[2];
	hParams[0] = m_worldMin;
	hParams[1] = m_worldMax;
	btGpuDemo2dOCLWrap::copyArrayToDevice(btGpuDemo2dOCLWrap::m_dParams, hParams, sizeof(float) * 4 * 2); 
	{
		BT_PROFILE("btCuda_collisionBatchResolutionBox");
		
		int nIter=getSolverInfo().m_numIterations;
		btDispatcherInfo& dispatchInfo = getDispatchInfo();
		btScalar timeStep = dispatchInfo.m_timeStep;

	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, 1, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcPos);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, 2, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcVel);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, 3, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcRot);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, 4, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcAngVel);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, 9, sizeof(float),	(void*)&timeStep);

	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 3, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcPos);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 4, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcVel);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 5, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcRot);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 6, sizeof(cl_mem),	(void*)&btGpuDemo2dOCLWrap::m_dcAngVel);
	btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 12, sizeof(float),	(void*)&timeStep);

		for(int i=0;i<nIter;i++)
		{
//			btCuda_collisionWithWallBox(m_dcPos, m_dcVel, m_dcRot, m_dcAngVel,m_dShapeBuffer, m_dShapeIds, m_dInvMass,
//				partProps, boxProps, m_numObj + 1, timeStep);
			btGpuDemo2dOCLWrap::runKernelWithWorkgroupSize(GPUDEMO2D_KERNEL_COLLISION_WITH_WALL, m_numObj + 1);
//			int* pBatchIds = m_dBatchIds;
			int batchOffs = 0;
			for(int iBatch=0;iBatch < m_maxBatches;iBatch++)
			{
				int numConstraints = m_numInBatches[iBatch]; 
/*
				btCuda_collisionBatchResolutionBox( m_dIds, pBatchIds, numConstraints, m_numObj + 1,
													m_dcPos, m_dcVel,
													m_dcRot, m_dcAngVel,
													m_dLambdaDtBox,
													m_dContact, m_dInvMass,
													partProps, iBatch, timeStep);
*/
				btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 10, sizeof(int),	(void*)&iBatch);
				btGpuDemo2dOCLWrap::setKernelArg(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, 11, sizeof(int),	(void*)&batchOffs);
				btGpuDemo2dOCLWrap::runKernelWithWorkgroupSize(GPUDEMO2D_KERNEL_SOLVE_CONSTRAINTS, numConstraints);
//				pBatchIds += numConstraints;
				batchOffs += numConstraints;
			}
		}
	}
	copyDataFromGPU();
	writebackData();
	m_numSimStep++;
#endif //BT_USE_CUDA
}