btCollisionDispatcher.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "btCollisionDispatcher.h"
00019
00020
00021 #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
00022
00023 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
00024 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00025 #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
00026 #include "LinearMath/btPoolAllocator.h"
00027 #include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
00028
00029 int gNumManifold = 0;
00030
00031 #ifdef BT_DEBUG
00032 #include <stdio.h>
00033 #endif
00034
00035
00036 btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
00037 m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
00038 m_collisionConfiguration(collisionConfiguration)
00039 {
00040 int i;
00041
00042 setNearCallback(defaultNearCallback);
00043
00044 m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
00045
00046 m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
00047
00048 for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
00049 {
00050 for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
00051 {
00052 m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
00053 btAssert(m_doubleDispatch[i][j]);
00054 }
00055 }
00056
00057
00058 }
00059
00060
00061 void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
00062 {
00063 m_doubleDispatch[proxyType0][proxyType1] = createFunc;
00064 }
00065
00066 btCollisionDispatcher::~btCollisionDispatcher()
00067 {
00068 }
00069
00070 btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
00071 {
00072 gNumManifold++;
00073
00074
00075
00076
00077 btCollisionObject* body0 = (btCollisionObject*)b0;
00078 btCollisionObject* body1 = (btCollisionObject*)b1;
00079
00080
00081
00082 btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
00083 btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
00084 : gContactBreakingThreshold ;
00085
00086 btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
00087
00088 void* mem = 0;
00089
00090 if (m_persistentManifoldPoolAllocator->getFreeCount())
00091 {
00092 mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
00093 } else
00094 {
00095 mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
00096
00097 }
00098 btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
00099 manifold->m_index1a = m_manifoldsPtr.size();
00100 m_manifoldsPtr.push_back(manifold);
00101
00102 return manifold;
00103 }
00104
00105 void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
00106 {
00107 manifold->clearManifold();
00108 }
00109
00110
00111 void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
00112 {
00113
00114 gNumManifold--;
00115
00116
00117 clearManifold(manifold);
00118
00119 int findIndex = manifold->m_index1a;
00120 btAssert(findIndex < m_manifoldsPtr.size());
00121 m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
00122 m_manifoldsPtr[findIndex]->m_index1a = findIndex;
00123 m_manifoldsPtr.pop_back();
00124
00125 manifold->~btPersistentManifold();
00126 if (m_persistentManifoldPoolAllocator->validPtr(manifold))
00127 {
00128 m_persistentManifoldPoolAllocator->freeMemory(manifold);
00129 } else
00130 {
00131 btAlignedFree(manifold);
00132 }
00133
00134 }
00135
00136
00137
00138 btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
00139 {
00140
00141 btCollisionAlgorithmConstructionInfo ci;
00142
00143 ci.m_dispatcher1 = this;
00144 ci.m_manifold = sharedManifold;
00145 btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
00146
00147 return algo;
00148 }
00149
00150
00151
00152
00153 bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
00154 {
00155
00156 bool hasResponse =
00157 (body0->hasContactResponse() && body1->hasContactResponse());
00158
00159 hasResponse = hasResponse &&
00160 ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
00161 return hasResponse;
00162 }
00163
00164 bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
00165 {
00166 btAssert(body0);
00167 btAssert(body1);
00168
00169 bool needsCollision = true;
00170
00171 #ifdef BT_DEBUG
00172 if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
00173 {
00174
00175 if ((body0->isStaticObject() || body0->isKinematicObject()) &&
00176 (body1->isStaticObject() || body1->isKinematicObject()))
00177 {
00178 m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
00179 printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
00180 }
00181 }
00182 #endif //BT_DEBUG
00183
00184 if ((!body0->isActive()) && (!body1->isActive()))
00185 needsCollision = false;
00186 else if (!body0->checkCollideWith(body1))
00187 needsCollision = false;
00188
00189 return needsCollision ;
00190
00191 }
00192
00193
00194
00197 class btCollisionPairCallback : public btOverlapCallback
00198 {
00199 const btDispatcherInfo& m_dispatchInfo;
00200 btCollisionDispatcher* m_dispatcher;
00201
00202 public:
00203
00204 btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
00205 :m_dispatchInfo(dispatchInfo),
00206 m_dispatcher(dispatcher)
00207 {
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 virtual ~btCollisionPairCallback() {}
00220
00221
00222 virtual bool processOverlap(btBroadphasePair& pair)
00223 {
00224 (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
00225
00226 return false;
00227 }
00228 };
00229
00230
00231
00232 void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
00233 {
00234
00235
00236 btCollisionPairCallback collisionCallback(dispatchInfo,this);
00237
00238 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
00239
00240
00241
00242 }
00243
00244
00245
00246
00247
00248 void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
00249 {
00250 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
00251 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
00252
00253 if (dispatcher.needsCollision(colObj0,colObj1))
00254 {
00255
00256 if (!collisionPair.m_algorithm)
00257 {
00258 collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
00259 }
00260
00261 if (collisionPair.m_algorithm)
00262 {
00263 btManifoldResult contactPointResult(colObj0,colObj1);
00264
00265 if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
00266 {
00267
00268 collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
00269 } else
00270 {
00271
00272 btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
00273 if (dispatchInfo.m_timeOfImpact > toi)
00274 dispatchInfo.m_timeOfImpact = toi;
00275
00276 }
00277 }
00278 }
00279
00280 }
00281
00282
00283 void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
00284 {
00285 if (m_collisionAlgorithmPoolAllocator->getFreeCount())
00286 {
00287 return m_collisionAlgorithmPoolAllocator->allocate(size);
00288 }
00289
00290
00291 return btAlignedAlloc(static_cast<size_t>(size), 16);
00292 }
00293
00294 void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
00295 {
00296 if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
00297 {
00298 m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
00299 } else
00300 {
00301 btAlignedFree(ptr);
00302 }
00303 }