forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			328 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			328 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /*
 | ||
|  | Bullet Continuous Collision Detection and Physics Library | ||
|  | Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
 | ||
|  | 
 | ||
|  | This software is provided 'as-is', without any express or implied warranty. | ||
|  | In no event will the authors be held liable for any damages arising from the use of this software. | ||
|  | Permission is granted to anyone to use this software for any purpose, | ||
|  | including commercial applications, and to alter it and redistribute it freely, | ||
|  | subject to the following restrictions: | ||
|  | 
 | ||
|  | 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. | ||
|  | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. | ||
|  | 3. This notice may not be removed or altered from any source distribution. | ||
|  | */ | ||
|  | 
 | ||
|  | 
 | ||
|  | #include "btDiscreteDynamicsWorldMt.h"
 | ||
|  | 
 | ||
|  | //collision detection
 | ||
|  | #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
 | ||
|  | #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
 | ||
|  | #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btCollisionShape.h"
 | ||
|  | #include "btSimulationIslandManagerMt.h"
 | ||
|  | #include "LinearMath/btTransformUtil.h"
 | ||
|  | #include "LinearMath/btQuickprof.h"
 | ||
|  | 
 | ||
|  | //rigidbody & constraints
 | ||
|  | #include "BulletDynamics/Dynamics/btRigidBody.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
 | ||
|  | #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #include "LinearMath/btIDebugDraw.h"
 | ||
|  | #include "BulletCollision/CollisionShapes/btSphereShape.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #include "BulletDynamics/Dynamics/btActionInterface.h"
 | ||
|  | #include "LinearMath/btQuickprof.h"
 | ||
|  | #include "LinearMath/btMotionState.h"
 | ||
|  | 
 | ||
