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