1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #include "btCollisionDispatcherMt.h"
17 #include "LinearMath/btQuickprof.h"
18 
19 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
20 
21 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
22 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
23 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
24 #include "LinearMath/btPoolAllocator.h"
25 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
26 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
27 
btCollisionDispatcherMt(btCollisionConfiguration * config,int grainSize)28 btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
29 	: btCollisionDispatcher(config)
30 {
31 	m_batchUpdating = false;
32 	m_grainSize = grainSize;  // iterations per task
33 }
34 
getNewManifold(const btCollisionObject * body0,const btCollisionObject * body1)35 btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
36 {
37 	//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
38 
39 	btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
40 																																: gContactBreakingThreshold;
41 
42 	btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
43 
44 	void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
45 	if (NULL == mem)
46 	{
47 		//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
48 		if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
49 		{
50 			mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
51 		}
52 		else
53 		{
54 			btAssert(0);
55 			//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
56 			return 0;
57 		}
58 	}
59 	btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
60 	if (!m_batchUpdating)
61 	{
62 		// batch updater will update manifold pointers array after finishing, so
63 		// only need to update array when not batch-updating
64 		//btAssert( !btThreadsAreRunning() );
65 		manifold->m_index1a = m_manifoldsPtr.size();
66 		m_manifoldsPtr.push_back(manifold);
67 	}
68 
69 	return manifold;
70 }
71 
releaseManifold(btPersistentManifold * manifold)72 void btCollisionDispatcherMt::releaseManifold(btPersistentManifold* manifold)
73 {
74 	clearManifold(manifold);
75 	//btAssert( !btThreadsAreRunning() );
76 	if (!m_batchUpdating)
77 	{
78 		// batch updater will update manifold pointers array after finishing, so
79 		// only need to update array when not batch-updating
80 		int findIndex = manifold->m_index1a;
81 		btAssert(findIndex < m_manifoldsPtr.size());
82 		m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
83 		m_manifoldsPtr[findIndex]->m_index1a = findIndex;
84 		m_manifoldsPtr.pop_back();
85 	}
86 
87 	manifold->~btPersistentManifold();
88 	if (m_persistentManifoldPoolAllocator->validPtr(manifold))
89 	{
90 		m_persistentManifoldPoolAllocator->freeMemory(manifold);
91 	}
92 	else
93 	{
94 		btAlignedFree(manifold);
95 	}
96 }
97 
98 struct CollisionDispatcherUpdater : public btIParallelForBody
99 {
100 	btBroadphasePair* mPairArray;
101 	btNearCallback mCallback;
102 	btCollisionDispatcher* mDispatcher;
103 	const btDispatcherInfo* mInfo;
104 
CollisionDispatcherUpdaterCollisionDispatcherUpdater105 	CollisionDispatcherUpdater()
106 	{
107 		mPairArray = NULL;
108 		mCallback = NULL;
109 		mDispatcher = NULL;
110 		mInfo = NULL;
111 	}
forLoopCollisionDispatcherUpdater112 	void forLoop(int iBegin, int iEnd) const
113 	{
114 		for (int i = iBegin; i < iEnd; ++i)
115 		{
116 			btBroadphasePair* pair = &mPairArray[i];
117 			mCallback(*pair, *mDispatcher, *mInfo);
118 		}
119 	}
120 };
121 
dispatchAllCollisionPairs(btOverlappingPairCache * pairCache,const btDispatcherInfo & info,btDispatcher * dispatcher)122 void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
123 {
124 	int pairCount = pairCache->getNumOverlappingPairs();
125 	if (pairCount == 0)
126 	{
127 		return;
128 	}
129 	CollisionDispatcherUpdater updater;
130 	updater.mCallback = getNearCallback();
131 	updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
132 	updater.mDispatcher = this;
133 	updater.mInfo = &info;
134 
135 	m_batchUpdating = true;
136 	btParallelFor(0, pairCount, m_grainSize, updater);
137 	m_batchUpdating = false;
138 
139 	// reconstruct the manifolds array to ensure determinism
140 	m_manifoldsPtr.resizeNoInitialize(0);
141 
142 	btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
143 	for (int i = 0; i < pairCount; ++i)
144 	{
145 		if (btCollisionAlgorithm* algo = pairs[i].m_algorithm)
146 		{
147 			algo->getAllContactManifolds(m_manifoldsPtr);
148 		}
149 	}
150 
151 	// update the indices (used when releasing manifolds)
152 	for (int i = 0; i < m_manifoldsPtr.size(); ++i)
153 	{
154 		m_manifoldsPtr[i]->m_index1a = i;
155 	}
156 }
157