Blender V2.61 - r43446
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 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. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 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 //btAssert(gNumManifold < 65535); 00075 00076 00077 btCollisionObject* body0 = (btCollisionObject*)b0; 00078 btCollisionObject* body1 = (btCollisionObject*)b1; 00079 00080 //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance) 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 //printf("releaseManifold: gNumManifold %d\n",gNumManifold); 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 //here you can do filtering 00156 bool hasResponse = 00157 (body0->hasContactResponse() && body1->hasContactResponse()); 00158 //no response between two static/kinematic bodies: 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 //broadphase filtering already deals with this 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 /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) 00211 { 00212 m_dispatchInfo = other.m_dispatchInfo; 00213 m_dispatcher = other.m_dispatcher; 00214 return *this; 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 //m_blockedForChanges = true; 00235 00236 btCollisionPairCallback collisionCallback(dispatchInfo,this); 00237 00238 pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); 00239 00240 //m_blockedForChanges = false; 00241 00242 } 00243 00244 00245 00246 00247 //by default, Bullet will use this near callback 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 //dispatcher will keep algorithms persistent in the collision pair 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 //discrete collision detection query 00268 collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); 00269 } else 00270 { 00271 //continuous collision detection query, time of impact (toi) 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 //warn user for overflow? 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 }