Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @ 1997

Last change on this file since 1997 was 1972, checked in by rgrieder, 16 years ago

Downgraded Bullet to latest tagged version: 2.72
That should give us more stability.

  • Property svn:eol-style set to native
File size: 15.9 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#include "btMultiSapBroadphase.h"
17
18#include "btSimpleBroadphase.h"
19#include "LinearMath/btAabbUtil2.h"
20#include "btQuantizedBvh.h"
21
22///     btSapBroadphaseArray    m_sapBroadphases;
23
24///     btOverlappingPairCache* m_overlappingPairs;
25extern int gOverlappingPairs;
26
27/*
28class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
29{
30public:
31
32        virtual btBroadphasePair*       addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
33        {
34                return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
35        }
36};
37
38*/
39
40btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
41:m_overlappingPairs(pairCache),
42m_optimizedAabbTree(0),
43m_ownsPairCache(false),
44m_invalidPair(0)
45{
46        if (!m_overlappingPairs)
47        {
48                m_ownsPairCache = true;
49                void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
50                m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
51        }
52
53        struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
54        {
55                virtual ~btMultiSapOverlapFilterCallback()
56                {}
57                // return true when pairs need collision
58                virtual bool    needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
59                {
60                        btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
61                        btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
62                       
63                        bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
64                        collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
65       
66                        return collides;
67                }
68        };
69
70        void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
71        m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
72
73        m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
74//      mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
75//      m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
76}
77
78btMultiSapBroadphase::~btMultiSapBroadphase()
79{
80        if (m_ownsPairCache)
81        {
82                m_overlappingPairs->~btOverlappingPairCache();
83                btAlignedFree(m_overlappingPairs);
84        }
85}
86
87
88void    btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
89{
90        m_optimizedAabbTree = new btQuantizedBvh();
91        m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
92        QuantizedNodeArray&     nodes = m_optimizedAabbTree->getLeafNodeArray();
93        for (int i=0;i<m_sapBroadphases.size();i++)
94        {
95                btQuantizedBvhNode node;
96                btVector3 aabbMin,aabbMax;
97                m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
98                m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
99                m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
100                int partId = 0;
101                node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
102                nodes.push_back(node);
103        }
104        m_optimizedAabbTree->buildInternal();
105}
106
107btBroadphaseProxy*      btMultiSapBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
108{
109        //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
110
111        void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
112        btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin,  aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
113        m_multiSapProxies.push_back(proxy);
114
115        ///this should deal with inserting/removal into child broadphases
116        setAabb(proxy,aabbMin,aabbMax,dispatcher);
117        return proxy;
118}
119
120void    btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
121{
122        ///not yet
123        btAssert(0);
124
125}
126
127
128void    btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*  childBroadphase)
129{
130        void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
131        btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
132        bridgeProxyRef->m_childProxy = childProxy;
133        bridgeProxyRef->m_childBroadphase = childBroadphase;
134        parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
135}
136
137
138bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
139bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
140{
141return
142amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
143amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
144amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
145}
146
147
148
149
150
151
152//#include <stdio.h>
153
154void    btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
155{
156        btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
157        multiProxy->m_aabbMin = aabbMin;
158        multiProxy->m_aabbMax = aabbMax;
159       
160       
161//      bool fullyContained = false;
162//      bool alreadyInSimple = false;
163       
164
165
166       
167        struct MyNodeOverlapCallback : public btNodeOverlapCallback
168        {
169                btMultiSapBroadphase*   m_multiSap;
170                btMultiSapProxy*                m_multiProxy;
171                btDispatcher*                   m_dispatcher;
172
173                MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
174                        :m_multiSap(multiSap),
175                        m_multiProxy(multiProxy),
176                        m_dispatcher(dispatcher)
177                {
178
179                }
180
181                virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
182                {
183                        btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
184
185                        int containingBroadphaseIndex = -1;
186                        //already found?
187                        for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
188                        {
189
190                                if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
191                                {
192                                        containingBroadphaseIndex = i;
193                                        break;
194                                }
195                        }
196                        if (containingBroadphaseIndex<0)
197                        {
198                                //add it
199                                btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
200                                m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
201
202                        }
203                }
204        };
205
206        MyNodeOverlapCallback   myNodeCallback(this,multiProxy,dispatcher);
207
208
209
210       
211        m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
212        int i;
213
214        for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
215        {
216                btVector3 worldAabbMin,worldAabbMax;
217                multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
218                bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
219                if (!overlapsBroadphase)
220                {
221                        //remove it now
222                        btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
223
224                        btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
225                        bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
226                       
227                        multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
228                        multiProxy->m_bridgeProxies.pop_back();
229
230                }
231        }
232
233
234        /*
235
236        if (1)
237        {
238
239                //find broadphase that contain this multiProxy
240                int numChildBroadphases = getBroadphaseArray().size();
241                for (int i=0;i<numChildBroadphases;i++)
242                {
243                        btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
244                        btVector3 worldAabbMin,worldAabbMax;
245                        childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
246                        bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
247                       
248                //      fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
249                        int containingBroadphaseIndex = -1;
250                       
251                        //if already contains this
252                       
253                        for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
254                        {
255                                if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
256                                {
257                                        containingBroadphaseIndex = i;
258                                }
259                                alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
260                        }
261
262                        if (overlapsBroadphase)
263                        {
264                                if (containingBroadphaseIndex<0)
265                                {
266                                        btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
267                                        childProxy->m_multiSapParentProxy = multiProxy;
268                                        addToChildBroadphase(multiProxy,childProxy,childBroadphase);
269                                }
270                        } else
271                        {
272                                if (containingBroadphaseIndex>=0)
273                                {
274                                        //remove
275                                        btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
276
277                                        btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
278                                        bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
279                                       
280                                        multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
281                                        multiProxy->m_bridgeProxies.pop_back();
282                                }
283                        }
284                }
285
286
287                ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
288                ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
289                if (0)//!multiProxy->m_bridgeProxies.size())
290                {
291                        ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
292                        ///this is needed to be able to calculate the aabb overlap
293                        btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
294                        childProxy->m_multiSapParentProxy = multiProxy;
295                        addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
296                }
297        }
298
299        if (!multiProxy->m_bridgeProxies.size())
300        {
301                ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
302                ///this is needed to be able to calculate the aabb overlap
303                btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
304                childProxy->m_multiSapParentProxy = multiProxy;
305                addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
306        }
307*/
308
309
310        //update
311        for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
312        {
313                btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
314                bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
315        }
316
317}
318bool stopUpdating=false;
319
320
321
322class btMultiSapBroadphasePairSortPredicate
323{
324        public:
325
326                bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
327                {
328                                btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
329                                btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
330                                btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
331                                btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
332
333                                 return aProxy0 > bProxy0 || 
334                                        (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
335                                        (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); 
336                }
337};
338
339
340        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
341void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
342{
343
344//      m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
345
346        if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
347        {
348       
349                btBroadphasePairArray&  overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
350
351        //      quicksort(overlappingPairArray,0,overlappingPairArray.size());
352
353                overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
354
355                //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
356        //      overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
357
358                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
359                m_invalidPair = 0;
360
361               
362                int i;
363
364                btBroadphasePair previousPair;
365                previousPair.m_pProxy0 = 0;
366                previousPair.m_pProxy1 = 0;
367                previousPair.m_algorithm = 0;
368               
369               
370                for (i=0;i<overlappingPairArray.size();i++)
371                {
372               
373                        btBroadphasePair& pair = overlappingPairArray[i];
374
375                        btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
376                        btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
377                        btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
378                        btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
379
380                        bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
381                       
382                        previousPair = pair;
383
384                        bool needsRemoval = false;
385
386                        if (!isDuplicate)
387                        {
388                                bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
389
390                                if (hasOverlap)
391                                {
392                                        needsRemoval = false;//callback->processOverlap(pair);
393                                } else
394                                {
395                                        needsRemoval = true;
396                                }
397                        } else
398                        {
399                                //remove duplicate
400                                needsRemoval = true;
401                                //should have no algorithm
402                                btAssert(!pair.m_algorithm);
403                        }
404                       
405                        if (needsRemoval)
406                        {
407                                getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
408
409                //              m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
410                //              m_overlappingPairArray.pop_back();
411                                pair.m_pProxy0 = 0;
412                                pair.m_pProxy1 = 0;
413                                m_invalidPair++;
414                                gOverlappingPairs--;
415                        } 
416                       
417                }
418
419        ///if you don't like to skip the invalid pairs in the array, execute following code:
420        #define CLEAN_INVALID_PAIRS 1
421        #ifdef CLEAN_INVALID_PAIRS
422
423                //perform a sort, to sort 'invalid' pairs to the end
424                //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
425                overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
426
427                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
428                m_invalidPair = 0;
429        #endif//CLEAN_INVALID_PAIRS
430               
431                //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
432        }
433
434
435}
436
437
438bool    btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
439{
440        btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
441                btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
442
443                return  TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
444                        multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
445               
446}
447
448
449void    btMultiSapBroadphase::printStats()
450{
451/*      printf("---------------------------------\n");
452       
453                printf("btMultiSapBroadphase.h\n");
454                printf("numHandles = %d\n",m_multiSapProxies.size());
455                        //find broadphase that contain this multiProxy
456                int numChildBroadphases = getBroadphaseArray().size();
457                for (int i=0;i<numChildBroadphases;i++)
458                {
459
460                        btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
461                        childBroadphase->printStats();
462
463                }
464                */
465
466}
Note: See TracBrowser for help on using the repository browser.