Bullet Collision Detection & Physics Library
btCollisionDispatcher.cpp
Go to the documentation of this file.
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 
17 
18 #include "btCollisionDispatcher.h"
19 
20 
22 
29 
30 int gNumManifold = 0;
31 
32 #ifdef BT_DEBUG
33 #include <stdio.h>
34 #endif
35 
36 
38 m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
39  m_collisionConfiguration(collisionConfiguration)
40 {
41  int i;
42 
44 
46 
48 
49  for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
50  {
51  for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
52  {
55  }
56  }
57 
58 
59 }
60 
61 
63 {
64  m_doubleDispatch[proxyType0][proxyType1] = createFunc;
65 }
66 
68 {
69 }
70 
72 {
73  gNumManifold++;
74 
75  //btAssert(gNumManifold < 65535);
76 
77 
78 
79  //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
80 
84 
85  btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
86 
87  void* mem = 0;
88 
90  {
92  } else
93  {
94  //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
96  {
97  mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
98  } else
99  {
100  btAssert(0);
101  //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
102  return 0;
103  }
104  }
105  btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
106  manifold->m_index1a = m_manifoldsPtr.size();
107  m_manifoldsPtr.push_back(manifold);
108 
109  return manifold;
110 }
111 
113 {
114  manifold->clearManifold();
115 }
116 
117 
119 {
120 
121  gNumManifold--;
122 
123  //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
124  clearManifold(manifold);
125 
126  int findIndex = manifold->m_index1a;
127  btAssert(findIndex < m_manifoldsPtr.size());
128  m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
129  m_manifoldsPtr[findIndex]->m_index1a = findIndex;
131 
132  manifold->~btPersistentManifold();
134  {
136  } else
137  {
138  btAlignedFree(manifold);
139  }
140 
141 }
142 
143 
144 
146 {
147 
149 
150  ci.m_dispatcher1 = this;
151  ci.m_manifold = sharedManifold;
152  btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap);
153 
154  return algo;
155 }
156 
157 
158 
159 
161 {
162  //here you can do filtering
163  bool hasResponse =
164  (body0->hasContactResponse() && body1->hasContactResponse());
165  //no response between two static/kinematic bodies:
166  hasResponse = hasResponse &&
167  ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
168  return hasResponse;
169 }
170 
172 {
173  btAssert(body0);
174  btAssert(body1);
175 
176  bool needsCollision = true;
177 
178 #ifdef BT_DEBUG
180  {
181  //broadphase filtering already deals with this
182  if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
183  {
185  printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
186  }
187  }
188 #endif //BT_DEBUG
189 
190  if ((!body0->isActive()) && (!body1->isActive()))
191  needsCollision = false;
192  else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
193  needsCollision = false;
194 
195  return needsCollision ;
196 
197 }
198 
199 
200 
204 {
207 
208 public:
209 
211  :m_dispatchInfo(dispatchInfo),
212  m_dispatcher(dispatcher)
213  {
214  }
215 
216  /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
217  {
218  m_dispatchInfo = other.m_dispatchInfo;
219  m_dispatcher = other.m_dispatcher;
220  return *this;
221  }
222  */
223 
224 
226 
227 
228  virtual bool processOverlap(btBroadphasePair& pair)
229  {
230  (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
231 
232  return false;
233  }
234 };
235 
236 
237 
239 {
240  //m_blockedForChanges = true;
241 
242  btCollisionPairCallback collisionCallback(dispatchInfo,this);
243 
244  pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
245 
246  //m_blockedForChanges = false;
247 
248 }
249 
250 
251 
252 
253 //by default, Bullet will use this near callback
255 {
256  btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
257  btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
258 
259  if (dispatcher.needsCollision(colObj0,colObj1))
260  {
261  btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
262  btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
263 
264 
265  //dispatcher will keep algorithms persistent in the collision pair
266  if (!collisionPair.m_algorithm)
267  {
268  collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap);
269  }
270 
271  if (collisionPair.m_algorithm)
272  {
273  btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
274 
276  {
277  //discrete collision detection query
278 
279  collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
280  } else
281  {
282  //continuous collision detection query, time of impact (toi)
283  btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
284  if (dispatchInfo.m_timeOfImpact > toi)
285  dispatchInfo.m_timeOfImpact = toi;
286 
287  }
288  }
289  }
290 
291 }
292 
293 
295 {
297  {
299  }
300 
301  //warn user for overflow?
302  return btAlignedAlloc(static_cast<size_t>(size), 16);
303 }
304 
306 {
308  {
310  } else
311  {
312  btAlignedFree(ptr);
313  }
314 }
virtual btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
btCollisionConfiguration * m_collisionConfiguration
virtual btPoolAllocator * getCollisionAlgorithmPool()=0
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void push_back(const T &_Val)
int getShapeType() const
void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
registerCollisionCreateFunc allows registration of custom/alternative collision create functions ...
btCollisionPairCallback(const btDispatcherInfo &dispatchInfo, btCollisionDispatcher *dispatcher)
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
virtual btCollisionAlgorithm * CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo &, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
const btDispatcherInfo & m_dispatchInfo
#define btAssert(x)
Definition: btScalar.h:113
btCollisionConfiguration allows to configure Bullet collision detection stack allocator size...
btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs...
btScalar getContactProcessingThreshold() const
virtual void freeCollisionAlgorithm(void *ptr)
btManifoldResult is a helper class to manage contact results.
bool validPtr(void *ptr)
void setNearCallback(btNearCallback nearCallback)
void swap(int index0, int index1)
bool hasContactResponse() const
virtual void releaseManifold(btPersistentManifold *manifold)
The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1)
interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array...
virtual btCollisionAlgorithmCreateFunc * getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)=0
btTransform & getWorldTransform()
static void defaultNearCallback(btBroadphasePair &collisionPair, btCollisionDispatcher &dispatcher, const btDispatcherInfo &dispatchInfo)
btCollisionAlgorithmCreateFunc * m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]
int size() const
return the number of elements in the array
btScalar m_timeOfImpact
Definition: btDispatcher.h:56
virtual bool processOverlap(btBroadphasePair &pair)
btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold=0)
btAlignedObjectArray< btPersistentManifold * > m_manifoldsPtr
virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const
Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm.
bool isStaticOrKinematicObject() const
bool checkCollideWith(const btCollisionObject *co) const
#define btAlignedFree(ptr)
btCollisionObject can be used to manage collision detection objects.
virtual void clearManifold(btPersistentManifold *manifold)
virtual btPersistentManifold * getNewManifold(const btCollisionObject *b0, const btCollisionObject *b1)
int getFreeCount() const
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
const btCollisionShape * getCollisionShape() const
btBroadphaseProxy * m_pProxy0
btCollisionDispatcher(btCollisionConfiguration *collisionConfiguration)
btCollisionDispatcher * m_dispatcher
virtual btPoolAllocator * getPersistentManifoldPool()=0
memory pools
void * allocate(int size)
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)
btPoolAllocator * m_collisionAlgorithmPoolAllocator
virtual bool needsResponse(const btCollisionObject *body0, const btCollisionObject *body1)
#define btAlignedAlloc(size, alignment)
virtual void * allocateCollisionAlgorithm(int size)
void freeMemory(void *ptr)
btNearCallback getNearCallback() const
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:69
const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:23
btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatche...
const btCollisionShape * getCollisionShape() const
btPoolAllocator * m_persistentManifoldPoolAllocator
virtual void processAllOverlappingPairs(btOverlapCallback *, btDispatcher *dispatcher)=0
btScalar gContactBreakingThreshold
int gNumManifold
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:278
bool isActive() const
The btBroadphasePair class contains a pair of aabb-overlapping objects.