|  | #include "LinearMath/btSerializer.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::IslandCallback | ||
|  | { | ||
|  | 	btContactSolverInfo*	m_solverInfo; | ||
|  | 	btConstraintSolver*		m_solver; | ||
|  | 	btIDebugDraw*			m_debugDrawer; | ||
|  | 	btDispatcher*			m_dispatcher; | ||
|  | 
 | ||
|  | 	InplaceSolverIslandCallbackMt( | ||
|  | 		btConstraintSolver*	solver, | ||
|  | 		btStackAlloc* stackAlloc, | ||
|  | 		btDispatcher* dispatcher) | ||
|  | 		:m_solverInfo(NULL), | ||
|  | 		m_solver(solver), | ||
|  | 		m_debugDrawer(NULL), | ||
|  | 		m_dispatcher(dispatcher) | ||
|  | 	{ | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	InplaceSolverIslandCallbackMt& operator=(InplaceSolverIslandCallbackMt& other) | ||
|  | 	{ | ||
|  | 		btAssert(0); | ||
|  | 		(void)other; | ||
|  | 		return *this; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btIDebugDraw* debugDrawer) | ||
|  | 	{ | ||
|  | 		btAssert(solverInfo); | ||
|  | 		m_solverInfo = solverInfo; | ||
|  | 		m_debugDrawer = debugDrawer; | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	virtual	void	processIsland( btCollisionObject** bodies, | ||
|  |                                    int numBodies, | ||
|  |                                    btPersistentManifold** manifolds, | ||
|  |                                    int numManifolds, | ||
|  |                                    btTypedConstraint** constraints, | ||
|  |                                    int numConstraints, | ||
|  |                                    int islandId | ||
|  |                                    ) | ||
|  | 	{ | ||
|  |         m_solver->solveGroup( bodies, | ||
|  |                               numBodies, | ||
|  |                               manifolds, | ||
|  |                               numManifolds, | ||
|  |                               constraints, | ||
|  |                               numConstraints, | ||
|  |                               *m_solverInfo, | ||
|  |                               m_debugDrawer, | ||
|  |                               m_dispatcher | ||
|  |                               ); | ||
|  |     } | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | ///
 | ||
|  | /// btConstraintSolverPoolMt
 | ||
|  | ///
 | ||
|  | 
 | ||
|  | btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver() | ||
|  | { | ||
|  |     int i = 0; | ||
|  | #if BT_THREADSAFE
 | ||
|  |     i = btGetCurrentThreadIndex() % m_solvers.size(); | ||
|  | #endif // #if BT_THREADSAFE
 | ||
|  |     while ( true ) | ||
|  |     { | ||
|  |         ThreadSolver& solver = m_solvers[ i ]; | ||
|  |         if ( solver.mutex.tryLock() ) | ||
|  |         { | ||
|  |             return &solver; | ||
|  |         } | ||
|  |         // failed, try the next one
 | ||
|  |         i = ( i + 1 ) % m_solvers.size(); | ||
|  |     } | ||
|  |     return NULL; | ||
|  | } | ||
|  | 
 | ||
|  | void btConstraintSolverPoolMt::init( btConstraintSolver** solvers, int numSolvers ) | ||
|  | { | ||
|  |     m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER; | ||
|  |     m_solvers.resize( numSolvers ); | ||
|  |     for ( int i = 0; i < numSolvers; ++i ) | ||
|  |     { | ||
|  |         m_solvers[ i ].solver = solvers[ i ]; | ||
|  |     } | ||
|  |     if ( numSolvers > 0 ) | ||
|  |     { | ||
|  |         m_solverType = solvers[ 0 ]->getSolverType(); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | // create the solvers for me
 | ||
|  | btConstraintSolverPoolMt::btConstraintSolverPoolMt( int numSolvers ) | ||
|  | { | ||
|  |     btAlignedObjectArray<btConstraintSolver*> solvers; | ||
|  |     solvers.reserve( numSolvers ); | ||
|  |     for ( int i = 0; i < numSolvers; ++i ) | ||
|  |     { | ||
|  |         btConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); | ||
|  |         solvers.push_back( solver ); | ||
|  |     } | ||
|  |     init( &solvers[ 0 ], numSolvers ); | ||
|  | } | ||
|  | 
 | ||
|  | // pass in fully constructed solvers (destructor will delete them)
 | ||
|  | btConstraintSolverPoolMt::btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers ) | ||
|  | { | ||
|  |     init( solvers, numSolvers ); | ||
|  | } | ||
|  | 
 | ||
|  | btConstraintSolverPoolMt::~btConstraintSolverPoolMt() | ||
|  | { | ||
|  |     // delete all solvers
 | ||
|  |     for ( int i = 0; i < m_solvers.size(); ++i ) | ||
|  |     { | ||
|  |         ThreadSolver& solver = m_solvers[ i ]; | ||
|  |         delete solver.solver; | ||
|  |         solver.solver = NULL; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | ///solve a group of constraints
 | ||
|  | btScalar btConstraintSolverPoolMt::solveGroup( btCollisionObject** bodies, | ||
|  |     int numBodies, | ||
|  |     btPersistentManifold** manifolds, | ||
|  |     int numManifolds, | ||
|  |     btTypedConstraint** constraints, | ||
|  |     int numConstraints, | ||
|  |     const btContactSolverInfo& info, | ||
|  |     btIDebugDraw* debugDrawer, | ||
|  |     btDispatcher* dispatcher | ||
|  | ) | ||
|  | { | ||
|  |     ThreadSolver* ts = getAndLockThreadSolver(); | ||
|  |     ts->solver->solveGroup( bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher ); | ||
|  |     ts->mutex.unlock(); | ||
|  |     return 0.0f; | ||
|  | } | ||
|  | 
 | ||
|  | void btConstraintSolverPoolMt::reset() | ||
|  | { | ||
|  |     for ( int i = 0; i < m_solvers.size(); ++i ) | ||
|  |     { | ||
|  |         ThreadSolver& solver = m_solvers[ i ]; | ||
|  |         solver.mutex.lock(); | ||
|  |         solver.solver->reset(); | ||
|  |         solver.mutex.unlock(); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | ///
 | ||
|  | /// btDiscreteDynamicsWorldMt
 | ||
|  | ///
 | ||
|  | 
 | ||
|  | btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, btCollisionConfiguration* collisionConfiguration) | ||
|  | : btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) | ||
|  | { | ||
|  | 	if (m_ownsIslandManager) | ||
|  | 	{ | ||
|  | 		m_islandManager->~btSimulationIslandManager(); | ||
|  | 		btAlignedFree( m_islandManager); | ||
|  | 	} | ||
|  |     { | ||
|  | 		void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallbackMt),16); | ||
|  | 		m_solverIslandCallbackMt = new (mem) InplaceSolverIslandCallbackMt (m_constraintSolver, 0, dispatcher); | ||
|  |     } | ||
|  | 	{ | ||
|  | 		void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16); | ||
|  | 		btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt(); | ||
|  |         im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize ); | ||
|  |         m_islandManager = im; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt() | ||
|  | { | ||
|  | 	if (m_solverIslandCallbackMt) | ||
|  | 	{ | ||
|  | 		m_solverIslandCallbackMt->~InplaceSolverIslandCallbackMt(); | ||
|  | 		btAlignedFree(m_solverIslandCallbackMt); | ||
|  | 	} | ||
|  | 	if (m_ownsConstraintSolver) | ||
|  | 	{ | ||
|  | 		m_constraintSolver->~btConstraintSolver(); | ||
|  | 		btAlignedFree(m_constraintSolver); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo) | ||
|  | { | ||
|  | 	BT_PROFILE("solveConstraints"); | ||
|  | 
 | ||
|  | 	m_solverIslandCallbackMt->setup(&solverInfo, getDebugDrawer()); | ||
|  | 	m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); | ||
|  | 
 | ||
|  | 	/// solve all the constraints for this island
 | ||
|  |     btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager); | ||
|  |     im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, m_solverIslandCallbackMt ); | ||
|  | 
 | ||
|  | 	m_constraintSolver->allSolved(solverInfo, m_debugDrawer); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | struct UpdaterUnconstrainedMotion : public btIParallelForBody | ||
|  | { | ||
|  |     btScalar timeStep; | ||
|  |     btRigidBody** rigidBodies; | ||
|  | 
 | ||
|  |     void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE | ||
|  |     { | ||
|  |         for ( int i = iBegin; i < iEnd; ++i ) | ||
|  |         { | ||
|  |             btRigidBody* body = rigidBodies[ i ]; | ||
|  |             if ( !body->isStaticOrKinematicObject() ) | ||
|  |             { | ||
|  |                 //don't integrate/update velocities here, it happens in the constraint solver
 | ||
|  |                 body->applyDamping( timeStep ); | ||
|  |                 body->predictIntegratedTransform( timeStep, body->getInterpolationWorldTransform() ); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | void btDiscreteDynamicsWorldMt::predictUnconstraintMotion( btScalar timeStep ) | ||
|  | { | ||
|  |     BT_PROFILE( "predictUnconstraintMotion" ); | ||
|  |     if ( m_nonStaticRigidBodies.size() > 0 ) | ||
|  |     { | ||
|  |         UpdaterUnconstrainedMotion update; | ||
|  |         update.timeStep = timeStep; | ||
|  |         update.rigidBodies = &m_nonStaticRigidBodies[ 0 ]; | ||
|  |         int grainSize = 50;  // num of iterations per task for task scheduler
 | ||
|  |         btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update ); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void btDiscreteDynamicsWorldMt::createPredictiveContacts( btScalar timeStep ) | ||
|  | { | ||
|  |     BT_PROFILE( "createPredictiveContacts" ); | ||
|  |     releasePredictiveContacts(); | ||
|  |     if ( m_nonStaticRigidBodies.size() > 0 ) | ||
|  |     { | ||
|  |         UpdaterCreatePredictiveContacts update; | ||
|  |         update.world = this; | ||
|  |         update.timeStep = timeStep; | ||
|  |         update.rigidBodies = &m_nonStaticRigidBodies[ 0 ]; | ||
|  |         int grainSize = 50;  // num of iterations per task for task scheduler
 | ||
|  |         btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update ); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void btDiscreteDynamicsWorldMt::integrateTransforms( btScalar timeStep ) | ||
|  | { | ||
|  |     BT_PROFILE( "integrateTransforms" ); | ||
|  |     if ( m_nonStaticRigidBodies.size() > 0 ) | ||
|  |     { | ||
|  |         UpdaterIntegrateTransforms update; | ||
|  |         update.world = this; | ||
|  |         update.timeStep = timeStep; | ||
|  |         update.rigidBodies = &m_nonStaticRigidBodies[ 0 ]; | ||
|  |         int grainSize = 50;  // num of iterations per task for task scheduler
 | ||
|  |         btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update ); | ||
|  |     } | ||
|  | } | ||
|  | 
 |