165 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| Bullet Continuous Collision Detection and Physics Library
 | |
| Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
 | |
| 
 | |
| 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 "btCollisionDispatcherMt.h"
 | |
| #include "LinearMath/btQuickprof.h"
 | |
| 
 | |
| #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
 | |
| 
 | |
| #include "BulletCollision/CollisionShapes/btCollisionShape.h"
 | |
| #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
 | |
| #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
 | |
| #include "LinearMath/btPoolAllocator.h"
 | |
| #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
 | |
| #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
 | |
| 
 | |
| 
 | |
| btCollisionDispatcherMt::btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize )
 | |
|     : btCollisionDispatcher( config )
 | |
| {
 | |
|     m_batchUpdating = false;
 | |
|     m_grainSize = grainSize;  // iterations per task
 | |
| }
 | |
| 
 | |
| 
 | |
| btPersistentManifold* btCollisionDispatcherMt::getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 )
 | |
| {
 | |
|     //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
 | |
| 
 | |
|     btScalar contactBreakingThreshold = ( m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD ) ?
 | |
|         btMin( body0->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ), body1->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ) )
 | |
|         : gContactBreakingThreshold;
 | |
| 
 | |
|     btScalar contactProcessingThreshold = btMin( body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold() );
 | |
| 
 | |
|     void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
 | |
|     if ( NULL == mem )
 | |
|     {
 | |
|         //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
 | |
|         if ( ( m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION ) == 0 )
 | |
|         {
 | |
|             mem = btAlignedAlloc( sizeof( btPersistentManifold ), 16 );
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             btAssert( 0 );
 | |
|             //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
|     btPersistentManifold* manifold = new( mem ) btPersistentManifold( body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold );
 | |
|     if ( !m_batchUpdating )
 | |
|     {
 | |
|         // batch updater will update manifold pointers array after finishing, so
 | |
|         // only need to update array when not batch-updating
 | |
|         //btAssert( !btThreadsAreRunning() );
 | |
|         manifold->m_index1a = m_manifoldsPtr.size();
 | |
|         m_manifoldsPtr.push_back( manifold );
 | |
|     }
 | |
| 
 | |
|     return manifold;
 | |
| }
 | |
| 
 | |
| void btCollisionDispatcherMt::releaseManifold( btPersistentManifold* manifold )
 | |
| {
 | |
|     clearManifold( manifold );
 | |
|     //btAssert( !btThreadsAreRunning() );
 | |
|     if ( !m_batchUpdating )
 | |
|     {
 | |
|         // batch updater will update manifold pointers array after finishing, so
 | |
|         // only need to update array when not batch-updating
 | |
|         int findIndex = manifold->m_index1a;
 | |
|         btAssert( findIndex < m_manifoldsPtr.size() );
 | |
|         m_manifoldsPtr.swap( findIndex, m_manifoldsPtr.size() - 1 );
 | |
|         m_manifoldsPtr[ findIndex ]->m_index1a = findIndex;
 | |
|         m_manifoldsPtr.pop_back();
 | |
|     }
 | |
| 
 | |
|     manifold->~btPersistentManifold();
 | |
|     if ( m_persistentManifoldPoolAllocator->validPtr( manifold ) )
 | |
|     {
 | |
|         m_persistentManifoldPoolAllocator->freeMemory( manifold );
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         btAlignedFree( manifold );
 | |
|     }
 | |
| }
 | |
| 
 | |
| struct CollisionDispatcherUpdater : public btIParallelForBody
 | |
| {
 | |
|     btBroadphasePair* mPairArray;
 | |
|     btNearCallback mCallback;
 | |
|     btCollisionDispatcher* mDispatcher;
 | |
|     const btDispatcherInfo* mInfo;
 | |
| 
 | |
|     CollisionDispatcherUpdater()
 | |
|     {
 | |
|         mPairArray = NULL;
 | |
|         mCallback = NULL;
 | |
|         mDispatcher = NULL;
 | |
|         mInfo = NULL;
 | |
|     }
 | |
|     void forLoop( int iBegin, int iEnd ) const
 | |
|     {
 | |
|         for ( int i = iBegin; i < iEnd; ++i )
 | |
|         {
 | |
|             btBroadphasePair* pair = &mPairArray[ i ];
 | |
|             mCallback( *pair, *mDispatcher, *mInfo );
 | |
|         }
 | |
|     }
 | |
| };
 | |
| 
 | |
| 
 | |
| void btCollisionDispatcherMt::dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher )
 | |
| {
 | |
|     int pairCount = pairCache->getNumOverlappingPairs();
 | |
|     if ( pairCount == 0 )
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     CollisionDispatcherUpdater updater;
 | |
|     updater.mCallback = getNearCallback();
 | |
|     updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
 | |
|     updater.mDispatcher = this;
 | |
|     updater.mInfo = &info;
 | |
| 
 | |
|     m_batchUpdating = true;
 | |
|     btParallelFor( 0, pairCount, m_grainSize, updater );
 | |
|     m_batchUpdating = false;
 | |
| 
 | |
|     // reconstruct the manifolds array to ensure determinism
 | |
|     m_manifoldsPtr.resizeNoInitialize( 0 );
 | |
| 
 | |
|     btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
 | |
|     for ( int i = 0; i < pairCount; ++i )
 | |
|     {
 | |
|         if (btCollisionAlgorithm* algo = pairs[ i ].m_algorithm)
 | |
|         {
 | |
|             algo->getAllContactManifolds( m_manifoldsPtr );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // update the indices (used when releasing manifolds)
 | |
|     for ( int i = 0; i < m_manifoldsPtr.size(); ++i )
 | |
|     {
 | |
|         m_manifoldsPtr[ i ]->m_index1a = i;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 |