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; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 |