Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @ 2732

Last change on this file since 2732 was 2662, checked in by rgrieder, 16 years ago

Merged presentation branch back to trunk.

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16
17
18#include "btCollisionDispatcher.h"
19
20
21#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
22
23#include "BulletCollision/CollisionShapes/btCollisionShape.h"
24#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
25#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
26#include "LinearMath/btPoolAllocator.h"
27#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
28
29int gNumManifold = 0;
30
31#ifdef BT_DEBUG
32#include <stdio.h>
33#endif
34
35
36btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): 
37        m_count(0),
38        m_useIslands(true),
39        m_staticWarningReported(false),
40        m_collisionConfiguration(collisionConfiguration)
41{
42        int i;
43
44        setNearCallback(defaultNearCallback);
45       
46        m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
47
48        m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
49
50        for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
51        {
52                for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
53                {
54                        m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
55                        assert(m_doubleDispatch[i][j]);
56                }
57        }
58       
59       
60}
61
62
63void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
64{
65        m_doubleDispatch[proxyType0][proxyType1] = createFunc;
66}
67
68btCollisionDispatcher::~btCollisionDispatcher()
69{
70}
71
72btPersistentManifold*   btCollisionDispatcher::getNewManifold(void* b0,void* b1) 
73{ 
74        gNumManifold++;
75       
76        //btAssert(gNumManifold < 65535);
77       
78
79        btCollisionObject* body0 = (btCollisionObject*)b0;
80        btCollisionObject* body1 = (btCollisionObject*)b1;
81
82        btScalar contactBreakingThreshold = btMin(gContactBreakingThreshold,btMin(body0->getCollisionShape()->getContactBreakingThreshold(),body1->getCollisionShape()->getContactBreakingThreshold()));
83       
84        void* mem = 0;
85       
86        if (m_persistentManifoldPoolAllocator->getFreeCount())
87        {
88                mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
89        } else
90        {
91                mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
92
93        }
94        btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold);
95        manifold->m_index1a = m_manifoldsPtr.size();
96        m_manifoldsPtr.push_back(manifold);
97
98        return manifold;
99}
100
101void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
102{
103        manifold->clearManifold();
104}
105
106       
107void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
108{
109       
110        gNumManifold--;
111
112        //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
113        clearManifold(manifold);
114
115        int findIndex = manifold->m_index1a;
116        btAssert(findIndex < m_manifoldsPtr.size());
117        m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
118        m_manifoldsPtr[findIndex]->m_index1a = findIndex;
119        m_manifoldsPtr.pop_back();
120
121        manifold->~btPersistentManifold();
122        if (m_persistentManifoldPoolAllocator->validPtr(manifold))
123        {
124                m_persistentManifoldPoolAllocator->freeMemory(manifold);
125        } else
126        {
127                btAlignedFree(manifold);
128        }
129       
130}
131
132       
133
134btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
135{
136       
137        btCollisionAlgorithmConstructionInfo ci;
138
139        ci.m_dispatcher1 = this;
140        ci.m_manifold = sharedManifold;
141        btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
142
143        return algo;
144}
145
146
147
148
149
150bool    btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
151{
152        //here you can do filtering
153        bool hasResponse = 
154                (body0->hasContactResponse() && body1->hasContactResponse());
155        //no response between two static/kinematic bodies:
156        hasResponse = hasResponse &&
157                ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
158        return hasResponse;
159}
160
161bool    btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
162{
163        assert(body0);
164        assert(body1);
165
166        bool needsCollision = true;
167
168#ifdef BT_DEBUG
169        if (!m_staticWarningReported)
170        {
171                //broadphase filtering already deals with this
172                if ((body0->isStaticObject() || body0->isKinematicObject()) &&
173                        (body1->isStaticObject() || body1->isKinematicObject()))
174                {
175                        m_staticWarningReported = true;
176                        printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
177                }
178        }
179#endif //BT_DEBUG
180
181        if ((!body0->isActive()) && (!body1->isActive()))
182                needsCollision = false;
183        else if (!body0->checkCollideWith(body1))
184                needsCollision = false;
185       
186        return needsCollision ;
187
188}
189
190
191
192///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
193///this is useful for the collision dispatcher.
194class btCollisionPairCallback : public btOverlapCallback
195{
196        const btDispatcherInfo& m_dispatchInfo;
197        btCollisionDispatcher*  m_dispatcher;
198
199public:
200
201        btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher*     dispatcher)
202        :m_dispatchInfo(dispatchInfo),
203        m_dispatcher(dispatcher)
204        {
205        }
206
207        /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
208        {
209                m_dispatchInfo = other.m_dispatchInfo;
210                m_dispatcher = other.m_dispatcher;
211                return *this;
212        }
213        */
214
215
216        virtual ~btCollisionPairCallback() {}
217
218
219        virtual bool    processOverlap(btBroadphasePair& pair)
220        {
221                (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
222
223                return false;
224        }
225};
226
227
228
229void    btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) 
230{
231        //m_blockedForChanges = true;
232
233        btCollisionPairCallback collisionCallback(dispatchInfo,this);
234
235        pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
236
237        //m_blockedForChanges = false;
238
239}
240
241
242
243
244//by default, Bullet will use this near callback
245void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
246{
247                btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
248                btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
249
250                if (dispatcher.needsCollision(colObj0,colObj1))
251                {
252                        //dispatcher will keep algorithms persistent in the collision pair
253                        if (!collisionPair.m_algorithm)
254                        {
255                                collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
256                        }
257
258                        if (collisionPair.m_algorithm)
259                        {
260                                btManifoldResult contactPointResult(colObj0,colObj1);
261                               
262                                if (dispatchInfo.m_dispatchFunc ==              btDispatcherInfo::DISPATCH_DISCRETE)
263                                {
264                                        //discrete collision detection query
265                                        collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
266                                } else
267                                {
268                                        //continuous collision detection query, time of impact (toi)
269                                        btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
270                                        if (dispatchInfo.m_timeOfImpact > toi)
271                                                dispatchInfo.m_timeOfImpact = toi;
272
273                                }
274                        }
275                }
276
277}
278
279
280void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
281{
282        if (m_collisionAlgorithmPoolAllocator->getFreeCount())
283        {
284                return m_collisionAlgorithmPoolAllocator->allocate(size);
285        }
286       
287        //warn user for overflow?
288        return  btAlignedAlloc(static_cast<size_t>(size), 16);
289}
290
291void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
292{
293        if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
294        {
295                m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
296        } else
297        {
298                btAlignedFree(ptr);
299        }
300}
Note: See TracBrowser for help on using the repository browser.