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