Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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