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