Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Added Bullet physics engine.

  • Property svn:eol-style set to native
File size: 16.4 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
152void    btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
153{
154        btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
155        aabbMin = multiProxy->m_aabbMin;
156        aabbMax = multiProxy->m_aabbMax;
157}
158
159void    btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback)
160{
161        for (int i=0;i<m_multiSapProxies.size();i++)
162        {
163                rayCallback.process(m_multiSapProxies[i]);
164        }
165}
166
167
168//#include <stdio.h>
169
170void    btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
171{
172        btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
173        multiProxy->m_aabbMin = aabbMin;
174        multiProxy->m_aabbMax = aabbMax;
175       
176       
177//      bool fullyContained = false;
178//      bool alreadyInSimple = false;
179       
180
181
182       
183        struct MyNodeOverlapCallback : public btNodeOverlapCallback
184        {
185                btMultiSapBroadphase*   m_multiSap;
186                btMultiSapProxy*                m_multiProxy;
187                btDispatcher*                   m_dispatcher;
188
189                MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
190                        :m_multiSap(multiSap),
191                        m_multiProxy(multiProxy),
192                        m_dispatcher(dispatcher)
193                {
194
195                }
196
197                virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
198                {
199                        btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
200
201                        int containingBroadphaseIndex = -1;
202                        //already found?
203                        for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
204                        {
205
206                                if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
207                                {
208                                        containingBroadphaseIndex = i;
209                                        break;
210                                }
211                        }
212                        if (containingBroadphaseIndex<0)
213                        {
214                                //add it
215                                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);
216                                m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
217
218                        }
219                }
220        };
221
222        MyNodeOverlapCallback   myNodeCallback(this,multiProxy,dispatcher);
223
224
225
226       
227        m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
228        int i;
229
230        for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
231        {
232                btVector3 worldAabbMin,worldAabbMax;
233                multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
234                bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
235                if (!overlapsBroadphase)
236                {
237                        //remove it now
238                        btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
239
240                        btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
241                        bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
242                       
243                        multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
244                        multiProxy->m_bridgeProxies.pop_back();
245
246                }
247        }
248
249
250        /*
251
252        if (1)
253        {
254
255                //find broadphase that contain this multiProxy
256                int numChildBroadphases = getBroadphaseArray().size();
257                for (int i=0;i<numChildBroadphases;i++)
258                {
259                        btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
260                        btVector3 worldAabbMin,worldAabbMax;
261                        childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
262                        bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
263                       
264                //      fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
265                        int containingBroadphaseIndex = -1;
266                       
267                        //if already contains this
268                       
269                        for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
270                        {
271                                if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
272                                {
273                                        containingBroadphaseIndex = i;
274                                }
275                                alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
276                        }
277
278                        if (overlapsBroadphase)
279                        {
280                                if (containingBroadphaseIndex<0)
281                                {
282                                        btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
283                                        childProxy->m_multiSapParentProxy = multiProxy;
284                                        addToChildBroadphase(multiProxy,childProxy,childBroadphase);
285                                }
286                        } else
287                        {
288                                if (containingBroadphaseIndex>=0)
289                                {
290                                        //remove
291                                        btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
292
293                                        btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
294                                        bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
295                                       
296                                        multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
297                                        multiProxy->m_bridgeProxies.pop_back();
298                                }
299                        }
300                }
301
302
303                ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
304                ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
305                if (0)//!multiProxy->m_bridgeProxies.size())
306                {
307                        ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
308                        ///this is needed to be able to calculate the aabb overlap
309                        btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
310                        childProxy->m_multiSapParentProxy = multiProxy;
311                        addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
312                }
313        }
314
315        if (!multiProxy->m_bridgeProxies.size())
316        {
317                ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
318                ///this is needed to be able to calculate the aabb overlap
319                btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
320                childProxy->m_multiSapParentProxy = multiProxy;
321                addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
322        }
323*/
324
325
326        //update
327        for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
328        {
329                btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
330                bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
331        }
332
333}
334bool stopUpdating=false;
335
336
337
338class btMultiSapBroadphasePairSortPredicate
339{
340        public:
341
342                bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
343                {
344                                btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
345                                btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
346                                btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
347                                btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
348
349                                 return aProxy0 > bProxy0 || 
350                                        (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
351                                        (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); 
352                }
353};
354
355
356        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
357void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
358{
359
360//      m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
361
362        if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
363        {
364       
365                btBroadphasePairArray&  overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
366
367        //      quicksort(overlappingPairArray,0,overlappingPairArray.size());
368
369                overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
370
371                //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
372        //      overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
373
374                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
375                m_invalidPair = 0;
376
377               
378                int i;
379
380                btBroadphasePair previousPair;
381                previousPair.m_pProxy0 = 0;
382                previousPair.m_pProxy1 = 0;
383                previousPair.m_algorithm = 0;
384               
385               
386                for (i=0;i<overlappingPairArray.size();i++)
387                {
388               
389                        btBroadphasePair& pair = overlappingPairArray[i];
390
391                        btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
392                        btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
393                        btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
394                        btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
395
396                        bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
397                       
398                        previousPair = pair;
399
400                        bool needsRemoval = false;
401
402                        if (!isDuplicate)
403                        {
404                                bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
405
406                                if (hasOverlap)
407                                {
408                                        needsRemoval = false;//callback->processOverlap(pair);
409                                } else
410                                {
411                                        needsRemoval = true;
412                                }
413                        } else
414                        {
415                                //remove duplicate
416                                needsRemoval = true;
417                                //should have no algorithm
418                                btAssert(!pair.m_algorithm);
419                        }
420                       
421                        if (needsRemoval)
422                        {
423                                getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
424
425                //              m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
426                //              m_overlappingPairArray.pop_back();
427                                pair.m_pProxy0 = 0;
428                                pair.m_pProxy1 = 0;
429                                m_invalidPair++;
430                                gOverlappingPairs--;
431                        } 
432                       
433                }
434
435        ///if you don't like to skip the invalid pairs in the array, execute following code:
436        #define CLEAN_INVALID_PAIRS 1
437        #ifdef CLEAN_INVALID_PAIRS
438
439                //perform a sort, to sort 'invalid' pairs to the end
440                //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
441                overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
442
443                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
444                m_invalidPair = 0;
445        #endif//CLEAN_INVALID_PAIRS
446               
447                //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
448        }
449
450
451}
452
453
454bool    btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
455{
456        btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
457                btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
458
459                return  TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
460                        multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
461               
462}
463
464
465void    btMultiSapBroadphase::printStats()
466{
467/*      printf("---------------------------------\n");
468       
469                printf("btMultiSapBroadphase.h\n");
470                printf("numHandles = %d\n",m_multiSapProxies.size());
471                        //find broadphase that contain this multiProxy
472                int numChildBroadphases = getBroadphaseArray().size();
473                for (int i=0;i<numChildBroadphases;i++)
474                {
475
476                        btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
477                        childBroadphase->printStats();
478
479                }
480                */
481
482}
Note: See TracBrowser for help on using the repository browser.