-#ifndef Bullet_C_API_H
-#define Bullet_C_API_H
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+/*
+ Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
+ Work in progress, functionality will be added on demand.
+
+ If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
+*/
+
+#ifndef BULLET_C_API_H
+#define BULLET_C_API_H
+
+#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef double plReal;
+#else
+typedef float plReal;
+#endif
+
+typedef plReal plVector3[3];
+typedef plReal plQuaternion[4];
#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
+extern "C" {
+#endif
+
+/* Particular physics SDK */
+ PL_DECLARE_HANDLE(plPhysicsSdkHandle);
+
+/* Dynamics world, belonging to some physics SDK */
+ PL_DECLARE_HANDLE(plDynamicsWorldHandle);
+
+/* Rigid Body that can be part of a Dynamics World */
+ PL_DECLARE_HANDLE(plRigidBodyHandle);
+
+/* Collision Shape/Geometry, property of a Rigid Body */
+ PL_DECLARE_HANDLE(plCollisionShapeHandle);
+
+/* Constraint for Rigid Bodies */
+ PL_DECLARE_HANDLE(plConstraintHandle);
+
+/* Triangle Mesh interface */
+ PL_DECLARE_HANDLE(plMeshInterfaceHandle);
+
+/* Broadphase Scene/Proxy Handles */
+ PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
+ PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
+ PL_DECLARE_HANDLE(plCollisionWorldHandle);
+
+/*
+ Create and Delete a Physics SDK
+*/
+
+ extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc.
+ extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk);
+
+/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
+
+ typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
+
+ extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
+
+ extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp);
+
+ extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+ extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
+
+ extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+/* todo: add pair cache support with queries like add/remove/find pair */
+
+ extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
+
+/* todo: add/remove objects */
+
+
+/* Dynamics World */
+
+ extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
+
+ extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world);
+
+ extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep);
+
+ extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+ extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+
+/* Rigid Body */
+
+ extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape );
+
+ extern void plDeleteRigidBody(plRigidBodyHandle body);
+
+
+/* Collision Shape definition */
+
+ extern plCollisionShapeHandle plNewSphereShape(plReal radius);
+ extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
+ extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCompoundShape();
+ extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
+
+ extern void plDeleteShape(plCollisionShapeHandle shape);
+
+ /* Convex Meshes */
+ extern plCollisionShapeHandle plNewConvexHullShape();
+ extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
+/* Concave static triangle meshes */
+ extern plMeshInterfaceHandle plNewMeshInterface();
+ extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+ extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+ extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
+
+/* SOLID has Response Callback/Table/Management */
+/* PhysX has Triggers, User Callbacks and filtering */
+/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
+
+/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */
+/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */
+
+ /* get world transform */
+ extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+ extern void plGetPosition(plRigidBodyHandle object,plVector3 position);
+ extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
+
+ /* set world transform (position/orientation) */
+ extern void plSetPosition(plRigidBodyHandle object, const plVector3 position);
+ extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
+ extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
+
+ typedef struct plRayCastResult {
+ plRigidBodyHandle m_body;
+ plCollisionShapeHandle m_shape;
+ plVector3 m_positionWorld;
+ plVector3 m_normalWorld;
+ } plRayCastResult;
+
+ extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
+
+ /* Sweep API */
+
+ /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
+
+ /* Continuous Collision Detection API */
double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
#ifdef __cplusplus
}
-#endif // __cplusplus
-
#endif
+#endif //BULLET_C_API_H
+
#include <assert.h>
-#ifdef DEBUG_BROADPHASE
-#include <stdio.h>
-void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
+btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
+:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache)
{
- 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)
- assert(numEdges == m_numHandles*2+1);
-}
-#endif //DEBUG_BROADPHASE
-
-
-btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
-{
- (void)shapeType;
- BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask);
-
- Handle* handle = getHandle(handleId);
-
- return handle;
-}
-
-void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy)
-{
- Handle* handle = static_cast<Handle*>(proxy);
- removeHandle(handle->m_handleId);
-}
-
-void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
-{
- Handle* handle = static_cast<Handle*>(proxy);
- updateHandle(handle->m_handleId,aabbMin,aabbMax);
-
-}
-
-
-
-
-
-
-btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles)
-:btOverlappingPairCache()
-{
- m_invalidPair = 0;
- //assert(bounds.HasVolume());
-
// 1 handle is reserved as sentinel
- btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES);
-
- // init bounds
- m_worldAabbMin = worldAabbMin;
- m_worldAabbMax = worldAabbMax;
-
- btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
-
- BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL;
-
- m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
-
- // allocate handles buffer 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(i + 1);
- m_pHandles[maxHandles - 1].SetNextFree(0);
- }
-
- {
- // allocate edge buffers
- for (int i = 0; i < 3; i++)
- m_pEdges[i] = new 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 = BP_HANDLE_SENTINEL;
- m_pEdges[axis][1].m_handle = 0;
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
- }
-
-}
-
-btAxisSweep3::~btAxisSweep3()
-{
-
- for (int i = 2; i >= 0; i--)
- delete[] m_pEdges[i];
- delete[] m_pHandles;
-}
-
-void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
-{
- btPoint3 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() & BP_HANDLE_MASK) | isMax);
- out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax);
- out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax);
-
-}
-
-
-
-BP_FP_INT_TYPE btAxisSweep3::allocHandle()
-{
- assert(m_firstFreeHandle);
-
- BP_FP_INT_TYPE handle = m_firstFreeHandle;
- m_firstFreeHandle = getHandle(handle)->GetNextFree();
- m_numHandles++;
-
- return handle;
-}
-
-void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle)
-{
- assert(handle > 0 && handle < m_maxHandles);
-
- getHandle(handle)->SetNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
-
- m_numHandles--;
-}
-
-
-
-BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask)
-{
- // 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();
- assert(handle!= 0xcdcd);
-
- Handle* pHandle = getHandle(handle);
-
- pHandle->m_handleId = 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 = 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] = limit - 1;
- pHandle->m_maxEdges[axis] = limit;
- }
-
- // now sort the new edges to their correct position
- sortMinDown(0, pHandle->m_minEdges[0], false);
- sortMaxDown(0, pHandle->m_maxEdges[0], false);
- sortMinDown(1, pHandle->m_minEdges[1], false);
- sortMaxDown(1, pHandle->m_maxEdges[1], false);
- sortMinDown(2, pHandle->m_minEdges[2], true);
- sortMaxDown(2, pHandle->m_maxEdges[2], true);
-
-
- return handle;
-}
-
-
-void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle)
-{
-
- Handle* pHandle = getHandle(handle);
-
- //explicitly remove the pairs containing the proxy
- //we could do it also in the sortMinUp (passing true)
- //todo: compare performance
- removeOverlappingPairsContainingProxy(pHandle);
-
-
- // compute current limit of edge arrays
- int limit = 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 = BP_HANDLE_SENTINEL;
-
- sortMaxUp(axis,max,false);
-
-
- BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
- pEdges[i].m_pos = BP_HANDLE_SENTINEL;
-
-
- sortMinUp(axis,i,false);
-
- pEdges[limit-1].m_handle = 0;
- pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL;
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis,false);
-#endif //DEBUG_BROADPHASE
-
-
- }
-
-
- // free the handle
- freeHandle(handle);
-
-
-}
-
-extern int gOverlappingPairs;
-
-
-void btAxisSweep3::refreshOverlappingPairs()
-{
-
-}
-void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
-{
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
-
- //remove the 'invalid' ones
-#ifdef USE_POPBACK_REMOVAL
- while (m_invalidPair>0)
- {
- m_invalidPair--;
- m_overlappingPairArray.pop_back();
- }
-#else
- m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-#endif
-
-
- int i;
-
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
-
-
- for (i=0;i<m_overlappingPairArray.size();i++)
- {
-
- btBroadphasePair& pair = m_overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- bool hasOverlap = testOverlap(pair.m_pProxy0,pair.m_pProxy1);
-
- if (hasOverlap)
- {
- needsRemoval = callback->processOverlap(pair);
- } else
- {
- needsRemoval = true;
- }
- } else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
-
- if (needsRemoval)
- {
- cleanOverlappingPair(pair);
-
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- m_invalidPair++;
- gOverlappingPairs--;
- }
-
- }
-}
-
-
-bool btAxisSweep3::testOverlap(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;
-}
-
-bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB)
-{
- //optimization 1: check the array index (memory address), instead of the m_pos
-
- for (int axis = 0; axis < 3; axis++)
- {
- if (axis != ignoreAxis)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
- }
-
- //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
-
- /*for (int axis = 0; axis < 3; axis++)
- {
- if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
- m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
- {
- return false;
- }
- }
- */
-
- return true;
-}
-
-void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax)
-{
-// assert(bounds.IsFinite());
- //assert(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);
-
- if (dmax > 0)
- sortMaxUp(axis, emax);
-
- // shrink (only removes overlaps)
- if (dmin > 0)
- sortMinUp(axis, emin);
-
- if (dmax < 0)
- sortMaxDown(axis, emax);
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
- }
-
-
-}
-
-
-
-
-// sorting a min edge downwards can only ever *add* overlaps
-void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, 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
- if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
- {
- 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
-void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, 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())
- {
- // if next edge is maximum remove any overlap between the two handles
- if (updateOverlaps)
- {
- /*
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- btBroadphasePair tmpPair(*handle0,*handle1);
- removeOverlappingPair(tmpPair);
- */
-
- }
-
- // 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++;
- }
-
+ btAssert(maxHandles > 1 && maxHandles < 32767);
}
-// sorting a max edge downwards can only ever *remove* overlaps
-void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, 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
- if (updateOverlaps)
- {
- //this is done during the overlappingpairarray iteration/narrowphase collision
- /*
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pPrev->m_handle);
- btBroadphasePair* pair = findPair(handle0,handle1);
- //assert(pair);
-
- if (pair)
- {
- removeOverlappingPair(*pair);
- }
- */
-
- }
-
- // 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
-void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
+:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
{
- 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())
- {
- // if next edge is a minimum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext))
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- 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++;
- }
-
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 2147483647);
}
#ifndef AXIS_SWEEP_3_H
#define AXIS_SWEEP_3_H
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btVector3.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
-
-
-//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects
-//#define BP_USE_FIXEDPOINT_INT_32 1
-
-#ifdef BP_USE_FIXEDPOINT_INT_32
- #define BP_FP_INT_TYPE unsigned int
- #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles
- #define BP_HANDLE_SENTINEL 0x7fffffff
- #define BP_HANDLE_MASK 0xfffffffe
-#else
- #define BP_FP_INT_TYPE unsigned short int
- #define BP_MAX_HANDLES 32767
- #define BP_HANDLE_SENTINEL 0xffff
- #define BP_HANDLE_MASK 0xfffe
-#endif //BP_USE_FIXEDPOINT_INT_32
+#include "btOverlappingPairCallback.h"
//#define DEBUG_BROADPHASE 1
-/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
-/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats.
-/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos
-class btAxisSweep3 : public btOverlappingPairCache
+/// btAxisSweep3Internal is an internal template class that implements sweep and prune.
+/// 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:
};
public:
- class Handle : public btBroadphaseProxy
+ ATTRIBUTE_ALIGNED16(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_handleId;
+// BP_FP_INT_TYPE m_uniqueId;
BP_FP_INT_TYPE m_pad;
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
- inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
- inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+ 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
-private:
+protected:
btPoint3 m_worldAabbMin; // overall system bounds
btPoint3 m_worldAabbMax; // overall system bounds
btVector3 m_quantize; // scaling factor for quantization
BP_FP_INT_TYPE m_numHandles; // number of active handles
- int m_maxHandles; // max number of 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)
- int m_invalidPair;
+ 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;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
- void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
+ 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:
- btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384);
- virtual ~btAxisSweep3();
- virtual void refreshOverlappingPairs();
+ 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);
+
+ virtual ~btAxisSweep3Internal();
+
+
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask);
- void removeHandle(BP_FP_INT_TYPE handle);
- void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax);
- inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+ BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher);
+ void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+ void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher);
+ SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
- virtual void destroyProxy(btBroadphaseProxy* proxy);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
- bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+
+ 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;
+ }
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#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)
+ assert(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,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher)
+{
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher);
+
+ Handle* handle = getHandle(handleId);
+
+ 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);
+ removeHandle(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);
+ updateHandle(handle->m_uniqueId,aabbMin,aabbMax,dispatcher);
+
+}
+
+
+
+
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<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 maxHandles, btOverlappingPairCache* pairCache )
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ if (!m_pairCache)
+ {
+ void* ptr = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
+ m_pairCache = new(ptr) btOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ //assert(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 and put all handles on free list
+ void* ptr = btAlignedAlloc(sizeof(Handle)*maxHandles,16);
+ m_pHandles = new(ptr) 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(i + 1);
+ m_pHandles[maxHandles - 1].SetNextFree(0);
+ }
+
+ {
+ // allocate edge buffers
+ for (int i = 0; i < 3; i++)
+ {
+ void* ptr = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+ m_pEdges[i] = new(ptr) 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()
+{
+
+ for (int i = 2; i >= 0; i--)
+ {
+ btAlignedFree(m_pEdges[i]);
+ }
+ btAlignedFree(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 btPoint3& point, int isMax) const
+{
+ btPoint3 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);
+
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+ assert(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)
+{
+ assert(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 btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short 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 = 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 = 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] = 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
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+
+
+ // compute current limit of edge arrays
+ int limit = 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);
+
+
+}
+
+extern int gOverlappingPairs;
+#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+#ifdef USE_LAZY_REMOVAL
+
+ if (m_ownsPairCache)
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.heapSort(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)
+ {
+ 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++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///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.heapSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+#endif //USE_LAZY_REMOVAL
+
+
+
+
+}
+
+
+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>::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB)
+{
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ if (axis != ignoreAxis)
+ {
+ if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
+ pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
+ {
+ return false;
+ }
+ }
+ }
+
+ //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
+
+ /*for (int axis = 0; axis < 3; axis++)
+ {
+ if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
+ m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
+ {
+ return false;
+ }
+ }
+ */
+
+ return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher)
+{
+// assert(bounds.IsFinite());
+ //assert(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
+ if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
+ {
+ 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())
+ {
+#ifndef USE_LAZY_REMOVAL
+ // if next edge is maximum remove any overlap between the two handles
+ if (updateOverlaps)
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1);
+
+ }
+#endif //USE_LAZY_REMOVAL
+
+ // 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
+ if (updateOverlaps)
+ {
+ //this is done during the overlappingpairarray iteration/narrowphase collision
+#ifndef USE_LAZY_REMOVAL
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pPrev->m_handle);
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1);
+
+#endif //USE_LAZY_REMOVAL
+
+ }
+
+ // 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);
+
+ if (!pNext->IsMax())
+ {
+ // if next edge is a minimum check the bounds and add an overlap if necessary
+ if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext))
+ {
+ 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++;
+ }
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
+{
+public:
+
+ btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
+
+};
+
+/// bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
+{
+public:
+
+ bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
};
struct btDispatcherInfo;
class btDispatcher;
-struct btBroadphaseProxy;
-#include "../../LinearMath/btVector3.h"
+#include "btBroadphaseProxy.h"
+class btOverlappingPairCache;
+
+#include "LinearMath/btVector3.h"
///BroadphaseInterface for aabb-overlapping object pairs
class btBroadphaseInterface
public:
virtual ~btBroadphaseInterface() {}
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0;
- virtual void destroyProxy(btBroadphaseProxy* proxy)=0;
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0;
- virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0;
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) =0;
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()=0;
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
};
#ifndef BROADPHASE_PROXY_H
#define BROADPHASE_PROXY_H
-#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btAlignedAllocator.h"
/// btDispatcher uses these types
CONE_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE,
CYLINDER_SHAPE_PROXYTYPE,
+ UNIFORM_SCALING_SHAPE_PROXYTYPE,
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
//concave shapes
///btBroadphaseProxy
-struct btBroadphaseProxy
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
- short int m_collisionFilterGroup;
- short int m_collisionFilterMask;
+
+ ///in the case of btMultiSapBroadphase, we store the collifionFilterGroup/Mask in the m_multiSapParentProxy
+ union
+ {
+ struct
+ {
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+ };
+
+ void* m_multiSapParentProxy;
+
+ };
+
+ int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+ int m_unusedPadding; //making the structure 16 bytes, better for alignment etc.
+
+ SIMD_FORCE_INLINE int getUid()
+ {
+ return m_uniqueId;//(int)this;
+ }
//used for memory pools
btBroadphaseProxy() :m_clientObject(0){}
{
}
- static inline bool isPolyhedral(int proxyType)
+
+
+ static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
{
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
- static inline bool isConvex(int proxyType)
+ static SIMD_FORCE_INLINE bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
- static inline bool isConcave(int proxyType)
+ static SIMD_FORCE_INLINE bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_HERE));
}
- static inline bool isCompound(int proxyType)
+ static SIMD_FORCE_INLINE bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
- static inline bool isInfinite(int proxyType)
+ static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
{
return (proxyType == STATIC_PLANE_PROXYTYPE);
}
/// contains a pair of aabb-overlapping objects
-struct btBroadphasePair
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
btBroadphasePair ()
:
{
}
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
*/
+
class btBroadphasePairSortPredicate
{
public:
btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
{
- m_dispatcher = ci.m_dispatcher;
+ m_dispatcher = ci.m_dispatcher1;
}
#ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H
-#include "../../LinearMath/btScalar.h"
+#include "LinearMath/btScalar.h"
struct btBroadphaseProxy;
class btDispatcher;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
- :m_dispatcher(0),
+ :m_dispatcher1(0),
m_manifold(0)
{
}
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
- :m_dispatcher(dispatcher)
+ :m_dispatcher1(dispatcher)
{
(void)temp;
}
- btDispatcher* m_dispatcher;
+ btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
int getDispatcherId();
#ifndef _DISPATCHER_H
#define _DISPATCHER_H
-#include "../../LinearMath/btScalar.h"
+#include "LinearMath/btScalar.h"
class btCollisionAlgorithm;
struct btBroadphaseProxy;
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0;
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+ virtual btPersistentManifold** getInternalManifoldPointer() = 0;
+
+ virtual void* allocateCollisionAlgorithm(int size) = 0;
+
+ virtual void freeCollisionAlgorithm(void* ptr) = 0;
+
};
--- /dev/null
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btMultiSapBroadphase.h"
+
+#include "btSimpleBroadphase.h"
+#include "LinearMath/btAabbUtil2.h"
+
+/// btSapBroadphaseArray m_sapBroadphases;
+
+/// btOverlappingPairCache* m_overlappingPairs;
+extern int gOverlappingPairs;
+
+btMultiSapBroadphase::btMultiSapBroadphase(int maxProxies,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ if (!m_overlappingPairs)
+ {
+ m_ownsPairCache = true;
+ void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
+ m_overlappingPairs = new (mem)btOverlappingPairCache();
+ }
+
+ struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+ {
+ virtual ~btMultiSapOverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+ {
+ btMultiSapBroadphase::btMultiSapProxy* multiSapProxy0 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+ btMultiSapBroadphase::btMultiSapProxy* multiSapProxy1 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+ bool collides = (multiSapProxy0->m_collisionFilterGroup & multiSapProxy1->m_collisionFilterMask) != 0;
+ collides = collides && (multiSapProxy1->m_collisionFilterGroup & multiSapProxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+ };
+
+ void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
+ m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
+
+ m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
+ mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
+ m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
+}
+
+btMultiSapBroadphase::~btMultiSapBroadphase()
+{
+ if (m_ownsPairCache)
+ {
+ btAlignedFree(m_overlappingPairs);
+ }
+}
+
+btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher)
+{
+ void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+ btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+ m_multiSapProxies.push_back(proxy);
+
+ ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+ ///this is needed to be able to calculate the aabb overlap
+ btBroadphaseProxy* simpleProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask, dispatcher);
+ simpleProxy->m_multiSapParentProxy = proxy;
+
+ mem = btAlignedAlloc(sizeof(btChildProxy),16);
+ btChildProxy* childProxyRef = new btChildProxy();
+ childProxyRef->m_proxy = simpleProxy;
+ childProxyRef->m_childBroadphase = m_simpleBroadphase;
+ proxy->m_childProxies.push_back(childProxyRef);
+
+ ///this should deal with inserting/removal into child broadphases
+ setAabb(proxy,aabbMin,aabbMax,dispatcher);
+ return proxy;
+}
+
+void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+ ///not yet
+ btAssert(0);
+
+}
+void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+ btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+ multiProxy->m_aabbMin = aabbMin;
+ multiProxy->m_aabbMax = aabbMax;
+
+ for (int i=0;i<multiProxy->m_childProxies.size();i++)
+ {
+ btChildProxy* childProxyRef = multiProxy->m_childProxies[i];
+ childProxyRef->m_childBroadphase->setAabb(childProxyRef->m_proxy,aabbMin,aabbMax,dispatcher);
+ }
+
+}
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+ m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+#ifndef USE_HASH_PAIRCACHE
+
+ btBroadphasePairArray& overlappingPairArray = m_overlappingPairs->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+ int i;
+
+ for (i=0;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ 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_overlappingPairs->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++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+///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.heapSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+#endif//CLEAN_INVALID_PAIRS
+
+#endif //USE_HASH_PAIRCACHE
+
+}
+
+
+bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
+{
+ btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+ btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+ return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
+ multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
+
+}
--- /dev/null
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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_MULTI_SAP_BROADPHASE
+#define BT_MULTI_SAP_BROADPHASE
+
+#include "btBroadphaseInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCache.h"
+
+class btAxisSweep3;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray<btAxisSweep3*> btSapBroadphaseArray;
+
+///multi SAP broadphase
+///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
+///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+class btMultiSapBroadphase :public btBroadphaseInterface
+{
+ btSapBroadphaseArray m_sapBroadphases;
+
+ btSimpleBroadphase* m_simpleBroadphase;
+
+ btOverlappingPairCache* m_overlappingPairs;
+
+ bool m_ownsPairCache;
+
+ btOverlapFilterCallback* m_filterCallback;
+
+ int m_invalidPair;
+
+ struct btChildProxy
+ {
+ btBroadphaseProxy* m_proxy;
+ btBroadphaseInterface* m_childBroadphase;
+ };
+
+public:
+
+ struct btMultiSapProxy : public btBroadphaseProxy
+ {
+
+ ///array with all the entries that this proxy belongs to
+ btAlignedObjectArray<btChildProxy*> m_childProxies;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ int m_shapeType;
+ void* m_userPtr;
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+
+ btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
+ :m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax),
+ m_shapeType(shapeType),
+ m_userPtr(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask)
+ {
+
+ }
+
+
+ };
+
+protected:
+
+ btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
+
+public:
+
+ btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
+
+ btSapBroadphaseArray getBroadphaseArray()
+ {
+ return m_sapBroadphases;
+ }
+
+ const btSapBroadphaseArray getBroadphaseArray() const
+ {
+ return m_sapBroadphases;
+ }
+
+ virtual ~btMultiSapBroadphase();
+
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_overlappingPairs;
+ }
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_overlappingPairs;
+ }
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
int gOverlappingPairs = 0;
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
btOverlappingPairCache::btOverlappingPairCache():
-m_blockedForChanges(false),
-m_overlapFilterCallback(0)
-//m_NumOverlapBroadphasePair(0)
+ m_overlapFilterCallback(0),
+ m_blockedForChanges(false)
{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+#ifdef USE_HASH_PAIRCACHE
+ growTables();
+#endif //USE_HASH_PAIRCACHE
}
//todo/test: show we erase/delete data, or is it automatic
}
-
-void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair)
-{
-
- int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
- if (findIndex < m_overlappingPairArray.size())
- {
- gOverlappingPairs--;
- btBroadphasePair& pair = m_overlappingPairArray[findIndex];
- cleanOverlappingPair(pair);
-
- m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1);
- m_overlappingPairArray.pop_back();
- }
-}
-
-
-void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
+void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
- delete pair.m_algorithm;;
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm=0;
}
}
}
-
-
-
-void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
-{
- //don't add overlap with own
- assert(proxy0 != proxy1);
-
- if (!needsBroadphaseCollision(proxy0,proxy1))
- return;
-
-
- btBroadphasePair pair(*proxy0,*proxy1);
-
- m_overlappingPairArray.push_back(pair);
- gOverlappingPairs++;
-
-}
-
-///this findPair becomes really slow. Either sort the list to speedup the query, or
-///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
-///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
-///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
- btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
-{
- if (!needsBroadphaseCollision(proxy0,proxy1))
- return 0;
-
- btBroadphasePair tmpPair(*proxy0,*proxy1);
- int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
-
- if (findIndex < m_overlappingPairArray.size())
- {
- //assert(it != m_overlappingPairSet.end());
- btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
- return pair;
- }
- return 0;
-}
-
-
-
-
-
-void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
+void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache)
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
- m_pairCache(pairCache)
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair);
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
- CleanPairCallback cleanPairs(proxy,this);
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
- processAllOverlappingPairs(&cleanPairs);
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
}
-
-
-void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy)
+void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback);
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+#ifdef USE_HASH_PAIRCACHE
+
+
+
+
+
+
+
+btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ gFindPairs++;
+
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+
+ int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
+
+ int index = m_hashTable[hash];
+ while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == BT_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+#include <stdio.h>
+
+void btOverlappingPairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_NULL_PAIR;
+ }
+
+ for(i=0;i<curHashtableSize;i++)
+ {
+
+ const btBroadphasePair& pair = m_overlappingPairArray[i];
+ int proxyId1 = pair.m_pProxy0->getUid();
+ int proxyId2 = pair.m_pProxy1->getUid();
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+ int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btBroadphasePair* btOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+
+ int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
+
+
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ void* mem = &m_overlappingPairArray.expand();
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
+ }
+
+ pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+// pair->m_pProxy0 = proxy0;
+// pair->m_pProxy1 = proxy1;
+ pair->m_algorithm = 0;
+ pair->m_userInfo = 0;
+
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+ gRemovePairs++;
+
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+
+ int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+ cleanOverlappingPair(*pair,dispatcher);
+
+ void* userData = pair->m_userInfo;
+
+ btAssert(pair->m_pProxy0->getUid() == proxyId1);
+ btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ btAssert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_NULL_PAIR);
+
+ int previous = BT_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+
+ // Remove the last pair from the hash table.
+ const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+ int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1);
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_NULL_PAIR);
+
+ previous = BT_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return userData;
+}
+#include <stdio.h>
+
+void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ btBroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+#else
+
+
+
+
+void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+{
+#ifndef USE_LAZY_REMOVAL
+
+ btBroadphasePair findPair(*proxy0,*proxy1);
+
+ int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ gOverlappingPairs--;
+ btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+ void* userData = pair.m_userInfo;
+ cleanOverlappingPair(pair,dispatcher);
+
+ m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+#endif //USE_LAZY_REMOVAL
+
+ return 0;
}
-void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback)
+
+
+
+
+
+btBroadphasePair* btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ //don't add overlap with own
+ assert(proxy0 != proxy1);
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ void* mem = &m_overlappingPairArray.expand();
+ btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+ gOverlappingPairs++;
+ return pair;
+
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ btBroadphasePair tmpPair(*proxy0,*proxy1);
+ int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ //assert(it != m_overlappingPairSet.end());
+ btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ return pair;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+#include <stdio.h>
+
+void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- cleanOverlappingPair(*pair);
+ cleanOverlappingPair(*pair,dispatcher);
- m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
gOverlappingPairs--;
} else
}
}
+
+
+#endif //USE_HASH_PAIRCACHE
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+///disable the USE_HASH_PAIRCACHE define to use a pair manager that sorts the pairs to find duplicates/non-overlap
+#define USE_HASH_PAIRCACHE 1
struct btOverlapCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
+typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
+
+#ifdef USE_HASH_PAIRCACHE
+
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+class btOverlappingPairCache
+{
+ btBroadphasePairArray m_overlappingPairArray;
+ btOverlapFilterCallback* m_overlapFilterCallback;
+ bool m_blockedForChanges;
+
+
+public:
+ btOverlappingPairCache();
+ virtual ~btOverlappingPairCache();
+
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ SIMD_FORCE_INLINE btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ gAddedPairs++;
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ return internalAddPair(proxy0,proxy1);
+ }
+
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+// btBroadphasePair* GetPairs() { return m_pairs; }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ void growTables();
+
+ SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+ {
+ return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+ }
+
+ /*
+ // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ // This assumes proxyId1 and proxyId2 are 16-bit.
+ SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+ {
+ int key = (proxyId2 << 16) | proxyId1;
+ key = ~key + (key << 15);
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057;
+ key = key ^ (key >> 16);
+ return key;
+ }
+ */
+
+
+
+ SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ {
+ int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId1) <<16);
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+ }
+
+
+
+
+
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ {
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+
+ int index = m_hashTable[hash];
+
+ while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == BT_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+
+public:
+
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+
+};
+
+
+
+#else//USE_HASH_PAIRCACHE
+
+#define USE_LAZY_REMOVAL 1
+
///btOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
-class btOverlappingPairCache : public btBroadphaseInterface
+class btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
- btAlignedObjectArray<btBroadphasePair> m_overlappingPairArray;
-
+ btBroadphasePairArray m_overlappingPairArray;
+
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
+
public:
btOverlappingPairCache();
virtual ~btOverlappingPairCache();
- virtual void processAllOverlappingPairs(btOverlapCallback*);
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
- void removeOverlappingPair(btBroadphasePair& pair);
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
- void cleanOverlappingPair(btBroadphasePair& pair);
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
- void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
- void cleanProxyFromPairs(btBroadphaseProxy* proxy);
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy);
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
return collides;
}
-
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
- virtual void refreshOverlappingPairs() =0;
btBroadphasePair* getOverlappingPairArrayPtr()
{
}
};
+#endif //USE_HASH_PAIRCACHE
+
#endif //OVERLAPPING_PAIR_CACHE_H
--- /dev/null
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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 OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+///btOverlappingPairCallback provides user callback to keep track of overlap between objects, like a collision sensor
+class btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCallback()
+ {
+
+ }
+
+ virtual void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
\ No newline at end of file
#include "LinearMath/btMatrix3x3.h"
#include <new>
+extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
- for (int i=0;i<m_numProxies;i++)
+ for (int i=0;i<m_numHandles;i++)
{
- for (int j=i+1;j<m_numProxies;j++)
+ for (int j=i+1;j<m_numHandles;j++)
{
- assert(m_pProxies[i] != m_pProxies[j]);
+ btAssert(&m_pHandles[i] != &m_pHandles[j]);
}
}
}
-btSimpleBroadphase::btSimpleBroadphase(int maxProxies)
- :btOverlappingPairCache(),
- m_firstFreeProxy(0),
- m_numProxies(0),
- m_maxProxies(maxProxies)
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+ :m_pairCache(overlappingPairCache),
+ m_ownsPairCache(false),
+ m_invalidPair(0)
{
- m_proxies = new btSimpleBroadphaseProxy[maxProxies];
- m_freeProxies = new int[maxProxies];
- m_pProxies = new btSimpleBroadphaseProxy*[maxProxies];
-
+ if (!overlappingPairCache)
+ {
+ void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16);
+ m_pairCache = new (mem)btOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ // allocate handles buffer and put all handles on free list
+ void* ptr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
+ m_pHandles = new(ptr) btSimpleBroadphaseProxy[maxProxies];
+ m_maxHandles = maxProxies;
+ m_numHandles = 0;
+ m_firstFreeHandle = 0;
+ m_firstAllocatedHandle = -1;
- int i;
- for (i=0;i<m_maxProxies;i++)
{
- m_freeProxies[i] = i;
+ for (int i = m_firstFreeHandle; i < maxProxies; i++)
+ {
+ m_pHandles[i].SetNextFree(i + 1);
+ m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+ m_pHandles[i].SetNextAllocated(-1);
+ }
+ m_pHandles[maxProxies - 1].SetNextFree(0);
+ m_pHandles[maxProxies - 1].SetNextAllocated(-1);
+
}
+
}
btSimpleBroadphase::~btSimpleBroadphase()
{
- delete[] m_proxies;
- delete []m_freeProxies;
- delete [] m_pProxies;
+ btAlignedFree(m_pHandles);
- /*int i;
- for (i=m_numProxies-1;i>=0;i--)
+ if (m_ownsPairCache)
{
- BP_Proxy* proxy = m_pProxies[i];
- destroyProxy(proxy);
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
}
- */
}
-btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask)
+btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher)
{
- if (m_numProxies >= m_maxProxies)
+ if (m_numHandles >= m_maxHandles)
{
- assert(0);
+ btAssert(0);
return 0; //should never happen, but don't let the game crash ;-)
}
- assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]);
-
- int freeIndex= m_freeProxies[m_firstFreeProxy];
- btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
- m_firstFreeProxy++;
-
- btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
-
- int index = int(proxy - proxy1);
- btAssert(index == freeIndex);
+ assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
- m_pProxies[m_numProxies] = proxy;
- m_numProxies++;
- //validate();
+ int newHandleIndex = allocHandle();
+ btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
return proxy;
}
};
};
-void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg)
+void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
{
- int i;
-
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
- btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
-
- int index = int(proxy0 - proxy1);
- btAssert (index < m_maxProxies);
- m_freeProxies[--m_firstFreeProxy] = index;
+ freeHandle(proxy0);
+
+ m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
- removeOverlappingPairsContainingProxy(proxyOrg);
-
- for (i=0;i<m_numProxies;i++)
- {
- if (m_pProxies[i] == proxyOrg)
- {
- m_pProxies[i] = m_pProxies[m_numProxies-1];
- break;
- }
- }
- m_numProxies--;
//validate();
}
-void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
+void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_min = aabbMin;
}
};
-void btSimpleBroadphase::refreshOverlappingPairs()
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
int i,j;
- for (i=0;i<m_numProxies;i++)
+ if (m_firstAllocatedHandle >= 0)
{
- btBroadphaseProxy* proxy0 = m_pProxies[i];
- for (j=i+1;j<m_numProxies;j++)
+
+ btSimpleBroadphaseProxy* proxy0 = &m_pHandles[m_firstAllocatedHandle];
+
+ for (i=0;i<m_numHandles;i++)
{
- btBroadphaseProxy* proxy1 = m_pProxies[j];
- btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
- btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+ btSimpleBroadphaseProxy* proxy1 = &m_pHandles[m_firstAllocatedHandle];
- if (aabbOverlap(p0,p1))
+ for (j=0;j<m_numHandles;j++)
{
- if ( !findPair(proxy0,proxy1))
+
+ if (proxy0 != proxy1)
{
- addOverlappingPair(proxy0,proxy1);
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+
+ if (aabbOverlap(p0,p1))
+ {
+ if ( !m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->addOverlappingPair(proxy0,proxy1);
+ }
+ } else
+ {
+ #ifdef USE_HASH_PAIRCACHE
+ if ( m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+ }
+ #endif //USE_HASH_PAIRCACHE
+
+ }
}
+ proxy1 = &m_pHandles[proxy1->GetNextAllocated()];
+
}
+ proxy0 = &m_pHandles[proxy0->GetNextAllocated()];
}
- }
+ #ifndef USE_HASH_PAIRCACHE
- CheckOverlapCallback checkOverlap;
+ if (m_ownsPairCache)
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ 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];
- processAllOverlappingPairs(&checkOverlap);
+ bool isDuplicate = (pair == previousPair);
+ previousPair = pair;
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ 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++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///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.heapSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ }
+ #endif //USE_HASH_PAIRCACHE
+ }
}
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+ return aabbOverlap(p0,p1);
+}
+
+
+
{
btVector3 m_min;
btVector3 m_max;
+ int m_nextFree;
+ int m_nextAllocated;
+// int m_handleId;
+
btSimpleBroadphaseProxy() {};
(void)shapeType;
}
+
+ SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
+ SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
+
+ SIMD_FORCE_INLINE void SetNextAllocated(int next) {m_nextAllocated = next;}
+ SIMD_FORCE_INLINE int GetNextAllocated() const {return m_nextAllocated;}
+
};
///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
-class btSimpleBroadphase : public btOverlappingPairCache
+///btSimpleBroadphase is just a unit-test implementation to verify and test other broadphases.
+///So please don't use this class, but use bt32BitAxisSweep3 or btAxisSweep3 instead!
+class btSimpleBroadphase : public btBroadphaseInterface
{
protected:
- btSimpleBroadphaseProxy* m_proxies;
- int* m_freeProxies;
- int m_firstFreeProxy;
+ int m_numHandles; // number of active handles
+ int m_maxHandles; // max number of handles
+ btSimpleBroadphaseProxy* m_pHandles; // handles pool
+ int m_firstFreeHandle; // free handles list
+ int m_firstAllocatedHandle;
- btSimpleBroadphaseProxy** m_pProxies;
- int m_numProxies;
+ int allocHandle()
+ {
-
+ int freeHandle = m_firstFreeHandle;
+ m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+
+ m_pHandles[freeHandle].SetNextAllocated(m_firstAllocatedHandle);
+ m_firstAllocatedHandle = freeHandle;
+
+ m_numHandles++;
+
+ return freeHandle;
+ }
+
+ void freeHandle(btSimpleBroadphaseProxy* proxy)
+ {
+ int handle = int(proxy-m_pHandles);
+ btAssert(handle >= 0 && handle < m_maxHandles);
+
+ proxy->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_firstAllocatedHandle = proxy->GetNextAllocated();
+ proxy->SetNextAllocated(-1);
+
+ m_numHandles--;
+ }
+
+
+ btOverlappingPairCache* m_pairCache;
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
- int m_maxProxies;
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
protected:
- virtual void refreshOverlappingPairs();
+
+
public:
- btSimpleBroadphase(int maxProxies=16384);
+ btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher);
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
-
-
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
};
BroadphaseCollision/btBroadphaseProxy.cpp
BroadphaseCollision/btCollisionAlgorithm.cpp
BroadphaseCollision/btDispatcher.cpp
+ BroadphaseCollision/btMultiSapBroadphase.cpp
BroadphaseCollision/btOverlappingPairCache.cpp
BroadphaseCollision/btSimpleBroadphase.cpp
CollisionDispatch/btCollisionDispatcher.cpp
CollisionDispatch/btCollisionWorld.cpp
CollisionDispatch/btCompoundCollisionAlgorithm.cpp
CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+ CollisionDispatch/btDefaultCollisionConfiguration.cpp
CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
CollisionDispatch/btConvexConvexAlgorithm.cpp
CollisionDispatch/btEmptyCollisionAlgorithm.cpp
CollisionDispatch/btManifoldResult.cpp
CollisionDispatch/btSimulationIslandManager.cpp
CollisionDispatch/btUnionFind.cpp
+ CollisionDispatch/SphereTriangleDetector.cpp
CollisionShapes/btBoxShape.cpp
CollisionShapes/btBvhTriangleMeshShape.cpp
+ CollisionShapes/btCapsuleShape.cpp
CollisionShapes/btCollisionShape.cpp
CollisionShapes/btCompoundShape.cpp
CollisionShapes/btConcaveShape.cpp
CollisionShapes/btConeShape.cpp
CollisionShapes/btConvexHullShape.cpp
CollisionShapes/btConvexShape.cpp
+ CollisionShapes/btConvexInternalShape.cpp
CollisionShapes/btConvexTriangleMeshShape.cpp
CollisionShapes/btCylinderShape.cpp
CollisionShapes/btEmptyShape.cpp
+ CollisionShapes/btHeightfieldTerrainShape.cpp
CollisionShapes/btMinkowskiSumShape.cpp
CollisionShapes/btMultiSphereShape.cpp
CollisionShapes/btOptimizedBvh.cpp
CollisionShapes/btTriangleIndexVertexArray.cpp
CollisionShapes/btTriangleMesh.cpp
CollisionShapes/btTriangleMeshShape.cpp
+ CollisionShapes/btUniformScalingShape.cpp
NarrowPhaseCollision/btContinuousConvexCollision.cpp
NarrowPhaseCollision/btGjkEpa.cpp
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
#ifndef SPHERE_TRIANGLE_DETECTOR_H
#define SPHERE_TRIANGLE_DETECTOR_H
-#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-#include "../../LinearMath/btPoint3.h"
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "LinearMath/btPoint3.h"
class btSphereShape;
--- /dev/null
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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_COLLISION_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+struct btCollisionAlgorithmCreateFunc;
+
+class btStackAlloc;
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///todo: describe the meaning
+class btCollisionConfiguration
+{
+
+public:
+
+ virtual ~btCollisionConfiguration()
+ {
+ }
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+ virtual btStackAlloc* getStackAllocator() = 0;
+
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
#ifndef COLLISION_CREATE_FUNC
#define COLLISION_CREATE_FUNC
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
class btCollisionAlgorithm;
class btCollisionObject;
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
int gNumManifold = 0;
#include <stdio.h>
-
-btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms):
-m_count(0),
-m_useIslands(true),
-m_convexConvexCreateFunc(0),
-m_convexConcaveCreateFunc(0),
-m_swappedConvexConcaveCreateFunc(0),
-m_compoundCreateFunc(0),
-m_swappedCompoundCreateFunc(0),
-m_emptyCreateFunc(0)
-{
- (void)noDefaultAlgorithms;
- int i;
-
- setNearCallback(defaultNearCallback);
- m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
- for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
- {
- for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
- {
- m_doubleDispatch[i][j] = m_emptyCreateFunc;
- }
- }
-}
-//if you want to not link with the default collision algorithms, you can
-//define BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-//in your Bullet library build system
-#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-btCollisionDispatcher::btCollisionDispatcher ():
+btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
m_count(0),
- m_useIslands(true)
+ m_useIslands(true),
+ m_collisionConfiguration(collisionConfiguration)
{
int i;
setNearCallback(defaultNearCallback);
- //default CreationFunctions, filling the m_doubleDispatch table
- m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc;
- m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc;
- m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
- m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc;
- m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc;
- m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
+ m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
+
+ m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
- m_doubleDispatch[i][j] = internalFindCreateFunc(i,j);
+ m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
assert(m_doubleDispatch[i][j]);
}
}
};
-#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
btCollisionDispatcher::~btCollisionDispatcher()
{
- delete m_convexConvexCreateFunc;
- delete m_convexConcaveCreateFunc;
- delete m_swappedConvexConcaveCreateFunc;
- delete m_compoundCreateFunc;
- delete m_swappedCompoundCreateFunc;
- delete m_emptyCreateFunc;
}
btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
btCollisionObject* body0 = (btCollisionObject*)b0;
btCollisionObject* body1 = (btCollisionObject*)b1;
- btPersistentManifold* manifold = new btPersistentManifold (body0,body1);
+ void* mem = 0;
+
+ if (m_persistentManifoldPoolAllocator->getFreeCount())
+ {
+ mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+ } else
+ {
+ mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
+
+ }
+ btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0);
+ manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
return manifold;
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold);
- ///todo: this can be improved a lot, linear search might be slow part!
- int findIndex = m_manifoldsPtr.findLinearSearch(manifold);
- if (findIndex < m_manifoldsPtr.size())
+ int findIndex = manifold->m_index1a;
+ btAssert(findIndex < m_manifoldsPtr.size());
+ m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
+ m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+ m_manifoldsPtr.pop_back();
+
+ manifold->~btPersistentManifold();
+ if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
- m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
- m_manifoldsPtr.pop_back();
- delete manifold;
+ m_persistentManifoldPoolAllocator->free(manifold);
+ } else
+ {
+ btAlignedFree(manifold);
}
}
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
{
-
-#ifdef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher = this;
- ci.m_manifold = sharedManifold;
- btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]
- ->CreateCollisionAlgorithm(ci,body0,body1);
-#else
- btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1);
-#endif //USE_DISPATCH_REGISTRY_ARRAY
- return algo;
-}
+ ci.m_dispatcher1 = this;
+ ci.m_manifold = sharedManifold;
+ btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
-#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
-btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1)
-{
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
- {
- return m_convexConvexCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
- {
- return m_convexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
- {
- return m_swappedConvexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0))
- {
- return m_compoundCreateFunc;
- } else
- {
- if (btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_swappedCompoundCreateFunc;
- }
- }
-
- //failed to find an algorithm
- return m_emptyCreateFunc;
+ return algo;
}
-#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-#ifndef USE_DISPATCH_REGISTRY_ARRAY
-
-btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
-{
- m_count++;
-
- btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher = this;
-
- if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() )
- {
- return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1);
- }
-
- if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave())
- {
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
- }
-
- if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave())
- {
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
- }
-
- if (body0->getCollisionShape()->isCompound())
- {
- return new btCompoundCollisionAlgorithm(ci,body0,body1,false);
- } else
- {
- if (body1->getCollisionShape()->isCompound())
- {
- return new btCompoundCollisionAlgorithm(ci,body0,body1,true);
- }
- }
- //failed to find an algorithm
- return new btEmptyAlgorithm(ci);
-
-}
-#endif //USE_DISPATCH_REGISTRY_ARRAY
bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
{
};
-void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo,this);
- pairCache->processAllOverlappingPairs(&collisionCallback);
+ pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false;
}
}
+
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+ if (m_collisionAlgorithmPoolAllocator->getFreeCount())
+ {
+ return m_collisionAlgorithmPoolAllocator->allocate(size);
+ }
+
+ //warn user for overflow?
+ return btAlignedAlloc(size,16);
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+ if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+ {
+ m_collisionAlgorithmPoolAllocator->free(ptr);
+ } else
+ {
+ btAlignedFree(ptr);
+ }
+}
#ifndef COLLISION__DISPATCHER_H
#define COLLISION__DISPATCHER_H
-#include "../BroadphaseCollision/btDispatcher.h"
-#include "../NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "../CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
class btIDebugDraw;
class btOverlappingPairCache;
-
+class btPoolAllocator;
+class btCollisionConfiguration;
#include "btCollisionCreateFunc.h"
btNearCallback m_nearCallback;
+ btPoolAllocator* m_collisionAlgorithmPoolAllocator;
+
+ btPoolAllocator* m_persistentManifoldPoolAllocator;
+
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
- btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1);
- //default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+ btCollisionConfiguration* m_collisionConfiguration;
-#ifndef USE_DISPATCH_REGISTRY_ARRAY
- btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
-#endif //USE_DISPATCH_REGISTRY_ARRAY
public:
return m_manifoldsPtr[index];
}
- ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support
- btCollisionDispatcher ();
-
- ///a special constructor that doesn't create/register the default collision algorithms
- btCollisionDispatcher(bool noDefaultAlgorithms);
+ btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionDispatcher();
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo);
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher);
void setNearCallback(btNearCallback nearCallback)
{
//by default, Bullet will use this near callback
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
+ virtual void* allocateCollisionAlgorithm(int size);
+
+ virtual void freeCollisionAlgorithm(void* ptr);
+
+ btCollisionConfiguration* getCollisionConfiguration()
+ {
+ return m_collisionConfiguration;
+ }
+
+ const btCollisionConfiguration* getCollisionConfiguration() const
+ {
+ return m_collisionConfiguration;
+ }
+
+ void setCollisionConfiguration(btCollisionConfiguration* config)
+ {
+ m_collisionConfiguration = config;
+ }
+
};
#endif //COLLISION__DISPATCHER_H
3. This notice may not be removed or altered from any source distribution.
*/
+
#include "btCollisionObject.h"
btCollisionObject::btCollisionObject()
: m_broadphaseHandle(0),
m_collisionShape(0),
m_collisionFlags(0),
+ m_islandTag1(-1),
+ m_companionId(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_userObjectPointer(0),
+ m_internalOwner(0),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdSquareMotionThreshold(btScalar(0.)),
}
+
#ifndef COLLISION_OBJECT_H
#define COLLISION_OBJECT_H
-#include "../../LinearMath/btTransform.h"
+#include "LinearMath/btTransform.h"
//island management, m_activationState1
#define ACTIVE_TAG 1
struct btBroadphaseProxy;
class btCollisionShape;
-#include "../../LinearMath/btMotionState.h"
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
enum CollisionFlags
{
CF_STATIC_OBJECT= 1,
};
- inline bool mergesSimulationIslands() const
+ SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
}
- inline bool isStaticObject() const {
+ SIMD_FORCE_INLINE bool isStaticObject() const {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
- inline bool isKinematicObject() const
+ SIMD_FORCE_INLINE bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
- inline bool isStaticOrKinematicObject() const
+ SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
{
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
}
- inline bool hasContactResponse() const {
+ SIMD_FORCE_INLINE bool hasContactResponse() const {
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
}
m_collisionShape = collisionShape;
}
- const btCollisionShape* getCollisionShape() const
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
- btCollisionShape* getCollisionShape()
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btQuickprof.h"
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize)
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
:m_dispatcher1(dispatcher),
-m_broadphasePairCache(pairCache),
-m_ownsDispatcher(false),
-m_ownsBroadphasePairCache(false)
+m_broadphasePairCache(pairCache)
{
- m_stackAlloc = new btStackAlloc(stackSize);
+ m_stackAlloc = collisionConfiguration->getStackAllocator();
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
}
btCollisionWorld::~btCollisionWorld()
{
- m_stackAlloc->destroy();
- delete m_stackAlloc;
//clean up remaining objects
int i;
//
// only clear the cached algorithms
//
- getBroadphase()->cleanProxyFromPairs(bp);
- getBroadphase()->destroyProxy(bp);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
}
}
- if (m_ownsDispatcher)
- delete m_dispatcher1;
- if (m_ownsBroadphasePairCache)
- delete m_broadphasePairCache;
}
type,
collisionObject,
collisionFilterGroup,
- collisionFilterMask
+ collisionFilterMask,
+ m_dispatcher1
)) ;
for (int i=0;i<m_collisionObjects.size();i++)
{
m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
- m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
+ m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1);
}
- m_broadphasePairCache->refreshOverlappingPairs();
-
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
END_PROFILE("perform Broadphase Collision Detection");
btDispatcher* dispatcher = getDispatcher();
if (dispatcher)
- dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo);
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
END_PROFILE("performDiscreteCollisionDetection");
}
+
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
//
// only clear the cached algorithms
//
- getBroadphase()->cleanProxyFromPairs(bp);
- getBroadphase()->destroyProxy(bp);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
collisionObject->setBroadphaseHandle(0);
}
}
btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver;
+#define USE_SUBSIMPLEX_CONVEX_CAST 1
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
- //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
- //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
-
+#else
+ //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
+ //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{
//add hit
if (castResult.m_normal.length2() > btScalar(0.0001))
{
- castResult.m_normal.normalize();
+
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ //rotate normal into worldspace
+ castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+ castResult.m_normal.normalize();
btCollisionWorld::LocalRayResult localRayResult
(
collisionObject,
castResult.m_fraction
);
- resultCallback.AddSingleResult(localRayResult);
+ bool normalInWorldSpace = true;
+ resultCallback.AddSingleResult(localRayResult, normalInWorldSpace);
}
}
hitNormalLocal,
hitFraction);
- return m_resultCallback->AddSingleResult(rayResult);
+ bool normalInWorldSpace = false;
+ return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
}
class btCollisionShape;
class btConvexShape;
class btBroadphaseInterface;
-#include "../../LinearMath/btVector3.h"
-#include "../../LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
#include "btCollisionObject.h"
#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray
-#include "../BroadphaseCollision/btOverlappingPairCache.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btAlignedObjectArray.h"
///CollisionWorld is interface and container for the collision detection
class btCollisionWorld
btStackAlloc* m_stackAlloc;
- btOverlappingPairCache* m_broadphasePairCache;
+ btBroadphaseInterface* m_broadphasePairCache;
- bool m_ownsDispatcher;
- bool m_ownsBroadphasePairCache;
-
public:
//this constructor doesn't own the dispatcher and paircache/broadphase
- btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024);
+ btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionWorld();
btOverlappingPairCache* getPairCache()
{
- return m_broadphasePairCache;
+ return m_broadphasePairCache->getOverlappingPairCache();
}
:m_closestHitFraction(btScalar(1.))
{
}
- virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0;
+ virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
};
struct ClosestRayResultCallback : public RayResultCallback
btVector3 m_hitPointWorld;
btCollisionObject* m_collisionObject;
- virtual btScalar AddSingleResult(LocalRayResult& rayResult)
+ virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
- m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ if (normalInWorldSpace)
+ {
+ m_hitNormalWorld = rayResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+ }
m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
return rayResult.m_hitFraction;
}
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
-:m_isSwapped(isSwapped)
+:btCollisionAlgorithm(ci),
+m_isSwapped(isSwapped)
{
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
btCollisionShape* childShape = compoundShape->getChildShape(i);
btCollisionShape* orgShape = colObj->getCollisionShape();
colObj->setCollisionShape( childShape );
- m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj);
+ m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj);
colObj->setCollisionShape( orgShape );
}
}
int i;
for (i=0;i<numChildren;i++)
{
- delete m_childCollisionAlgorithms[i];
+ m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
}
}
#ifndef COMPOUND_COLLISION_ALGORITHM_H
#define COMPOUND_COLLISION_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../BroadphaseCollision/btDispatcher.h"
-#include "../BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "../NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
/// Place holder, not fully implemented yet
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btCompoundCollisionAlgorithm(ci,body0,body1,false);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
}
};
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btCompoundCollisionAlgorithm(ci,body0,body1,true);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
}
};
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
: btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
-m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped)
+m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
{
}
//aabb filter is already applied!
btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher = m_dispatcher;
+ ci.m_dispatcher1 = m_dispatcher;
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
ob->setCollisionShape( &tm );
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
///this should use the btDispatcher, so the actual registered algorithm is used
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
- delete colAlgo;
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->setCollisionShape( tmpShape );
}
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
+ resultOut->refreshContactPoints();
}
-
+
}
}
#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../BroadphaseCollision/btDispatcher.h"
-#include "../BroadphaseCollision/btBroadphaseInterface.h"
-#include "../CollisionShapes/btTriangleCallback.h"
-#include "../NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher;
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
void clearCache();
- inline const btVector3& getAabbMin() const
+ SIMD_FORCE_INLINE const btVector3& getAabbMin() const
{
return m_aabbMin;
}
- inline const btVector3& getAabbMax() const
+ SIMD_FORCE_INLINE const btVector3& getAabbMax() const
{
return m_aabbMax;
}
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
}
};
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
}
};
-btConvexConvexAlgorithm::CreateFunc::CreateFunc()
-{
- m_ownsSolvers = true;
- m_simplexSolver = new btVoronoiSimplexSolver();
- m_pdSolver = new btGjkEpaPenetrationDepthSolver;
-}
+
btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
- m_ownsSolvers = false;
m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver;
}
btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
{
- if (m_ownsSolvers){
- delete m_simplexSolver;
- delete m_pdSolver;
- }
}
btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#endif
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+
}
#ifndef CONVEX_CONVEX_ALGORITHM_H
#define CONVEX_CONVEX_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../NarrowPhaseCollision/btGjkPairDetector.h"
-#include "../NarrowPhaseCollision/btPersistentManifold.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
class btConvexPenetrationDepthSolver;
{
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
- bool m_ownsSolvers;
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
- CreateFunc();
+
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
+ return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
}
};
--- /dev/null
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btDefaultCollisionConfiguration.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+#define DEFAULT_MAX_OVERLAPPING_PAIRS 65535
+#define DEFAULT_STACK_ALLOCATOR_SIZE (5*1024*1024)
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
+{
+
+ void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
+ m_simplexSolver = new (mem)btVoronoiSimplexSolver();
+ mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+ m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
+ m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+ m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+ m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
+ m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
+ m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
+ mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
+ m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
+ m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+ m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+ m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+ m_boxSphereCF->m_swapped = true;
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+ m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+ m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+ m_triangleSphereCF->m_swapped = true;
+
+
+ ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+ int maxSize = sizeof(btConvexConvexAlgorithm);
+ int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
+ int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
+ int maxSize4 = sizeof(btEmptyAlgorithm);
+
+ int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
+ collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
+
+ if (stackAlloc)
+ {
+ m_ownsStackAllocator = false;
+ this->m_stackAlloc = stackAlloc;
+ } else
+ {
+ m_ownsStackAllocator = true;
+ void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
+ m_stackAlloc = new(mem)btStackAlloc(DEFAULT_STACK_ALLOCATOR_SIZE);
+ }
+
+ if (persistentManifoldPool)
+ {
+ m_ownsPersistentManifoldPool = false;
+ m_persistentManifoldPool = persistentManifoldPool;
+ } else
+ {
+ m_ownsPersistentManifoldPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),DEFAULT_MAX_OVERLAPPING_PAIRS);
+ }
+
+ if (collisionAlgorithmPool)
+ {
+ m_ownsCollisionAlgorithmPool = false;
+ m_collisionAlgorithmPool = collisionAlgorithmPool;
+ } else
+ {
+ m_ownsCollisionAlgorithmPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,DEFAULT_MAX_OVERLAPPING_PAIRS);
+ }
+
+
+}
+
+btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
+{
+ if (m_ownsStackAllocator)
+ {
+ m_stackAlloc->destroy();
+ m_stackAlloc->~btStackAlloc();
+ btAlignedFree(m_stackAlloc);
+ }
+ if (m_ownsCollisionAlgorithmPool)
+ {
+ m_collisionAlgorithmPool->~btPoolAllocator();
+ btAlignedFree(m_collisionAlgorithmPool);
+ }
+ if (m_ownsPersistentManifoldPool)
+ {
+ m_persistentManifoldPool->~btPoolAllocator();
+ btAlignedFree(m_persistentManifoldPool);
+ }
+
+ m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexConvexCreateFunc);
+
+ m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexConcaveCreateFunc);
+ m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedConvexConcaveCreateFunc);
+
+ m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_compoundCreateFunc);
+
+ m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedCompoundCreateFunc);
+
+ m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_emptyCreateFunc);
+
+ m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereSphereCF);
+
+ m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereBoxCF);
+ m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_boxSphereCF);
+ m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_sphereTriangleCF);
+ m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_triangleSphereCF);
+
+ m_simplexSolver->~btVoronoiSimplexSolver();
+ btAlignedFree(m_simplexSolver);
+ m_pdSolver->~btGjkEpaPenetrationDepthSolver();
+ btAlignedFree(m_pdSolver);
+
+
+}
+
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereSphereCF;
+ }
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+ {
+ return m_sphereBoxCF;
+ }
+
+ if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_boxSphereCF;
+ }
+
+ if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+ {
+ return m_sphereTriangleCF;
+ }
+
+ if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+ {
+ return m_triangleSphereCF;
+ }
+
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+ {
+ return m_convexConvexCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+ {
+ return m_convexConcaveCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+ {
+ return m_swappedConvexConcaveCreateFunc;
+ }
+
+ if (btBroadphaseProxy::isCompound(proxyType0))
+ {
+ return m_compoundCreateFunc;
+ } else
+ {
+ if (btBroadphaseProxy::isCompound(proxyType1))
+ {
+ return m_swappedCompoundCreateFunc;
+ }
+ }
+
+ //failed to find an algorithm
+ return m_emptyCreateFunc;
+}
--- /dev/null
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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_DEFAULT_COLLISION_CONFIGURATION
+#define BT_DEFAULT_COLLISION_CONFIGURATION
+
+#include "btCollisionConfiguration.h"
+class btVoronoiSimplexSolver;
+class btGjkEpaPenetrationDepthSolver;
+
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///todo: describe the meaning
+class btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+
+ int m_persistentManifoldPoolSize;
+
+ btStackAlloc* m_stackAlloc;
+ bool m_ownsStackAllocator;
+
+ btPoolAllocator* m_persistentManifoldPool;
+ bool m_ownsPersistentManifoldPool;
+
+ btPoolAllocator* m_collisionAlgorithmPool;
+ bool m_ownsCollisionAlgorithmPool;
+
+ //default simplex/penetration depth solvers
+ btVoronoiSimplexSolver* m_simplexSolver;
+ btGjkEpaPenetrationDepthSolver* m_pdSolver;
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
+ btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
+ btCollisionAlgorithmCreateFunc* m_boxSphereCF;
+ btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
+ btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
+
+public:
+
+ btDefaultCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0);
+
+ virtual ~btDefaultCollisionConfiguration();
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool()
+ {
+ return m_persistentManifoldPool;
+ }
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool()
+ {
+ return m_collisionAlgorithmPool;
+ }
+
+ virtual btStackAlloc* getStackAllocator()
+ {
+ return m_stackAlloc;
+ }
+
+
+ btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+
+};
+
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
+
#ifndef EMPTY_ALGORITH
#define EMPTY_ALGORITH
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
#define ATTRIBUTE_ALIGNED(a)
{
(void)body0;
(void)body1;
- return new btEmptyAlgorithm(ci);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
+ return new(mem) btEmptyAlgorithm(ci);
}
};
}
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
-
+ newPt.m_positionWorldOnA = pointA;
+ newPt.m_positionWorldOnB = pointInWorld;
+
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
+
+ ///todo, check this for any side effects
+ if (insertIndex >= 0)
+ {
+ //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
+ m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
+ } else
+ {
+ m_manifoldPtr->AddManifoldPoint(newPt);
+ }
+
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
}
- if (insertIndex >= 0)
- {
- //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
- m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
- } else
- {
- m_manifoldPtr->AddManifoldPoint(newPt);
- }
}
#define MANIFOLD_RESULT_H
class btCollisionObject;
-class btPersistentManifold;
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btManifoldPoint;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-#include "../../LinearMath/btTransform.h"
+#include "LinearMath/btTransform.h"
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback;
m_manifoldPtr = manifoldPtr;
}
+ const btPersistentManifold* getPersistentManifold() const
+ {
+ return m_manifoldPtr;
+ }
+ btPersistentManifold* getPersistentManifold()
+ {
+ return m_manifoldPtr;
+ }
+
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{
m_partId0=partId0;
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
+ SIMD_FORCE_INLINE void refreshContactPoints()
+ {
+ btAssert(m_manifoldPtr);
+ if (!m_manifoldPtr->getNumContacts())
+ return;
+
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+
+ if (isSwapped)
+ {
+ m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
+ } else
+ {
+ m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
+ }
+ }
};
}
-void btSimulationIslandManager::findUnions(btDispatcher* dispatcher)
+void btSimulationIslandManager::findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld)
{
{
- for (int i=0;i<dispatcher->getNumManifolds();i++)
- {
- const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- //static objects (invmass btScalar(0.)) don't merge !
+ btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+ for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
+ {
+ const btBroadphasePair& collisionPair = pairPtr[i];
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
}
// do the union find
- findUnions(dispatcher);
+ findUnions(dispatcher,colWorld);
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
{
-
-
- /*if (0)
- {
- int maxNumManifolds = dispatcher->getNumManifolds();
- btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher;
- btPersistentManifold** manifold = colDis->getInternalManifoldPointer();
- callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0);
- return;
- }
- */
-
-
BEGIN_PROFILE("islandUnionFindAndHeapSort");
//we are going to sort the unionfind array, and store the element id in the size
}
}
- btAlignedObjectArray<btPersistentManifold*> islandmanifold;
+
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
- islandmanifold.reserve(maxNumManifolds);
+#define SPLIT_ISLANDS 1
+#ifdef SPLIT_ISLANDS
+
+
+#endif //SPLIT_ISLANDS
+
+
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
{
//kinematic objects don't merge islands, but wake up all connected objects
- if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+ if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
colObj1->activate();
}
- if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+ if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
{
colObj0->activate();
}
-
- //filtering for response
+#ifdef SPLIT_ISLANDS
+ // //filtering for response
if (dispatcher->needsResponse(colObj0,colObj1))
- islandmanifold.push_back(manifold);
+ m_islandmanifold.push_back(manifold);
+#endif //SPLIT_ISLANDS
}
}
- int numManifolds = int (islandmanifold.size());
-
+#ifndef SPLIT_ISLANDS
+ btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
+
+ callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
+#else
// Sort manifolds, based on islands
// Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
+ int numManifolds = int (m_islandmanifold.size());
+
//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
- islandmanifold.heapSort(btPersistentManifoldSortPredicate());
+ m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
END_PROFILE("islandUnionFindAndHeapSort");
- btAlignedObjectArray<btCollisionObject*> islandBodies;
+
+// printf("Start Islands\n");
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
- islandBodies.push_back(colObj0);
+ m_islandBodies.push_back(colObj0);
if (!colObj0->isActive())
islandSleeping = true;
}
if (startManifoldIndex<numManifolds)
{
- int curIslandId = getIslandId(islandmanifold[startManifoldIndex]);
+ int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
- startManifold = &islandmanifold[startManifoldIndex];
+ startManifold = &m_islandmanifold[startManifoldIndex];
- for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++)
+ for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
if (!islandSleeping)
{
- callback->ProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId);
+ callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
+// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
}
if (numIslandManifolds)
startManifoldIndex = endManifoldIndex;
}
- islandBodies.resize(0);
+ m_islandBodies.resize(0);
}
+#endif //SPLIT_ISLANDS
-
+ m_islandmanifold.resize(0);
}
#ifndef SIMULATION_ISLAND_MANAGER_H
#define SIMULATION_ISLAND_MANAGER_H
-#include "../CollisionDispatch/btUnionFind.h"
+#include "BulletCollision/CollisionDispatch/btUnionFind.h"
#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
class btCollisionObject;
class btCollisionWorld;
class btDispatcher;
+class btPersistentManifold;
+
///SimulationIslandManager creates and handles simulation islands, using btUnionFind
class btSimulationIslandManager
{
btUnionFind m_unionFind;
+ btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
+ btAlignedObjectArray<btCollisionObject* > m_islandBodies;
+
+
public:
btSimulationIslandManager();
virtual ~btSimulationIslandManager();
virtual void storeIslandActivationState(btCollisionWorld* world);
- void findUnions(btDispatcher* dispatcher);
+ void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
if (dist < SIMD_EPSILON)
{
btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
/// report a contact. internally this will be kept persistent, and contact reduction is done
- resultOut->setPersistentManifold(m_manifoldPtr);
resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
}
-
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr->getNumContacts())
+ {
+ resultOut->refreshContactPoints();
+ }
+ }
}
btVector3 bounds[2];
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
- bounds[0] = -boxShape->getHalfExtents();
- bounds[1] = boxShape->getHalfExtents();
+ bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
+ bounds[1] = boxShape->getHalfExtentsWithoutMargin();
margins = boxShape->getMargin();//also add sphereShape margin?
btVector3 p0, tmp, prel, n[6], normal;
btScalar fSep = btScalar(-10000000.0), fSepThis;
+ // set p0 and normal to a default value to shup up GCC
+ p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+
n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );
#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
#define SPHERE_BOX_COLLISION_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
-#include "../../LinearMath/btVector3.h"
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
- return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
- return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};
if (!m_manifoldPtr)
return;
+ resultOut->setPersistentManifold(m_manifoldPtr);
+
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
+ m_manifoldPtr->clearManifold();
+
///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1))
+ {
return;
-
+ }
///distance (negative means penetration)
btScalar dist = len - (radius0+radius1);
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
- resultOut->setPersistentManifold(m_manifoldPtr);
+
+
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
+ //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new)
+
}
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
class btPersistentManifold;
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
+ return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
}
};
if (!m_manifoldPtr)
return;
- btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape();
- btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape();
+ btCollisionObject* sphereObj = m_swapped? col1 : col0;
+ btCollisionObject* triObj = m_swapped? col0 : col1;
+
+ btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
+ btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ if (m_ownManifold)
+ resultOut->refreshContactPoints();
+
}
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
-#include "../BroadphaseCollision/btCollisionAlgorithm.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
+#include "btCollisionDispatcher.h"
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
- return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
+
+ return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
}
};
+
btUnionFind::~btUnionFind()
{
Free();
#ifndef UNION_FIND_H
#define UNION_FIND_H
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
#define USE_PATH_COMPRESSION 1
void reset(int N);
- inline int getNumElements() const
+ SIMD_FORCE_INLINE int getNumElements() const
{
return int(m_elements.size());
}
- inline bool isRoot(int x) const
+ SIMD_FORCE_INLINE bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}
#include "btBoxShape.h"
-btVector3 btBoxShape::getHalfExtents() const
-{
- return m_implicitShapeDimensions * m_localScaling;
-}
+
//{
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
- btVector3 halfExtents = getHalfExtents();
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
}
-void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
+void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithMargin();
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());
#include "btPolyhedralConvexShape.h"
#include "btCollisionMargin.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btSimdMinMax.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btMinMax.h"
///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box
class btBoxShape: public btPolyhedralConvexShape
public:
- btVector3 getHalfExtents() const;
-
+ btVector3 getHalfExtentsWithMargin() const
+ {
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
+ return halfExtents;
+ }
+
+ const btVector3& getHalfExtentsWithoutMargin() const
+ {
+ return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+ }
+
+
virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ halfExtents += margin;
- btVector3 halfExtents = getHalfExtents();
-
- btVector3 supVertex;
- supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
- vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
- vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
-
- return supVertex;
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
- virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
- btVector3 halfExtents = getHalfExtents();
- btVector3 margin(getMargin(),getMargin(),getMargin());
- halfExtents -= margin;
-
- return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
- vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
- vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+ return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
- btVector3 halfExtents = getHalfExtents();
- btVector3 margin(getMargin(),getMargin(),getMargin());
- halfExtents -= margin;
-
-
+ const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
for (int i=0;i<numVectors;i++)
{
const btVector3& vec = vectors[i];
- supportVerticesOut[i].setValue(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
- vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
- vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
+ supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
}
btBoxShape( const btVector3& boxHalfExtents)
{
- m_implicitShapeDimensions = boxHalfExtents;
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
};
-
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //correct the m_implicitShapeDimensions for the margin
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+
+ btConvexInternalShape::setMargin(collisionMargin);
+ btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+ }
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+ btConvexInternalShape::setLocalScaling(scaling);
+
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+ }
+
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const
{
virtual void getVertex(int i,btVector3& vtx) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3(
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
virtual void getPlaneEquation(btVector4& plane,int i) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
//debugging
- virtual char* getName()const
+ virtual const char* getName()const
{
return "Box";
}
#endif //OBB_BOX_MINKOWSKI_H
+
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
-btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression)
-:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression)
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
{
//construct bvh from meshInterface
#ifndef DISABLE_BVH
- m_bvh = new btOptimizedBvh();
btVector3 bvhAabbMin,bvhAabbMax;
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
- m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+
+ if (buildBvh)
+ {
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ m_bvh = new (mem) btOptimizedBvh();
+ m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+ m_ownsBvh = true;
+ }
#endif //DISABLE_BVH
}
-btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
-:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression)
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
{
//construct bvh from meshInterface
#ifndef DISABLE_BVH
- m_bvh = new btOptimizedBvh();
- m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+ if (buildBvh)
+ {
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ m_bvh = new (mem) btOptimizedBvh();
+
+ m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+ m_ownsBvh = true;
+ }
#endif //DISABLE_BVH
btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
{
- delete m_bvh;
+ if (m_ownsBvh)
+ {
+ m_bvh->~btOptimizedBvh();
+ btAlignedFree(m_bvh);
+ }
}
//perform bvh tree traversal and report overlapping triangles to 'callback'
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
- delete m_bvh;
+ if (m_ownsBvh)
+ {
+ m_bvh->~btOptimizedBvh();
+ btAlignedFree(m_bvh);
+ }
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
- m_bvh = new btOptimizedBvh();
+ void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+ m_bvh = new(mem) btOptimizedBvh();
//rebuild the bvh...
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
#include "btTriangleMeshShape.h"
#include "btOptimizedBvh.h"
+#include "LinearMath/btAlignedAllocator.h"
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
btOptimizedBvh* m_bvh;
bool m_useQuantizedAabbCompression;
- bool m_pad[12];////need padding due to alignment
+ bool m_ownsBvh;
+ bool m_pad[11];////need padding due to alignment
public:
- btBvhTriangleMeshShape() :btTriangleMeshShape(0) {};
- btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression);
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {};
+ btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
- btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+ btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
virtual ~btBvhTriangleMeshShape();
void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
//debugging
- virtual char* getName()const {return "BVHTRIANGLEMESH";}
+ virtual const char* getName()const {return "BVHTRIANGLEMESH";}
virtual void setLocalScaling(const btVector3& scaling);
{
return m_bvh;
}
+
+
+ void setOptimizedBvh(btOptimizedBvh* bvh)
+ {
+ btAssert(!m_bvh);
+ btAssert(!m_ownsBvh);
+
+ m_bvh = bvh;
+ m_ownsBvh = false;
+ }
+
bool usesQuantizedAabbCompression() const
{
return m_useQuantizedAabbCompression;
}
-void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
+void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//as an approximation, take the inertia of the box that bounds the spheres
#ifndef BT_CAPSULE_SHAPE_H
#define BT_CAPSULE_SHAPE_H
-#include "btConvexShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///btCapsuleShape represents a capsule around the Y axis
///A more general solution that can represent capsules is the btMultiSphereShape
-class btCapsuleShape : public btConvexShape
+class btCapsuleShape : public btConvexInternalShape
{
public:
btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
/// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; }
- virtual char* getName()const
+ virtual const char* getName()const
{
return "CapsuleShape";
}
#ifndef COLLISION_SHAPE_H
#define COLLISION_SHAPE_H
-#include "../../LinearMath/btTransform.h"
-#include "../../LinearMath/btVector3.h"
-#include "../../LinearMath/btMatrix3x3.h"
-#include "../../LinearMath/btPoint3.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btPoint3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects.
class btCollisionShape
#ifndef __SPU__
- inline bool isPolyhedral() const
+ SIMD_FORCE_INLINE bool isPolyhedral() const
{
return btBroadphaseProxy::isPolyhedral(getShapeType());
}
- inline bool isConvex() const
+ SIMD_FORCE_INLINE bool isConvex() const
{
return btBroadphaseProxy::isConvex(getShapeType());
}
- inline bool isConcave() const
+ SIMD_FORCE_INLINE bool isConcave() const
{
return btBroadphaseProxy::isConcave(getShapeType());
}
- inline bool isCompound() const
+ SIMD_FORCE_INLINE bool isCompound() const
{
return btBroadphaseProxy::isCompound(getShapeType());
}
///isInfinite is used to catch simulation error (aabb check)
- inline bool isInfinite() const
+ SIMD_FORCE_INLINE bool isInfinite() const
{
return btBroadphaseProxy::isInfinite(getShapeType());
}
virtual int getShapeType() const=0;
virtual void setLocalScaling(const btVector3& scaling) =0;
virtual const btVector3& getLocalScaling() const =0;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0;
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
//debugging support
- virtual char* getName()const =0 ;
+ virtual const char* getName()const =0 ;
#endif //__SPU__
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
{
- m_childTransforms.push_back(localTransform);
- m_childShapes.push_back(shape);
+ //m_childTransforms.push_back(localTransform);
+ //m_childShapes.push_back(shape);
+ btCompoundShapeChild child;
+ child.m_transform = localTransform;
+ child.m_childShape = shape;
+ child.m_childShapeType = shape->getShapeType();
+ child.m_childMargin = shape->getMargin();
+
+ m_children.push_back(child);
//extend the local aabbMin/aabbMax
btVector3 localAabbMin,localAabbMax;
aabbMax = center + extent;
}
-void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
+void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//approximation: take the inertia from the aabb for now
btTransform ident;
#include "btCollisionShape.h"
-#include "../../LinearMath/btVector3.h"
-#include "../../LinearMath/btTransform.h"
-#include "../../LinearMath/btMatrix3x3.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
class btOptimizedBvh;
+ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTransform m_transform;
+ btCollisionShape* m_childShape;
+ int m_childShapeType;
+ btScalar m_childMargin;
+};
+
/// btCompoundShape allows to store multiple other btCollisionShapes
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape.
-class btCompoundShape : public btCollisionShape
+ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
{
- btAlignedObjectArray<btTransform> m_childTransforms;
- btAlignedObjectArray<btCollisionShape*> m_childShapes;
+ //btAlignedObjectArray<btTransform> m_childTransforms;
+ //btAlignedObjectArray<btCollisionShape*> m_childShapes;
+ btAlignedObjectArray<btCompoundShapeChild> m_children;
btVector3 m_localAabbMin;
btVector3 m_localAabbMax;
btOptimizedBvh* m_aabbTree;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btCompoundShape();
virtual ~btCompoundShape();
int getNumChildShapes() const
{
- return int (m_childShapes.size());
+ return int (m_children.size());
}
btCollisionShape* getChildShape(int index)
{
- return m_childShapes[index];
+ return m_children[index].m_childShape;
}
const btCollisionShape* getChildShape(int index) const
{
- return m_childShapes[index];
+ return m_children[index].m_childShape;
}
- btTransform& getChildTransform(int index)
+ btTransform getChildTransform(int index)
{
- return m_childTransforms[index];
+ return m_children[index].m_transform;
}
- const btTransform& getChildTransform(int index) const
+ const btTransform getChildTransform(int index) const
+ {
+ return m_children[index].m_transform;
+ }
+
+
+ btCompoundShapeChild* getChildList()
{
- return m_childTransforms[index];
+ return &m_children[0];
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
return m_localScaling;
}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;}
{
return m_collisionMargin;
}
- virtual char* getName()const
+ virtual const char* getName()const
{
return "Compound";
}
#define CONCAVE_SHAPE_H
#include "btCollisionShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btTriangleCallback.h"
#ifndef CONE_MINKOWSKI_H
#define CONE_MINKOWSKI_H
-#include "btConvexShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///btConeShape implements a Cone shape, around the Y axis
-class btConeShape : public btConvexShape
+class btConeShape : public btConvexInternalShape
{
btScalar getHeight() const { return m_height;}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia)
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
btTransform identity;
identity.setIdentity();
virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; }
- virtual char* getName()const
+ virtual const char* getName()const
{
return "Cone";
}
#define CONVEX_HULL_SHAPE_H
#include "btPolyhedralConvexShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices)
///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices.
btAlignedObjectArray<btPoint3> m_points;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; }
//debugging
- virtual char* getName()const {return "Convex";}
+ virtual const char* getName()const {return "Convex";}
virtual int getNumVertices() const;
--- /dev/null
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+
+#include "btConvexInternalShape.h"
+
+
+btConvexInternalShape::btConvexInternalShape()
+: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
+m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+{
+}
+
+
+void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+{
+ m_localScaling = scaling;
+}
+
+
+
+void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+{
+
+ btScalar margin = getMargin();
+