Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h @ 1972

Last change on this file since 1972 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: 26.6 KB
Line 
1//Bullet Continuous Collision Detection and Physics Library
2//Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
3
4//
5// btAxisSweep3.h
6//
7// Copyright (c) 2006 Simon Hobbs
8//
9// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
10//
11// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
12//
13// 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.
14//
15// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
16//
17// 3. This notice may not be removed or altered from any source distribution.
18
19#ifndef AXIS_SWEEP_3_H
20#define AXIS_SWEEP_3_H
21
22#include "LinearMath/btPoint3.h"
23#include "LinearMath/btVector3.h"
24#include "btOverlappingPairCache.h"
25#include "btBroadphaseInterface.h"
26#include "btBroadphaseProxy.h"
27#include "btOverlappingPairCallback.h"
28
29//#define DEBUG_BROADPHASE 1
30#define USE_OVERLAP_TEST_ON_REMOVES 1
31
32/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
33/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
34/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
35template <typename BP_FP_INT_TYPE>
36class btAxisSweep3Internal : public btBroadphaseInterface
37{
38protected:
39
40        BP_FP_INT_TYPE  m_bpHandleMask;
41        BP_FP_INT_TYPE  m_handleSentinel;
42
43public:
44       
45
46        class Edge
47        {
48        public:
49                BP_FP_INT_TYPE m_pos;                   // low bit is min/max
50                BP_FP_INT_TYPE m_handle;
51
52                BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
53        };
54
55public:
56        class   Handle : public btBroadphaseProxy
57        {
58        public:
59        BT_DECLARE_ALIGNED_ALLOCATOR();
60       
61                // indexes into the edge arrays
62                BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3];            // 6 * 2 = 12
63//              BP_FP_INT_TYPE m_uniqueId;
64                BP_FP_INT_TYPE m_pad;
65               
66                //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
67       
68                SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
69                SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
70        };              // 24 bytes + 24 for Edge structures = 44 bytes total per entry
71
72       
73protected:
74        btPoint3 m_worldAabbMin;                                                // overall system bounds
75        btPoint3 m_worldAabbMax;                                                // overall system bounds
76
77        btVector3 m_quantize;                                           // scaling factor for quantization
78
79        BP_FP_INT_TYPE m_numHandles;                                            // number of active handles
80        BP_FP_INT_TYPE m_maxHandles;                                            // max number of handles
81        Handle* m_pHandles;                                             // handles pool
82       
83        BP_FP_INT_TYPE m_firstFreeHandle;               // free handles list
84
85        Edge* m_pEdges[3];                                              // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
86        void* m_pEdgesRawPtr[3];
87
88        btOverlappingPairCache* m_pairCache;
89
90        ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
91        btOverlappingPairCallback* m_userPairCallback;
92       
93        bool    m_ownsPairCache;
94
95        int     m_invalidPair;
96
97        // allocation/deallocation
98        BP_FP_INT_TYPE allocHandle();
99        void freeHandle(BP_FP_INT_TYPE handle);
100       
101
102        bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
103
104#ifdef DEBUG_BROADPHASE
105        void debugPrintAxis(int axis,bool checkCardinality=true);
106#endif //DEBUG_BROADPHASE
107
108        //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
109        //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
110
111        void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
112
113        void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
114        void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
115        void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
116        void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
117
118public:
119
120        btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0);
121
122        virtual ~btAxisSweep3Internal();
123
124        BP_FP_INT_TYPE getNumHandles() const
125        {
126                return m_numHandles;
127        }
128
129        virtual void    calculateOverlappingPairs(btDispatcher* dispatcher);
130       
131        BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
132        void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
133        void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher);
134        SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
135
136        void    processAllOverlappingPairs(btOverlapCallback* callback);
137
138        //Broadphase Interface
139        virtual btBroadphaseProxy*      createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
140        virtual void    destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
141        virtual void    setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
142       
143        bool    testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
144
145        btOverlappingPairCache* getOverlappingPairCache()
146        {
147                return m_pairCache;
148        }
149        const btOverlappingPairCache*   getOverlappingPairCache() const
150        {
151                return m_pairCache;
152        }
153
154        void    setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
155        {
156                m_userPairCallback = pairCallback;
157        }
158        const btOverlappingPairCallback*        getOverlappingPairUserCallback() const
159        {
160                return m_userPairCallback;
161        }
162
163        ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
164        ///will add some transform later
165        virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
166        {
167                aabbMin = m_worldAabbMin;
168                aabbMax = m_worldAabbMax;
169        }
170
171        virtual void    printStats()
172        {
173/*              printf("btAxisSweep3.h\n");
174                printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
175                printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
176                        m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
177                        */
178
179        }
180
181};
182
183////////////////////////////////////////////////////////////////////
184
185
186
187
188#ifdef DEBUG_BROADPHASE
189#include <stdio.h>
190
191template <typename BP_FP_INT_TYPE>
192void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
193{
194        int numEdges = m_pHandles[0].m_maxEdges[axis];
195        printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
196
197        int i;
198        for (i=0;i<numEdges+1;i++)
199        {
200                Edge* pEdge = m_pEdges[axis] + i;
201                Handle* pHandlePrev = getHandle(pEdge->m_handle);
202                int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
203                char beginOrEnd;
204                beginOrEnd=pEdge->IsMax()?'E':'B';
205                printf("        [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
206        }
207
208        if (checkCardinality)
209                assert(numEdges == m_numHandles*2+1);
210}
211#endif //DEBUG_BROADPHASE
212
213template <typename BP_FP_INT_TYPE>
214btBroadphaseProxy*      btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
215{
216                (void)shapeType;
217                BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
218               
219                Handle* handle = getHandle(handleId);
220                               
221                return handle;
222}
223
224
225
226template <typename BP_FP_INT_TYPE>
227void    btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
228{
229        Handle* handle = static_cast<Handle*>(proxy);
230        removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
231}
232
233template <typename BP_FP_INT_TYPE>
234void    btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
235{
236        Handle* handle = static_cast<Handle*>(proxy);
237        updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
238
239}
240
241
242
243
244
245template <typename BP_FP_INT_TYPE>
246btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache )
247:m_bpHandleMask(handleMask),
248m_handleSentinel(handleSentinel),
249m_pairCache(pairCache),
250m_userPairCallback(0),
251m_ownsPairCache(false),
252m_invalidPair(0)
253{
254        BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
255
256        if (!m_pairCache)
257        {
258                void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
259                m_pairCache = new(ptr) btHashedOverlappingPairCache();
260                m_ownsPairCache = true;
261        }
262
263        //assert(bounds.HasVolume());
264
265        // init bounds
266        m_worldAabbMin = worldAabbMin;
267        m_worldAabbMax = worldAabbMax;
268
269        btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
270
271        BP_FP_INT_TYPE  maxInt = m_handleSentinel;
272
273        m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
274
275        // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
276        m_pHandles = new Handle[maxHandles];
277       
278        m_maxHandles = maxHandles;
279        m_numHandles = 0;
280
281        // handle 0 is reserved as the null index, and is also used as the sentinel
282        m_firstFreeHandle = 1;
283        {
284                for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
285                        m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
286                m_pHandles[maxHandles - 1].SetNextFree(0);
287        }
288
289        {
290                // allocate edge buffers
291                for (int i = 0; i < 3; i++)
292                {
293                        m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
294                        m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
295                }
296        }
297        //removed overlap management
298
299        // make boundary sentinels
300       
301        m_pHandles[0].m_clientObject = 0;
302
303        for (int axis = 0; axis < 3; axis++)
304        {
305                m_pHandles[0].m_minEdges[axis] = 0;
306                m_pHandles[0].m_maxEdges[axis] = 1;
307
308                m_pEdges[axis][0].m_pos = 0;
309                m_pEdges[axis][0].m_handle = 0;
310                m_pEdges[axis][1].m_pos = m_handleSentinel;
311                m_pEdges[axis][1].m_handle = 0;
312#ifdef DEBUG_BROADPHASE
313                debugPrintAxis(axis);
314#endif //DEBUG_BROADPHASE
315
316        }
317
318}
319
320template <typename BP_FP_INT_TYPE>
321btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
322{
323       
324        for (int i = 2; i >= 0; i--)
325        {
326                btAlignedFree(m_pEdgesRawPtr[i]);
327        }
328        delete [] m_pHandles;
329
330        if (m_ownsPairCache)
331        {
332                m_pairCache->~btOverlappingPairCache();
333                btAlignedFree(m_pairCache);
334        }
335}
336
337template <typename BP_FP_INT_TYPE>
338void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
339{
340#ifdef OLD_CLAMPING_METHOD
341        ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
342        ///see http://code.google.com/p/bullet/issues/detail?id=87
343        btPoint3 clampedPoint(point);
344        clampedPoint.setMax(m_worldAabbMin);
345        clampedPoint.setMin(m_worldAabbMax);
346        btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
347        out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
348        out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
349        out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
350#else
351        btVector3 v = (point - m_worldAabbMin) * m_quantize;
352        out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
353        out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
354        out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
355#endif //OLD_CLAMPING_METHOD
356}
357
358
359template <typename BP_FP_INT_TYPE>
360BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
361{
362        assert(m_firstFreeHandle);
363
364        BP_FP_INT_TYPE handle = m_firstFreeHandle;
365        m_firstFreeHandle = getHandle(handle)->GetNextFree();
366        m_numHandles++;
367
368        return handle;
369}
370
371template <typename BP_FP_INT_TYPE>
372void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
373{
374        assert(handle > 0 && handle < m_maxHandles);
375
376        getHandle(handle)->SetNextFree(m_firstFreeHandle);
377        m_firstFreeHandle = handle;
378
379        m_numHandles--;
380}
381
382
383template <typename BP_FP_INT_TYPE>
384BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
385{
386        // quantize the bounds
387        BP_FP_INT_TYPE min[3], max[3];
388        quantize(min, aabbMin, 0);
389        quantize(max, aabbMax, 1);
390
391        // allocate a handle
392        BP_FP_INT_TYPE handle = allocHandle();
393       
394
395        Handle* pHandle = getHandle(handle);
396       
397        pHandle->m_uniqueId = static_cast<int>(handle);
398        //pHandle->m_pOverlaps = 0;
399        pHandle->m_clientObject = pOwner;
400        pHandle->m_collisionFilterGroup = collisionFilterGroup;
401        pHandle->m_collisionFilterMask = collisionFilterMask;
402        pHandle->m_multiSapParentProxy = multiSapProxy;
403
404        // compute current limit of edge arrays
405        BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
406
407       
408        // insert new edges just inside the max boundary edge
409        for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
410        {
411
412                m_pHandles[0].m_maxEdges[axis] += 2;
413
414                m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
415
416                m_pEdges[axis][limit - 1].m_pos = min[axis];
417                m_pEdges[axis][limit - 1].m_handle = handle;
418
419                m_pEdges[axis][limit].m_pos = max[axis];
420                m_pEdges[axis][limit].m_handle = handle;
421
422                pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
423                pHandle->m_maxEdges[axis] = limit;
424        }
425
426        // now sort the new edges to their correct position
427        sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
428        sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
429        sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
430        sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
431        sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
432        sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
433
434
435        return handle;
436}
437
438
439template <typename BP_FP_INT_TYPE>
440void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
441{
442
443        Handle* pHandle = getHandle(handle);
444
445        //explicitly remove the pairs containing the proxy
446        //we could do it also in the sortMinUp (passing true)
447        //todo: compare performance
448        if (!m_pairCache->hasDeferredRemoval())
449        {
450                m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
451        }
452
453        // compute current limit of edge arrays
454        int limit = static_cast<int>(m_numHandles * 2);
455       
456        int axis;
457
458        for (axis = 0;axis<3;axis++)
459        {
460                m_pHandles[0].m_maxEdges[axis] -= 2;
461        }
462
463        // remove the edges by sorting them up to the end of the list
464        for ( axis = 0; axis < 3; axis++)
465        {
466                Edge* pEdges = m_pEdges[axis];
467                BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
468                pEdges[max].m_pos = m_handleSentinel;
469
470                sortMaxUp(axis,max,dispatcher,false);
471
472
473                BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
474                pEdges[i].m_pos = m_handleSentinel;
475
476
477                sortMinUp(axis,i,dispatcher,false);
478
479                pEdges[limit-1].m_handle = 0;
480                pEdges[limit-1].m_pos = m_handleSentinel;
481               
482#ifdef DEBUG_BROADPHASE
483                        debugPrintAxis(axis,false);
484#endif //DEBUG_BROADPHASE
485
486
487        }
488
489
490        // free the handle
491        freeHandle(handle);
492
493       
494}
495
496extern int gOverlappingPairs;
497//#include <stdio.h>
498
499template <typename BP_FP_INT_TYPE>
500void    btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
501{
502
503        if (m_pairCache->hasDeferredRemoval())
504        {
505       
506                btBroadphasePairArray&  overlappingPairArray = m_pairCache->getOverlappingPairArray();
507
508                //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
509                overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
510
511                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
512                m_invalidPair = 0;
513
514               
515                int i;
516
517                btBroadphasePair previousPair;
518                previousPair.m_pProxy0 = 0;
519                previousPair.m_pProxy1 = 0;
520                previousPair.m_algorithm = 0;
521               
522               
523                for (i=0;i<overlappingPairArray.size();i++)
524                {
525               
526                        btBroadphasePair& pair = overlappingPairArray[i];
527
528                        bool isDuplicate = (pair == previousPair);
529
530                        previousPair = pair;
531
532                        bool needsRemoval = false;
533
534                        if (!isDuplicate)
535                        {
536                                bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
537
538                                if (hasOverlap)
539                                {
540                                        needsRemoval = false;//callback->processOverlap(pair);
541                                } else
542                                {
543                                        needsRemoval = true;
544                                }
545                        } else
546                        {
547                                //remove duplicate
548                                needsRemoval = true;
549                                //should have no algorithm
550                                btAssert(!pair.m_algorithm);
551                        }
552                       
553                        if (needsRemoval)
554                        {
555                                m_pairCache->cleanOverlappingPair(pair,dispatcher);
556
557                //              m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
558                //              m_overlappingPairArray.pop_back();
559                                pair.m_pProxy0 = 0;
560                                pair.m_pProxy1 = 0;
561                                m_invalidPair++;
562                                gOverlappingPairs--;
563                        } 
564                       
565                }
566
567        ///if you don't like to skip the invalid pairs in the array, execute following code:
568        #define CLEAN_INVALID_PAIRS 1
569        #ifdef CLEAN_INVALID_PAIRS
570
571                //perform a sort, to sort 'invalid' pairs to the end
572                overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
573
574                overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
575                m_invalidPair = 0;
576        #endif//CLEAN_INVALID_PAIRS
577               
578                //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
579        }
580
581
582
583       
584
585}
586
587
588template <typename BP_FP_INT_TYPE>
589bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
590{
591        const Handle* pHandleA = static_cast<Handle*>(proxy0);
592        const Handle* pHandleB = static_cast<Handle*>(proxy1);
593       
594        //optimization 1: check the array index (memory address), instead of the m_pos
595
596        for (int axis = 0; axis < 3; axis++)
597        { 
598                if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || 
599                        pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) 
600                { 
601                        return false; 
602                } 
603        } 
604        return true;
605}
606
607template <typename BP_FP_INT_TYPE>
608bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
609{
610        //optimization 1: check the array index (memory address), instead of the m_pos
611
612        if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || 
613                pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
614                pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
615                pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) 
616        { 
617                return false; 
618        } 
619        return true;
620}
621
622template <typename BP_FP_INT_TYPE>
623void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher)
624{
625//      assert(bounds.IsFinite());
626        //assert(bounds.HasVolume());
627
628        Handle* pHandle = getHandle(handle);
629
630        // quantize the new bounds
631        BP_FP_INT_TYPE min[3], max[3];
632        quantize(min, aabbMin, 0);
633        quantize(max, aabbMax, 1);
634
635        // update changed edges
636        for (int axis = 0; axis < 3; axis++)
637        {
638                BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
639                BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
640
641                int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
642                int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
643
644                m_pEdges[axis][emin].m_pos = min[axis];
645                m_pEdges[axis][emax].m_pos = max[axis];
646
647                // expand (only adds overlaps)
648                if (dmin < 0)
649                        sortMinDown(axis, emin,dispatcher,true);
650
651                if (dmax > 0)
652                        sortMaxUp(axis, emax,dispatcher,true);
653
654                // shrink (only removes overlaps)
655                if (dmin > 0)
656                        sortMinUp(axis, emin,dispatcher,true);
657
658                if (dmax < 0)
659                        sortMaxDown(axis, emax,dispatcher,true);
660
661#ifdef DEBUG_BROADPHASE
662        debugPrintAxis(axis);
663#endif //DEBUG_BROADPHASE
664        }
665
666       
667}
668
669
670
671
672// sorting a min edge downwards can only ever *add* overlaps
673template <typename BP_FP_INT_TYPE>
674void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
675{
676
677        Edge* pEdge = m_pEdges[axis] + edge;
678        Edge* pPrev = pEdge - 1;
679        Handle* pHandleEdge = getHandle(pEdge->m_handle);
680
681        while (pEdge->m_pos < pPrev->m_pos)
682        {
683                Handle* pHandlePrev = getHandle(pPrev->m_handle);
684
685                if (pPrev->IsMax())
686                {
687                        // if previous edge is a maximum check the bounds and add an overlap if necessary
688                        const int axis1 = (1  << axis) & 3;
689                        const int axis2 = (1  << axis1) & 3;
690                        if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
691                        {
692                                m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
693                                if (m_userPairCallback)
694                                        m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
695
696                                //AddOverlap(pEdge->m_handle, pPrev->m_handle);
697
698                        }
699
700                        // update edge reference in other handle
701                        pHandlePrev->m_maxEdges[axis]++;
702                }
703                else
704                        pHandlePrev->m_minEdges[axis]++;
705
706                pHandleEdge->m_minEdges[axis]--;
707
708                // swap the edges
709                Edge swap = *pEdge;
710                *pEdge = *pPrev;
711                *pPrev = swap;
712
713                // decrement
714                pEdge--;
715                pPrev--;
716        }
717
718#ifdef DEBUG_BROADPHASE
719        debugPrintAxis(axis);
720#endif //DEBUG_BROADPHASE
721
722}
723
724// sorting a min edge upwards can only ever *remove* overlaps
725template <typename BP_FP_INT_TYPE>
726void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
727{
728        Edge* pEdge = m_pEdges[axis] + edge;
729        Edge* pNext = pEdge + 1;
730        Handle* pHandleEdge = getHandle(pEdge->m_handle);
731
732        while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
733        {
734                Handle* pHandleNext = getHandle(pNext->m_handle);
735
736                if (pNext->IsMax())
737                {
738                        Handle* handle0 = getHandle(pEdge->m_handle);
739                        Handle* handle1 = getHandle(pNext->m_handle);
740                        const int axis1 = (1  << axis) & 3;
741                        const int axis2 = (1  << axis1) & 3;
742                       
743                        // if next edge is maximum remove any overlap between the two handles
744                        if (updateOverlaps
745#ifdef USE_OVERLAP_TEST_ON_REMOVES
746                                && testOverlap2D(handle0,handle1,axis1,axis2)
747#endif //USE_OVERLAP_TEST_ON_REMOVES
748                                )
749                        {
750                               
751
752                                m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); 
753                                if (m_userPairCallback)
754                                        m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
755                               
756                        }
757
758
759                        // update edge reference in other handle
760                        pHandleNext->m_maxEdges[axis]--;
761                }
762                else
763                        pHandleNext->m_minEdges[axis]--;
764
765                pHandleEdge->m_minEdges[axis]++;
766
767                // swap the edges
768                Edge swap = *pEdge;
769                *pEdge = *pNext;
770                *pNext = swap;
771
772                // increment
773                pEdge++;
774                pNext++;
775        }
776
777
778}
779
780// sorting a max edge downwards can only ever *remove* overlaps
781template <typename BP_FP_INT_TYPE>
782void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
783{
784
785        Edge* pEdge = m_pEdges[axis] + edge;
786        Edge* pPrev = pEdge - 1;
787        Handle* pHandleEdge = getHandle(pEdge->m_handle);
788
789        while (pEdge->m_pos < pPrev->m_pos)
790        {
791                Handle* pHandlePrev = getHandle(pPrev->m_handle);
792
793                if (!pPrev->IsMax())
794                {
795                        // if previous edge was a minimum remove any overlap between the two handles
796                        Handle* handle0 = getHandle(pEdge->m_handle);
797                        Handle* handle1 = getHandle(pPrev->m_handle);
798                        const int axis1 = (1  << axis) & 3;
799                        const int axis2 = (1  << axis1) & 3;
800
801                        if (updateOverlaps 
802#ifdef USE_OVERLAP_TEST_ON_REMOVES
803                                && testOverlap2D(handle0,handle1,axis1,axis2)
804#endif //USE_OVERLAP_TEST_ON_REMOVES
805                                )
806                        {
807                                //this is done during the overlappingpairarray iteration/narrowphase collision
808
809                               
810                                m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
811                                if (m_userPairCallback)
812                                        m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
813                       
814
815
816                        }
817
818                        // update edge reference in other handle
819                        pHandlePrev->m_minEdges[axis]++;;
820                }
821                else
822                        pHandlePrev->m_maxEdges[axis]++;
823
824                pHandleEdge->m_maxEdges[axis]--;
825
826                // swap the edges
827                Edge swap = *pEdge;
828                *pEdge = *pPrev;
829                *pPrev = swap;
830
831                // decrement
832                pEdge--;
833                pPrev--;
834        }
835
836       
837#ifdef DEBUG_BROADPHASE
838        debugPrintAxis(axis);
839#endif //DEBUG_BROADPHASE
840
841}
842
843// sorting a max edge upwards can only ever *add* overlaps
844template <typename BP_FP_INT_TYPE>
845void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
846{
847        Edge* pEdge = m_pEdges[axis] + edge;
848        Edge* pNext = pEdge + 1;
849        Handle* pHandleEdge = getHandle(pEdge->m_handle);
850
851        while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
852        {
853                Handle* pHandleNext = getHandle(pNext->m_handle);
854
855                const int axis1 = (1  << axis) & 3;
856                const int axis2 = (1  << axis1) & 3;
857
858                if (!pNext->IsMax())
859                {
860                        // if next edge is a minimum check the bounds and add an overlap if necessary
861                        if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
862                        {
863                                Handle* handle0 = getHandle(pEdge->m_handle);
864                                Handle* handle1 = getHandle(pNext->m_handle);
865                                m_pairCache->addOverlappingPair(handle0,handle1);
866                                if (m_userPairCallback)
867                                        m_userPairCallback->addOverlappingPair(handle0,handle1);
868                        }
869
870                        // update edge reference in other handle
871                        pHandleNext->m_minEdges[axis]--;
872                }
873                else
874                        pHandleNext->m_maxEdges[axis]--;
875
876                pHandleEdge->m_maxEdges[axis]++;
877
878                // swap the edges
879                Edge swap = *pEdge;
880                *pEdge = *pNext;
881                *pNext = swap;
882
883                // increment
884                pEdge++;
885                pNext++;
886        }
887       
888}
889
890
891
892////////////////////////////////////////////////////////////////////
893
894
895/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
896/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
897/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
898class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
899{
900public:
901
902        btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
903
904};
905
906/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
907/// This comes at the cost of more memory per handle, and a bit slower performance.
908/// It uses arrays rather then lists for storage of the 3 axis.
909class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
910{
911public:
912
913        bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
914
915};
916
917#endif
918
Note: See TracBrowser for help on using the repository browser.