123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- //Bullet Continuous Collision Detection and Physics Library
- //Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
- //
- // btAxisSweep3.h
- //
- // Copyright (c) 2006 Simon Hobbs
- //
- // 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.
- //
- // 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:
- //
- // 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.
- //
- // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- //
- // 3. This notice may not be removed or altered from any source distribution.
- #ifndef BT_AXIS_SWEEP_3_INTERNAL_H
- #define BT_AXIS_SWEEP_3_INTERNAL_H
- #include "LinearMath/btVector3.h"
- #include "btOverlappingPairCache.h"
- #include "btBroadphaseInterface.h"
- #include "btBroadphaseProxy.h"
- #include "btOverlappingPairCallback.h"
- #include "btDbvtBroadphase.h"
- //#define DEBUG_BROADPHASE 1
- #define USE_OVERLAP_TEST_ON_REMOVES 1
- /// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
- /// It uses quantized integers to represent the begin and end points for each of the 3 axis.
- /// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
- template <typename BP_FP_INT_TYPE>
- class btAxisSweep3Internal : public btBroadphaseInterface
- {
- protected:
- BP_FP_INT_TYPE m_bpHandleMask;
- BP_FP_INT_TYPE m_handleSentinel;
- public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
- class Edge
- {
- public:
- BP_FP_INT_TYPE m_pos; // low bit is min/max
- BP_FP_INT_TYPE m_handle;
- BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
- };
- public:
- class Handle : public btBroadphaseProxy
- {
- public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
- // indexes into the edge arrays
- BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
- // BP_FP_INT_TYPE m_uniqueId;
- btBroadphaseProxy* m_dbvtProxy; //for faster raycast
- //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
- SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
- SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
- }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
- protected:
- btVector3 m_worldAabbMin; // overall system bounds
- btVector3 m_worldAabbMax; // overall system bounds
- btVector3 m_quantize; // scaling factor for quantization
- BP_FP_INT_TYPE m_numHandles; // number of active handles
- BP_FP_INT_TYPE m_maxHandles; // max number of handles
- Handle* m_pHandles; // handles pool
- BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
- Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
- void* m_pEdgesRawPtr[3];
- btOverlappingPairCache* m_pairCache;
- ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
- btOverlappingPairCallback* m_userPairCallback;
- bool m_ownsPairCache;
- int m_invalidPair;
- ///additional dynamic aabb structure, used to accelerate ray cast queries.
- ///can be disabled using a optional argument in the constructor
- btDbvtBroadphase* m_raycastAccelerator;
- btOverlappingPairCache* m_nullPairCache;
- // allocation/deallocation
- BP_FP_INT_TYPE allocHandle();
- void freeHandle(BP_FP_INT_TYPE handle);
- bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
- #ifdef DEBUG_BROADPHASE
- void debugPrintAxis(int axis, bool checkCardinality = true);
- #endif //DEBUG_BROADPHASE
- //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
- //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
- void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- public:
- 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);
- virtual ~btAxisSweep3Internal();
- BP_FP_INT_TYPE getNumHandles() const
- {
- return m_numHandles;
- }
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
- void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
- virtual void resetPool(btDispatcher* dispatcher);
- void processAllOverlappingPairs(btOverlapCallback* callback);
- //Broadphase Interface
- virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
- 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));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
- void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
- ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
- void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
- bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
- btOverlappingPairCache* getOverlappingPairCache()
- {
- return m_pairCache;
- }
- const btOverlappingPairCache* getOverlappingPairCache() const
- {
- return m_pairCache;
- }
- void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
- {
- m_userPairCallback = pairCallback;
- }
- const btOverlappingPairCallback* getOverlappingPairUserCallback() const
- {
- return m_userPairCallback;
- }
- ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
- ///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- aabbMin = m_worldAabbMin;
- aabbMax = m_worldAabbMax;
- }
- virtual void printStats()
- {
- /* printf("btAxisSweep3.h\n");
- printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
- printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
- m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
- */
- }
- };
- ////////////////////////////////////////////////////////////////////
- #ifdef DEBUG_BROADPHASE
- #include <stdio.h>
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
- {
- int numEdges = m_pHandles[0].m_maxEdges[axis];
- printf("SAP Axis %d, numEdges=%d\n", axis, numEdges);
- int i;
- for (i = 0; i < numEdges + 1; i++)
- {
- Edge* pEdge = m_pEdges[axis] + i;
- Handle* pHandlePrev = getHandle(pEdge->m_handle);
- int handleIndex = pEdge->IsMax() ? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
- char beginOrEnd;
- beginOrEnd = pEdge->IsMax() ? 'E' : 'B';
- printf(" [%c,h=%d,p=%x,i=%d]\n", beginOrEnd, pEdge->m_handle, pEdge->m_pos, handleIndex);
- }
- if (checkCardinality)
- btAssert(numEdges == m_numHandles * 2 + 1);
- }
- #endif //DEBUG_BROADPHASE
- template <typename BP_FP_INT_TYPE>
- btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
- {
- (void)shapeType;
- BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
- Handle* handle = getHandle(handleId);
- if (m_raycastAccelerator)
- {
- btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
- handle->m_dbvtProxy = rayProxy;
- }
- return handle;
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
- {
- Handle* handle = static_cast<Handle*>(proxy);
- if (m_raycastAccelerator)
- m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
- removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
- {
- Handle* handle = static_cast<Handle*>(proxy);
- handle->m_aabbMin = aabbMin;
- handle->m_aabbMax = aabbMax;
- updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
- if (m_raycastAccelerator)
- m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
- {
- if (m_raycastAccelerator)
- {
- m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
- }
- else
- {
- //choose axis?
- BP_FP_INT_TYPE axis = 0;
- //for each proxy
- for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
- {
- if (m_pEdges[axis][i].IsMax())
- {
- rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
- }
- }
- }
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
- {
- if (m_raycastAccelerator)
- {
- m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
- }
- else
- {
- //choose axis?
- BP_FP_INT_TYPE axis = 0;
- //for each proxy
- for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
- {
- if (m_pEdges[axis][i].IsMax())
- {
- Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
- if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
- {
- callback.process(handle);
- }
- }
- }
- }
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
- {
- Handle* pHandle = static_cast<Handle*>(proxy);
- aabbMin = pHandle->m_aabbMin;
- aabbMax = pHandle->m_aabbMax;
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
- {
- Handle* pHandle = static_cast<Handle*>(proxy);
- unsigned short vecInMin[3];
- unsigned short vecInMax[3];
- vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
- vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
- vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
- vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
- vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
- vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
- aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
- aabbMin += m_worldAabbMin;
- aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
- aabbMax += m_worldAabbMin;
- }
- template <typename BP_FP_INT_TYPE>
- btAxisSweep3Internal<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)
- : m_bpHandleMask(handleMask),
- m_handleSentinel(handleSentinel),
- m_pairCache(pairCache),
- m_userPairCallback(0),
- m_ownsPairCache(false),
- m_invalidPair(0),
- m_raycastAccelerator(0)
- {
- BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles + 1); //need to add one sentinel handle
- if (!m_pairCache)
- {
- void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
- m_pairCache = new (ptr) btHashedOverlappingPairCache();
- m_ownsPairCache = true;
- }
- if (!disableRaycastAccelerator)
- {
- m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
- m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache); //m_pairCache);
- m_raycastAccelerator->m_deferedcollide = true; //don't add/remove pairs
- }
- //btAssert(bounds.HasVolume());
- // init bounds
- m_worldAabbMin = worldAabbMin;
- m_worldAabbMax = worldAabbMax;
- btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
- BP_FP_INT_TYPE maxInt = m_handleSentinel;
- m_quantize = btVector3(btScalar(maxInt), btScalar(maxInt), btScalar(maxInt)) / aabbSize;
- // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
- m_pHandles = new Handle[maxHandles];
- m_maxHandles = maxHandles;
- m_numHandles = 0;
- // handle 0 is reserved as the null index, and is also used as the sentinel
- m_firstFreeHandle = 1;
- {
- for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
- m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
- m_pHandles[maxHandles - 1].SetNextFree(0);
- }
- {
- // allocate edge buffers
- for (int i = 0; i < 3; i++)
- {
- m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge) * maxHandles * 2, 16);
- m_pEdges[i] = new (m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
- }
- }
- //removed overlap management
- // make boundary sentinels
- m_pHandles[0].m_clientObject = 0;
- for (int axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_minEdges[axis] = 0;
- m_pHandles[0].m_maxEdges[axis] = 1;
- m_pEdges[axis][0].m_pos = 0;
- m_pEdges[axis][0].m_handle = 0;
- m_pEdges[axis][1].m_pos = m_handleSentinel;
- m_pEdges[axis][1].m_handle = 0;
- #ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
- #endif //DEBUG_BROADPHASE
- }
- }
- template <typename BP_FP_INT_TYPE>
- btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
- {
- if (m_raycastAccelerator)
- {
- m_nullPairCache->~btOverlappingPairCache();
- btAlignedFree(m_nullPairCache);
- m_raycastAccelerator->~btDbvtBroadphase();
- btAlignedFree(m_raycastAccelerator);
- }
- for (int i = 2; i >= 0; i--)
- {
- btAlignedFree(m_pEdgesRawPtr[i]);
- }
- delete[] m_pHandles;
- if (m_ownsPairCache)
- {
- m_pairCache->~btOverlappingPairCache();
- btAlignedFree(m_pairCache);
- }
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
- {
- #ifdef OLD_CLAMPING_METHOD
- ///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]
- ///see http://code.google.com/p/bullet/issues/detail?id=87
- btVector3 clampedPoint(point);
- clampedPoint.setMax(m_worldAabbMin);
- clampedPoint.setMin(m_worldAabbMax);
- btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
- out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
- out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
- out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
- #else
- btVector3 v = (point - m_worldAabbMin) * m_quantize;
- 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);
- 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);
- 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);
- #endif //OLD_CLAMPING_METHOD
- }
- template <typename BP_FP_INT_TYPE>
- BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
- {
- btAssert(m_firstFreeHandle);
- BP_FP_INT_TYPE handle = m_firstFreeHandle;
- m_firstFreeHandle = getHandle(handle)->GetNextFree();
- m_numHandles++;
- return handle;
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
- {
- btAssert(handle > 0 && handle < m_maxHandles);
- getHandle(handle)->SetNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
- m_numHandles--;
- }
- template <typename BP_FP_INT_TYPE>
- BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
- {
- // quantize the bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
- // allocate a handle
- BP_FP_INT_TYPE handle = allocHandle();
- Handle* pHandle = getHandle(handle);
- pHandle->m_uniqueId = static_cast<int>(handle);
- //pHandle->m_pOverlaps = 0;
- pHandle->m_clientObject = pOwner;
- pHandle->m_collisionFilterGroup = collisionFilterGroup;
- pHandle->m_collisionFilterMask = collisionFilterMask;
- // compute current limit of edge arrays
- BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
- // insert new edges just inside the max boundary edge
- for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_maxEdges[axis] += 2;
- m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
- m_pEdges[axis][limit - 1].m_pos = min[axis];
- m_pEdges[axis][limit - 1].m_handle = handle;
- m_pEdges[axis][limit].m_pos = max[axis];
- m_pEdges[axis][limit].m_handle = handle;
- pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
- pHandle->m_maxEdges[axis] = limit;
- }
- // now sort the new edges to their correct position
- sortMinDown(0, pHandle->m_minEdges[0], dispatcher, false);
- sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher, false);
- sortMinDown(1, pHandle->m_minEdges[1], dispatcher, false);
- sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher, false);
- sortMinDown(2, pHandle->m_minEdges[2], dispatcher, true);
- sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher, true);
- return handle;
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher)
- {
- Handle* pHandle = getHandle(handle);
- //explicitly remove the pairs containing the proxy
- //we could do it also in the sortMinUp (passing true)
- ///@todo: compare performance
- if (!m_pairCache->hasDeferredRemoval())
- {
- m_pairCache->removeOverlappingPairsContainingProxy(pHandle, dispatcher);
- }
- // compute current limit of edge arrays
- int limit = static_cast<int>(m_numHandles * 2);
- int axis;
- for (axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_maxEdges[axis] -= 2;
- }
- // remove the edges by sorting them up to the end of the list
- for (axis = 0; axis < 3; axis++)
- {
- Edge* pEdges = m_pEdges[axis];
- BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
- pEdges[max].m_pos = m_handleSentinel;
- sortMaxUp(axis, max, dispatcher, false);
- BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
- pEdges[i].m_pos = m_handleSentinel;
- sortMinUp(axis, i, dispatcher, false);
- pEdges[limit - 1].m_handle = 0;
- pEdges[limit - 1].m_pos = m_handleSentinel;
- #ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis, false);
- #endif //DEBUG_BROADPHASE
- }
- // free the handle
- freeHandle(handle);
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
- {
- if (m_numHandles == 0)
- {
- m_firstFreeHandle = 1;
- {
- for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
- m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
- m_pHandles[m_maxHandles - 1].SetNextFree(0);
- }
- }
- }
- //#include <stdio.h>
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
- {
- if (m_pairCache->hasDeferredRemoval())
- {
- btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
- int i;
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- btBroadphasePair& pair = overlappingPairArray[i];
- bool isDuplicate = (pair == previousPair);
- previousPair = pair;
- bool needsRemoval = false;
- if (!isDuplicate)
- {
- ///important to use an AABB test that is consistent with the broadphase
- bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
- if (hasOverlap)
- {
- needsRemoval = false; //callback->processOverlap(pair);
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
- if (needsRemoval)
- {
- m_pairCache->cleanOverlappingPair(pair, dispatcher);
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- m_invalidPair++;
- }
- }
- ///if you don't like to skip the invalid pairs in the array, execute following code:
- #define CLEAN_INVALID_PAIRS 1
- #ifdef CLEAN_INVALID_PAIRS
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
- #endif //CLEAN_INVALID_PAIRS
- //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
- }
- }
- template <typename BP_FP_INT_TYPE>
- bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
- {
- const Handle* pHandleA = static_cast<Handle*>(proxy0);
- const Handle* pHandleB = static_cast<Handle*>(proxy1);
- //optimization 1: check the array index (memory address), instead of the m_pos
- for (int axis = 0; axis < 3; axis++)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
- return true;
- }
- template <typename BP_FP_INT_TYPE>
- bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1)
- {
- //optimization 1: check the array index (memory address), instead of the m_pos
- if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
- pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
- pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
- pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
- {
- return false;
- }
- return true;
- }
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
- {
- // btAssert(bounds.IsFinite());
- //btAssert(bounds.HasVolume());
- Handle* pHandle = getHandle(handle);
- // quantize the new bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
- // update changed edges
- for (int axis = 0; axis < 3; axis++)
- {
- BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
- BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
- int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
- int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
- m_pEdges[axis][emin].m_pos = min[axis];
- m_pEdges[axis][emax].m_pos = max[axis];
- // expand (only adds overlaps)
- if (dmin < 0)
- sortMinDown(axis, emin, dispatcher, true);
- if (dmax > 0)
- sortMaxUp(axis, emax, dispatcher, true);
- // shrink (only removes overlaps)
- if (dmin > 0)
- sortMinUp(axis, emin, dispatcher, true);
- if (dmax < 0)
- sortMaxDown(axis, emax, dispatcher, true);
- #ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
- #endif //DEBUG_BROADPHASE
- }
- }
- // sorting a min edge downwards can only ever *add* overlaps
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
- {
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
- if (pPrev->IsMax())
- {
- // if previous edge is a maximum check the bounds and add an overlap if necessary
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev, axis1, axis2))
- {
- m_pairCache->addOverlappingPair(pHandleEdge, pHandlePrev);
- if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(pHandleEdge, pHandlePrev);
- //AddOverlap(pEdge->m_handle, pPrev->m_handle);
- }
- // update edge reference in other handle
- pHandlePrev->m_maxEdges[axis]++;
- }
- else
- pHandlePrev->m_minEdges[axis]++;
- pHandleEdge->m_minEdges[axis]--;
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
- // decrement
- pEdge--;
- pPrev--;
- }
- #ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
- #endif //DEBUG_BROADPHASE
- }
- // sorting a min edge upwards can only ever *remove* overlaps
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
- {
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
- if (pNext->IsMax())
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- // if next edge is maximum remove any overlap between the two handles
- if (updateOverlaps
- #ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0, handle1, axis1, axis2)
- #endif //USE_OVERLAP_TEST_ON_REMOVES
- )
- {
- m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
- if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
- }
- // update edge reference in other handle
- pHandleNext->m_maxEdges[axis]--;
- }
- else
- pHandleNext->m_minEdges[axis]--;
- pHandleEdge->m_minEdges[axis]++;
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
- // increment
- pEdge++;
- pNext++;
- }
- }
- // sorting a max edge downwards can only ever *remove* overlaps
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
- {
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
- if (!pPrev->IsMax())
- {
- // if previous edge was a minimum remove any overlap between the two handles
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pPrev->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- if (updateOverlaps
- #ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0, handle1, axis1, axis2)
- #endif //USE_OVERLAP_TEST_ON_REMOVES
- )
- {
- //this is done during the overlappingpairarray iteration/narrowphase collision
- m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
- if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
- }
- // update edge reference in other handle
- pHandlePrev->m_minEdges[axis]++;
- ;
- }
- else
- pHandlePrev->m_maxEdges[axis]++;
- pHandleEdge->m_maxEdges[axis]--;
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
- // decrement
- pEdge--;
- pPrev--;
- }
- #ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
- #endif //DEBUG_BROADPHASE
- }
- // sorting a max edge upwards can only ever *add* overlaps
- template <typename BP_FP_INT_TYPE>
- void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
- {
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- if (!pNext->IsMax())
- {
- // if next edge is a minimum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext, axis1, axis2))
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- m_pairCache->addOverlappingPair(handle0, handle1);
- if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(handle0, handle1);
- }
- // update edge reference in other handle
- pHandleNext->m_minEdges[axis]--;
- }
- else
- pHandleNext->m_maxEdges[axis]--;
- pHandleEdge->m_maxEdges[axis]++;
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
- // increment
- pEdge++;
- pNext++;
- }
- }
- #endif
|