Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h @ 5781

Last change on this file since 5781 was 5781, checked in by rgrieder, 15 years ago

Reverted trunk again. We might want to find a way to delete these revisions again (x3n's changes are still available as diff in the commit mails).

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