minor tweaks to demos: enable constraint debug drawing in AllBulletDemos, default constraint debugging size set to 0.3,

set svn:eol-style native for folder files
http://code.google.com/p/bullet/issues/detail?id=191
This commit is contained in:
erwin.coumans
2009-02-18 22:52:03 +00:00
parent d9218378b0
commit 8acadeb711
126 changed files with 34617 additions and 34560 deletions

View File

@@ -1,71 +1,71 @@
cmake_minimum_required(VERSION 2.4)
PROJECT(BULLET_PHYSICS)
SET(BULLET_VERSION 2.74)
IF (NOT CMAKE_BUILD_TYPE)
# SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_BUILD_TYPE "Release")
ENDIF (NOT CMAKE_BUILD_TYPE)
IF(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
ENDIF(COMMAND cmake_policy)
# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system
# This should be the case.
FIND_PACKAGE(OpenGL)
IF (OPENGL_FOUND)
MESSAGE("OPENGL FOUND")
MESSAGE(${OPENGL_LIBRARIES})
ELSE (OPENGL_FOUND)
MESSAGE("OPENGL NOT FOUND")
SET(OPENGL_gl_LIBRARY opengl32)
SET(OPENGL_glu_LIBRARY glu32)
ENDIF (OPENGL_FOUND)
# ADD_DEFINITIONS(-DBT_USE_FREEGLUT)
FIND_PACKAGE(GLU)
FIND_PACKAGE(GLUT)
IF (GLUT_FOUND)
MESSAGE("GLUT FOUND")
MESSAGE(${GLUT_glut_LIBRARY})
ELSE (GLUT_FOUND)
IF (MINGW)
MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32")
SET(GLUT_glut_LIBRARY glut32)
ENDIF (MINGW)
IF (MSVC)
MESSAGE ("GLUT NOT FOUND, trying to use Bullet/Glut/glut32.lib for MSVC")
SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib)
ENDIF (MSVC)
ENDIF (GLUT_FOUND)
IF (WIN32)
INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut)
ELSE (WIN32)
# This is the lines for linux. This should always work if everything is installed and working fine.
INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR})
ENDIF (WIN32)
OPTION(BUILD_DEMOS "Set when you want to build the demos" ON)
IF(BUILD_DEMOS)
SUBDIRS(Demos)
ENDIF(BUILD_DEMOS)
OPTION(BUILD_EXTRAS "Set when you want to build the extras" ON)
IF(BUILD_EXTRAS)
SUBDIRS(Extras)
ENDIF(BUILD_EXTRAS)
SUBDIRS(src)
cmake_minimum_required(VERSION 2.4)
PROJECT(BULLET_PHYSICS)
SET(BULLET_VERSION 2.74)
IF (NOT CMAKE_BUILD_TYPE)
# SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_BUILD_TYPE "Release")
ENDIF (NOT CMAKE_BUILD_TYPE)
IF(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
ENDIF(COMMAND cmake_policy)
# This is the shortcut to finding GLU, GLUT and OpenGL if they are properly installed on your system
# This should be the case.
FIND_PACKAGE(OpenGL)
IF (OPENGL_FOUND)
MESSAGE("OPENGL FOUND")
MESSAGE(${OPENGL_LIBRARIES})
ELSE (OPENGL_FOUND)
MESSAGE("OPENGL NOT FOUND")
SET(OPENGL_gl_LIBRARY opengl32)
SET(OPENGL_glu_LIBRARY glu32)
ENDIF (OPENGL_FOUND)
# ADD_DEFINITIONS(-DBT_USE_FREEGLUT)
FIND_PACKAGE(GLU)
FIND_PACKAGE(GLUT)
IF (GLUT_FOUND)
MESSAGE("GLUT FOUND")
MESSAGE(${GLUT_glut_LIBRARY})
ELSE (GLUT_FOUND)
IF (MINGW)
MESSAGE ("GLUT NOT FOUND not found, trying to use MINGW glut32")
SET(GLUT_glut_LIBRARY glut32)
ENDIF (MINGW)
IF (MSVC)
MESSAGE ("GLUT NOT FOUND, trying to use Bullet/Glut/glut32.lib for MSVC")
SET(GLUT_glut_LIBRARY ${BULLET_PHYSICS_SOURCE_DIR}/Glut/glut32.lib)
ENDIF (MSVC)
ENDIF (GLUT_FOUND)
IF (WIN32)
INCLUDE_DIRECTORIES(${BULLET_PHYSICS_SOURCE_DIR}/Glut)
ELSE (WIN32)
# This is the lines for linux. This should always work if everything is installed and working fine.
INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${GLUT_INCLUDE_DIR})
ENDIF (WIN32)
OPTION(BUILD_DEMOS "Set when you want to build the demos" ON)
IF(BUILD_DEMOS)
SUBDIRS(Demos)
ENDIF(BUILD_DEMOS)
OPTION(BUILD_EXTRAS "Set when you want to build the extras" ON)
IF(BUILD_EXTRAS)
SUBDIRS(Extras)
ENDIF(BUILD_EXTRAS)
SUBDIRS(src)

View File

@@ -103,13 +103,13 @@ public:
btDemoEntry g_demoEntries[] =
{
{"ConstraintDemo",ConstraintDemo::Create},
{"ForkLift Demo",ForkLiftDemo::Create},
{"Ragdoll Demo",RagdollDemo::Create},
{"Basic Demo", BasicDemo::Create},
{"Convex Decomposition",ConvexDecompositionDemo::Create},
{"Concave Moving", GimpactConcaveDemo::Create},
{"Dynamic Control Demo",MotorDemo::Create},
// {"Dynamic Control Demo",MotorDemo::Create},
//{"ConcaveDemo",ConcaveDemo::Create},
{"Concave Convexcast Demo",ConcaveConvexcastDemo::Create},
// {"SoftBody Cloth",SoftDemo0::Create},

View File

@@ -52,6 +52,7 @@ namespace
int gDrawAabb;
int gWireFrame;
int gHelpText;
int gDebugConstraints;
int gDebugContacts;
int gDrawTextures=1;
int gDrawShadows=0;
@@ -80,6 +81,14 @@ void setDefaultSettings()
gDrawAabb=0;
gWireFrame=0;
gDebugContacts=0;
//enable constraint debug visualization for first demo, only if user hasn't overridden the setting
if (testSelection>1)
{
gDebugConstraints=0;
} else
{
gDebugConstraints=1;
}
gHelpText = 0;
gDrawTextures=1;
gDrawShadows=0;
@@ -118,6 +127,14 @@ void ResetScene()
void NextScene()
{
testSelection++;
if (testSelection>1)
{
gDebugConstraints=0;
} else
{
gDebugConstraints=1;
}
if(testSelection>23)
testSelection=0;
if (glui)
@@ -216,6 +233,13 @@ void SimulationLoop()
{
demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_NoHelpText);
}
if (gDebugConstraints)
{
demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits);
} else
{
demo->setDebugMode(demo->getDebugMode() & (~btIDebugDraw::DBG_DrawConstraints+btIDebugDraw::DBG_DrawConstraintLimits));
}
if (gDebugContacts)
{
demo->setDebugMode(demo->getDebugMode() |btIDebugDraw::DBG_DrawContactPoints);
@@ -281,6 +305,14 @@ void SimulationLoop()
}
if (testSelection != testIndex)
{
if (testSelection>1)
{
gDebugConstraints=0;
} else
{
gDebugConstraints=1;
}
testIndex = testSelection;
if (demo->getDynamicsWorld() && demo->getDynamicsWorld()->getDebugDrawer())
delete demo->getDynamicsWorld()->getDebugDrawer();
@@ -464,6 +496,7 @@ int main(int argc, char** argv)
glui->add_checkbox_to_panel(drawPanel, "AABBs", &gDrawAabb);
glui->add_checkbox_to_panel(drawPanel, "Wireframe", &gWireFrame);
glui->add_checkbox_to_panel(drawPanel, "Contacts", &gDebugContacts);
glui->add_checkbox_to_panel(drawPanel, "Constraints", &gDebugConstraints);
glui->add_checkbox_to_panel(drawPanel, "Textures", &gDrawTextures);
glui->add_checkbox_to_panel(drawPanel, "Shadows", &gDrawShadows);

View File

@@ -76,7 +76,7 @@ int main(int argc,char** argv)
/// Import Collada 1.4 Physics objects
/// also can pass filename in as argument
const char* filename = "boxc4d.dae";
const char* filename = "jenga.dae";
printf("argc=%i\n",argc);
{
for (int i=0;i<argc;i++)

View File

@@ -16,6 +16,8 @@ subject to the following restrictions:
Written by: Marten Svanfeldt
*/
#define CONSTRAINT_DEBUG_SIZE 0.2f
#include "btBulletDynamicsCommon.h"
#include "GlutStuff.h"
@@ -197,6 +199,8 @@ public:
hingeC = new btHingeConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_SPINE], localA, localB);
hingeC->setLimit(btScalar(-M_PI_4), btScalar(M_PI_2));
m_joints[JOINT_PELVIS_SPINE] = hingeC;
hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_PELVIS_SPINE], true);
@@ -206,6 +210,8 @@ public:
coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_HEAD], localA, localB);
coneC->setLimit(M_PI_4, M_PI_4, M_PI_2);
m_joints[JOINT_SPINE_HEAD] = coneC;
coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_SPINE_HEAD], true);
@@ -215,6 +221,8 @@ public:
coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_LEFT_UPPER_LEG], localA, localB);
coneC->setLimit(M_PI_4, M_PI_4, 0);
m_joints[JOINT_LEFT_HIP] = coneC;
coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_HIP], true);
localA.setIdentity(); localB.setIdentity();
@@ -223,6 +231,8 @@ public:
hingeC = new btHingeConstraint(*m_bodies[BODYPART_LEFT_UPPER_LEG], *m_bodies[BODYPART_LEFT_LOWER_LEG], localA, localB);
hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
m_joints[JOINT_LEFT_KNEE] = hingeC;
hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_KNEE], true);
@@ -232,6 +242,8 @@ public:
coneC = new btConeTwistConstraint(*m_bodies[BODYPART_PELVIS], *m_bodies[BODYPART_RIGHT_UPPER_LEG], localA, localB);
coneC->setLimit(M_PI_4, M_PI_4, 0);
m_joints[JOINT_RIGHT_HIP] = coneC;
coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_HIP], true);
localA.setIdentity(); localB.setIdentity();
@@ -240,6 +252,8 @@ public:
hingeC = new btHingeConstraint(*m_bodies[BODYPART_RIGHT_UPPER_LEG], *m_bodies[BODYPART_RIGHT_LOWER_LEG], localA, localB);
hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
m_joints[JOINT_RIGHT_KNEE] = hingeC;
hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_KNEE], true);
@@ -248,6 +262,8 @@ public:
localB.getBasis().setEulerZYX(0,0,M_PI_2); localB.setOrigin(btVector3(btScalar(0.), btScalar(-0.18), btScalar(0.)));
coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_LEFT_UPPER_ARM], localA, localB);
coneC->setLimit(M_PI_2, M_PI_2, 0);
coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_joints[JOINT_LEFT_SHOULDER] = coneC;
m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_SHOULDER], true);
@@ -258,6 +274,8 @@ public:
// hingeC->setLimit(btScalar(-M_PI_2), btScalar(0));
hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
m_joints[JOINT_LEFT_ELBOW] = hingeC;
hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_LEFT_ELBOW], true);
@@ -268,6 +286,8 @@ public:
coneC = new btConeTwistConstraint(*m_bodies[BODYPART_SPINE], *m_bodies[BODYPART_RIGHT_UPPER_ARM], localA, localB);
coneC->setLimit(M_PI_2, M_PI_2, 0);
m_joints[JOINT_RIGHT_SHOULDER] = coneC;
coneC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_SHOULDER], true);
localA.setIdentity(); localB.setIdentity();
@@ -277,6 +297,8 @@ public:
// hingeC->setLimit(btScalar(-M_PI_2), btScalar(0));
hingeC->setLimit(btScalar(0), btScalar(M_PI_2));
m_joints[JOINT_RIGHT_ELBOW] = hingeC;
hingeC->setDbgDrawSize(CONSTRAINT_DEBUG_SIZE);
m_ownerWorld->addConstraint(m_joints[JOINT_RIGHT_ELBOW], true);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +1,126 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#ifndef BT_DBVT_BROADPHASE_H
#define BT_DBVT_BROADPHASE_H
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
//
// Compile time config
//
#define DBVT_BP_PROFILE 0
//#define DBVT_BP_SORTPAIRS 1
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
#define DBVT_BP_MARGIN (btScalar)0.05
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
//
// btDbvtProxy
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
//btDbvtAabbMm aabb;
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0]=links[1]=0;
}
};
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
struct btDbvtBroadphase : btBroadphaseInterface
{
/* Config */
enum {
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
};
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
#if DBVT_BP_PROFILE
btClock m_clock;
struct {
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
#endif
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache();
const btOverlappingPairCache* getOverlappingPairCache() const;
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
void printStats();
static void benchmark(btBroadphaseInterface*);
void performDeferredRemoval(btDispatcher* dispatcher);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#ifndef BT_DBVT_BROADPHASE_H
#define BT_DBVT_BROADPHASE_H
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
//
// Compile time config
//
#define DBVT_BP_PROFILE 0
//#define DBVT_BP_SORTPAIRS 1
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
#define DBVT_BP_MARGIN (btScalar)0.05
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
//
// btDbvtProxy
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
//btDbvtAabbMm aabb;
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0]=links[1]=0;
}
};
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
struct btDbvtBroadphase : btBroadphaseInterface
{
/* Config */
enum {
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
};
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
#if DBVT_BP_PROFILE
btClock m_clock;
struct {
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
#endif
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache();
const btOverlappingPairCache* getOverlappingPairCache() const;
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
void printStats();
static void benchmark(btBroadphaseInterface*);
void performDeferredRemoval(btDispatcher* dispatcher);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif

View File

@@ -1,489 +1,489 @@
/*
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"
#include "btQuantizedBvh.h"
/// btSapBroadphaseArray m_sapBroadphases;
/// btOverlappingPairCache* m_overlappingPairs;
extern int gOverlappingPairs;
/*
class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
{
public:
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
}
};
*/
btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
:m_overlappingPairs(pairCache),
m_optimizedAabbTree(0),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!m_overlappingPairs)
{
m_ownsPairCache = true;
void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
}
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
{
virtual ~btMultiSapOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
{
btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->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)
{
m_overlappingPairs->~btOverlappingPairCache();
btAlignedFree(m_overlappingPairs);
}
}
void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
{
m_optimizedAabbTree = new btQuantizedBvh();
m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
for (int i=0;i<m_sapBroadphases.size();i++)
{
btQuantizedBvhNode node;
btVector3 aabbMin,aabbMax;
m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
int partId = 0;
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
nodes.push_back(node);
}
m_optimizedAabbTree->buildInternal();
}
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
{
//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
m_multiSapProxies.push_back(proxy);
///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::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
{
void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
bridgeProxyRef->m_childProxy = childProxy;
bridgeProxyRef->m_childBroadphase = childBroadphase;
parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
}
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
{
return
amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
}
void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
aabbMin = multiProxy->m_aabbMin;
aabbMax = multiProxy->m_aabbMax;
}
void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i=0;i<m_multiSapProxies.size();i++)
{
rayCallback.process(m_multiSapProxies[i]);
}
}
//#include <stdio.h>
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;
// bool fullyContained = false;
// bool alreadyInSimple = false;
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btMultiSapBroadphase* m_multiSap;
btMultiSapProxy* m_multiProxy;
btDispatcher* m_dispatcher;
MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
:m_multiSap(multiSap),
m_multiProxy(multiProxy),
m_dispatcher(dispatcher)
{
}
virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
{
btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
int containingBroadphaseIndex = -1;
//already found?
for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
{
if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
break;
}
}
if (containingBroadphaseIndex<0)
{
//add it
btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
}
}
};
MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
if (m_optimizedAabbTree)
m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
int i;
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btVector3 worldAabbMin,worldAabbMax;
multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
if (!overlapsBroadphase)
{
//remove it now
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
/*
if (1)
{
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
btVector3 worldAabbMin,worldAabbMax;
childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
// fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
int containingBroadphaseIndex = -1;
//if already contains this
for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
}
alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
}
if (overlapsBroadphase)
{
if (containingBroadphaseIndex<0)
{
btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,childBroadphase);
}
} else
{
if (containingBroadphaseIndex>=0)
{
//remove
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
}
///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
if (0)//!multiProxy->m_bridgeProxies.size())
{
///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
}
if (!multiProxy->m_bridgeProxies.size())
{
///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
*/
//update
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
}
}
bool stopUpdating=false;
class btMultiSapBroadphasePairSortPredicate
{
public:
bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
{
btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
return aProxy0 > bProxy0 ||
(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
}
};
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
// quicksort(overlappingPairArray,0,overlappingPairArray.size());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
// overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
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];
btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
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)
{
getOverlappingPairCache()->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(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}
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);
}
void btMultiSapBroadphase::printStats()
{
/* printf("---------------------------------\n");
printf("btMultiSapBroadphase.h\n");
printf("numHandles = %d\n",m_multiSapProxies.size());
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
childBroadphase->printStats();
}
*/
}
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
{
// not yet
}
/*
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"
#include "btQuantizedBvh.h"
/// btSapBroadphaseArray m_sapBroadphases;
/// btOverlappingPairCache* m_overlappingPairs;
extern int gOverlappingPairs;
/*
class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
{
public:
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
}
};
*/
btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
:m_overlappingPairs(pairCache),
m_optimizedAabbTree(0),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!m_overlappingPairs)
{
m_ownsPairCache = true;
void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
}
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
{
virtual ~btMultiSapOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
{
btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->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)
{
m_overlappingPairs->~btOverlappingPairCache();
btAlignedFree(m_overlappingPairs);
}
}
void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
{
m_optimizedAabbTree = new btQuantizedBvh();
m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
for (int i=0;i<m_sapBroadphases.size();i++)
{
btQuantizedBvhNode node;
btVector3 aabbMin,aabbMax;
m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
int partId = 0;
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
nodes.push_back(node);
}
m_optimizedAabbTree->buildInternal();
}
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
{
//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
m_multiSapProxies.push_back(proxy);
///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::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
{
void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
bridgeProxyRef->m_childProxy = childProxy;
bridgeProxyRef->m_childBroadphase = childBroadphase;
parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
}
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
{
return
amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
}
void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
aabbMin = multiProxy->m_aabbMin;
aabbMax = multiProxy->m_aabbMax;
}
void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i=0;i<m_multiSapProxies.size();i++)
{
rayCallback.process(m_multiSapProxies[i]);
}
}
//#include <stdio.h>
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;
// bool fullyContained = false;
// bool alreadyInSimple = false;
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btMultiSapBroadphase* m_multiSap;
btMultiSapProxy* m_multiProxy;
btDispatcher* m_dispatcher;
MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
:m_multiSap(multiSap),
m_multiProxy(multiProxy),
m_dispatcher(dispatcher)
{
}
virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
{
btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
int containingBroadphaseIndex = -1;
//already found?
for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
{
if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
break;
}
}
if (containingBroadphaseIndex<0)
{
//add it
btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
}
}
};
MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
if (m_optimizedAabbTree)
m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
int i;
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btVector3 worldAabbMin,worldAabbMax;
multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
if (!overlapsBroadphase)
{
//remove it now
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
/*
if (1)
{
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
btVector3 worldAabbMin,worldAabbMax;
childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
// fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
int containingBroadphaseIndex = -1;
//if already contains this
for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
}
alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
}
if (overlapsBroadphase)
{
if (containingBroadphaseIndex<0)
{
btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,childBroadphase);
}
} else
{
if (containingBroadphaseIndex>=0)
{
//remove
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
}
///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
if (0)//!multiProxy->m_bridgeProxies.size())
{
///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
}
if (!multiProxy->m_bridgeProxies.size())
{
///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
*/
//update
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
}
}
bool stopUpdating=false;
class btMultiSapBroadphasePairSortPredicate
{
public:
bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
{
btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
return aProxy0 > bProxy0 ||
(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
}
};
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
// quicksort(overlappingPairArray,0,overlappingPairArray.size());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
// overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
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];
btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
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)
{
getOverlappingPairCache()->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(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}
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);
}
void btMultiSapBroadphase::printStats()
{
/* printf("---------------------------------\n");
printf("btMultiSapBroadphase.h\n");
printf("numHandles = %d\n",m_multiSapProxies.size());
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
childBroadphase->printStats();
}
*/
}
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
{
// not yet
}

View File

@@ -1,151 +1,151 @@
/*
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 btBroadphaseInterface;
class btSimpleBroadphase;
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
///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;
class btQuantizedBvh* m_optimizedAabbTree;
bool m_ownsPairCache;
btOverlapFilterCallback* m_filterCallback;
int m_invalidPair;
struct btBridgeProxy
{
btBroadphaseProxy* m_childProxy;
btBroadphaseInterface* m_childBroadphase;
};
public:
struct btMultiSapProxy : public btBroadphaseProxy
{
///array with all the entries that this proxy belongs to
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
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)
:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax),
m_shapeType(shapeType)
{
m_multiSapParentProxy =this;
}
};
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,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///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;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE
/*
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 btBroadphaseInterface;
class btSimpleBroadphase;
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
///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;
class btQuantizedBvh* m_optimizedAabbTree;
bool m_ownsPairCache;
btOverlapFilterCallback* m_filterCallback;
int m_invalidPair;
struct btBridgeProxy
{
btBroadphaseProxy* m_childProxy;
btBroadphaseInterface* m_childBroadphase;
};
public:
struct btMultiSapProxy : public btBroadphaseProxy
{
///array with all the entries that this proxy belongs to
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
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)
:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax),
m_shapeType(shapeType)
{
m_multiSapParentProxy =this;
}
};
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,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///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;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE

View File

@@ -1,468 +1,468 @@
/*
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_CACHE_H
#define OVERLAPPING_PAIR_CACHE_H
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
{
virtual ~btOverlapCallback()
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
{
virtual ~btOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
extern int gRemovePairs;
extern int gAddedPairs;
extern int gFindPairs;
const int BT_NULL_PAIR=0xffffffff;
///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
class btOverlappingPairCache : public btOverlappingPairCallback
{
public:
virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual bool hasDeferredRemoval() = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
class btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
bool m_blockedForChanges;
public:
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual 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.
virtual 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);
virtual 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 = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
// Thomas Wang's hash
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
{
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
#endif
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];
}
virtual bool hasDeferredRemoval()
{
return false;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
btOverlappingPairCallback* m_ghostPairCallback;
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
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;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class btNullPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
public:
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
{
}
virtual int getNumOverlappingPairs() const
{
return 0;
}
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
{
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual bool hasDeferredRemoval()
{
return true;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
{
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
}
};
#endif //OVERLAPPING_PAIR_CACHE_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.
*/
#ifndef OVERLAPPING_PAIR_CACHE_H
#define OVERLAPPING_PAIR_CACHE_H
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
{
virtual ~btOverlapCallback()
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
{
virtual ~btOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
extern int gRemovePairs;
extern int gAddedPairs;
extern int gFindPairs;
const int BT_NULL_PAIR=0xffffffff;
///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
class btOverlappingPairCache : public btOverlappingPairCallback
{
public:
virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual bool hasDeferredRemoval() = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
class btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
bool m_blockedForChanges;
public:
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual 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.
virtual 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);
virtual 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 = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
// Thomas Wang's hash
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
{
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
#endif
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];
}
virtual bool hasDeferredRemoval()
{
return false;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
btOverlappingPairCallback* m_ghostPairCallback;
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
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;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class btNullPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
public:
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
{
}
virtual int getNumOverlappingPairs() const
{
return 0;
}
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
{
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual bool hasDeferredRemoval()
{
return true;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
{
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
}
};
#endif //OVERLAPPING_PAIR_CACHE_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,473 +1,473 @@
/*
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 QUANTIZED_BVH_H
#define QUANTIZED_BVH_H
//#define DEBUG_CHECK_DEQUANTIZATION 1
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
//Note: currently we have 16 bytes per quantized node
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
#define MAX_NUM_PARTS_IN_BITS 10
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrTriangleIndex >= 0);
}
int getEscapeIndex() const
{
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
int getTriangleIndex() const
{
btAssert(isLeafNode());
// Get only the lower bits where the triangle index is stored
return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
}
int getPartId() const
{
btAssert(isLeafNode());
// Get only the highest bits where the part index is stored
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
}
;
/// btOptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
//4
int m_escapeIndex;
//8
//for child nodes
int m_subPart;
int m_triangleIndex;
int m_padding[5];//bad, due to alignment
};
///btBvhSubtreeInfo provides info to gather a subtree of limited size
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
int m_rootNodeIndex;
//4 bytes
int m_subtreeSize;
int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
}
;
class btNodeOverlapCallback
{
public:
virtual ~btNodeOverlapCallback() {};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
///for code readability:
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{
public:
enum btTraversalMode
{
TRAVERSAL_STACKLESS = 0,
TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
TRAVERSAL_RECURSIVE
};
protected:
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
//quantization data
bool m_useQuantization;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
int m_subtreeHeaderCount;
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
}
btVector3 getAabbMin(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
}
btVector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
}
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
}
else
{
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
}
}
void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
quantize(quantizedAabbMin,newAabbMin,0);
quantize(quantizedAabbMax,newAabbMax,1);
for (int i=0;i<3;i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
}
} else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
void swapLeafNodes(int firstIndex,int secondIndex);
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
protected:
void buildTree (int startIndex,int endIndex);
int calcSplittingAxis(int startIndex,int endIndex);
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
///tree traversal designed for small-memory processors like PS3 SPU
void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btQuantizedBvh();
virtual ~btQuantizedBvh();
///***************************************** expert/internal use only *************************
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
void buildInternal();
///***************************************** expert/internal use only *************************
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
{
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
btAssert(point.getY() <= m_bvhAabbMax.getY());
btAssert(point.getZ() <= m_bvhAabbMax.getZ());
btAssert(point.getX() >= m_bvhAabbMin.getX());
btAssert(point.getY() >= m_bvhAabbMin.getY());
btAssert(point.getZ() >= m_bvhAabbMin.getZ());
btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
///@todo: double-check this
if (isMax)
{
out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
} else
{
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
}
#ifdef DEBUG_CHECK_DEQUANTIZATION
btVector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() < point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() < point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
} else
{
if (newPoint.getX() > point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() > point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() > point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
#endif //DEBUG_CHECK_DEQUANTIZATION
}
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
{
btAssert(m_useQuantization);
btVector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
quantize(out,clampedPoint,isMax);
}
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
vecOut += m_bvhAabbMin;
return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
void setTraversalMode(btTraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
}
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize();
/// Data buffer MUST be 16 byte aligned
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
SIMD_FORCE_INLINE bool isQuantized()
{
return m_useQuantization;
}
private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
}
;
#endif //QUANTIZED_BVH_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.
*/
#ifndef QUANTIZED_BVH_H
#define QUANTIZED_BVH_H
//#define DEBUG_CHECK_DEQUANTIZATION 1
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
//Note: currently we have 16 bytes per quantized node
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
#define MAX_NUM_PARTS_IN_BITS 10
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrTriangleIndex >= 0);
}
int getEscapeIndex() const
{
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
int getTriangleIndex() const
{
btAssert(isLeafNode());
// Get only the lower bits where the triangle index is stored
return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
}
int getPartId() const
{
btAssert(isLeafNode());
// Get only the highest bits where the part index is stored
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
}
;
/// btOptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
//4
int m_escapeIndex;
//8
//for child nodes
int m_subPart;
int m_triangleIndex;
int m_padding[5];//bad, due to alignment
};
///btBvhSubtreeInfo provides info to gather a subtree of limited size
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
int m_rootNodeIndex;
//4 bytes
int m_subtreeSize;
int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
}
;
class btNodeOverlapCallback
{
public:
virtual ~btNodeOverlapCallback() {};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
///for code readability:
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{
public:
enum btTraversalMode
{
TRAVERSAL_STACKLESS = 0,
TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
TRAVERSAL_RECURSIVE
};
protected:
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
//quantization data
bool m_useQuantization;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
int m_subtreeHeaderCount;
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
}
btVector3 getAabbMin(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
}
btVector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
}
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
}
else
{
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
}
}
void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
quantize(quantizedAabbMin,newAabbMin,0);
quantize(quantizedAabbMax,newAabbMax,1);
for (int i=0;i<3;i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
}
} else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
void swapLeafNodes(int firstIndex,int secondIndex);
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
protected:
void buildTree (int startIndex,int endIndex);
int calcSplittingAxis(int startIndex,int endIndex);
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
///tree traversal designed for small-memory processors like PS3 SPU
void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btQuantizedBvh();
virtual ~btQuantizedBvh();
///***************************************** expert/internal use only *************************
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
void buildInternal();
///***************************************** expert/internal use only *************************
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
{
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
btAssert(point.getY() <= m_bvhAabbMax.getY());
btAssert(point.getZ() <= m_bvhAabbMax.getZ());
btAssert(point.getX() >= m_bvhAabbMin.getX());
btAssert(point.getY() >= m_bvhAabbMin.getY());
btAssert(point.getZ() >= m_bvhAabbMin.getZ());
btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
///@todo: double-check this
if (isMax)
{
out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
} else
{
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
}
#ifdef DEBUG_CHECK_DEQUANTIZATION
btVector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() < point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() < point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
} else
{
if (newPoint.getX() > point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() > point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() > point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
#endif //DEBUG_CHECK_DEQUANTIZATION
}
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
{
btAssert(m_useQuantization);
btVector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
quantize(out,clampedPoint,isMax);
}
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
btVector3 vecOut;
vecOut.setValue(
(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
vecOut += m_bvhAabbMin;
return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
void setTraversalMode(btTraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
}
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize();
/// Data buffer MUST be 16 byte aligned
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
SIMD_FORCE_INLINE bool isQuantized()
{
return m_useQuantization;
}
private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
}
;
#endif //QUANTIZED_BVH_H

View File

@@ -1,209 +1,209 @@
/*
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 "LinearMath/btScalar.h"
#include "SphereTriangleDetector.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
:m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
{
}
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
btVector3 point,normal;
btScalar timeOfImpact = btScalar(1.);
btScalar depth = btScalar(0.);
// output.m_distance = btScalar(1e30);
//move sphere into triangle space
btTransform sphereInTr = transformB.inverseTimes(transformA);
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
{
if (swapResults)
{
btVector3 normalOnB = transformB.getBasis()*normal;
btVector3 normalOnA = -normalOnB;
btVector3 pointOnA = transformB*point+normalOnB*depth;
output.addContactPoint(normalOnA,pointOnA,depth);
} else
{
output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
}
}
}
#define MAX_OVERLAP btScalar(0.)
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
btScalar t = v.dot(diff);
if (t > 0) {
btScalar dotVV = v.dot(v);
if (t < dotVV) {
t /= dotVV;
diff -= t*v;
} else {
t = 1;
diff -= v;
}
} else
t = 0;
nearest = from + t*v;
return diff.dot(diff);
}
bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
btVector3 lp(p);
btVector3 lnormal(normal);
return pointInTriangle(vertices, lnormal, &lp);
}
///combined discrete/continuous sphere-triangle
bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
{
const btVector3* vertices = &m_triangle->getVertexPtr(0);
const btVector3& c = sphereCenter;
btScalar r = m_sphere->getRadius();
btVector3 delta (0,0,0);
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
btVector3 p1ToCentre = c - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
btScalar contactMargin = contactBreakingThreshold;
bool isInsideContactPlane = distanceFromPlane < r + contactMargin;
bool isInsideShellPlane = distanceFromPlane < r;
btScalar deltaDotNormal = delta.dot(normal);
if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0))
return false;
// Check for contact / intersection
bool hasContact = false;
btVector3 contactPoint;
if (isInsideContactPlane) {
if (facecontains(c,vertices,normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = c - normal*distanceFromPlane;
} else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin);
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i,pa,pb);
btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
}
}
}
}
if (hasContact) {
btVector3 contactToCentre = c - contactPoint;
btScalar distanceSqr = contactToCentre.length2();
if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) {
btScalar distance = btSqrt(distanceSqr);
resultNormal = contactToCentre;
resultNormal.normalize();
point = contactPoint;
depth = -(r-distance);
return true;
}
if (delta.dot(contactToCentre) >= btScalar(0.0))
return false;
// Moving towards the contact point -> collision
point = contactPoint;
timeOfImpact = btScalar(0.0);
return true;
}
return false;
}
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
{
const btVector3* p1 = &vertices[0];
const btVector3* p2 = &vertices[1];
const btVector3* p3 = &vertices[2];
btVector3 edge1( *p2 - *p1 );
btVector3 edge2( *p3 - *p2 );
btVector3 edge3( *p1 - *p3 );
btVector3 p1_to_p( *p - *p1 );
btVector3 p2_to_p( *p - *p2 );
btVector3 p3_to_p( *p - *p3 );
btVector3 edge1_normal( edge1.cross(normal));
btVector3 edge2_normal( edge2.cross(normal));
btVector3 edge3_normal( edge3.cross(normal));
btScalar r1, r2, r3;
r1 = edge1_normal.dot( p1_to_p );
r2 = edge2_normal.dot( p2_to_p );
r3 = edge3_normal.dot( p3_to_p );
if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
return true;
return false;
}
/*
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 "LinearMath/btScalar.h"
#include "SphereTriangleDetector.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
:m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
{
}
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
btVector3 point,normal;
btScalar timeOfImpact = btScalar(1.);
btScalar depth = btScalar(0.);
// output.m_distance = btScalar(1e30);
//move sphere into triangle space
btTransform sphereInTr = transformB.inverseTimes(transformA);
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
{
if (swapResults)
{
btVector3 normalOnB = transformB.getBasis()*normal;
btVector3 normalOnA = -normalOnB;
btVector3 pointOnA = transformB*point+normalOnB*depth;
output.addContactPoint(normalOnA,pointOnA,depth);
} else
{
output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
}
}
}
#define MAX_OVERLAP btScalar(0.)
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
btScalar t = v.dot(diff);
if (t > 0) {
btScalar dotVV = v.dot(v);
if (t < dotVV) {
t /= dotVV;
diff -= t*v;
} else {
t = 1;
diff -= v;
}
} else
t = 0;
nearest = from + t*v;
return diff.dot(diff);
}
bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
btVector3 lp(p);
btVector3 lnormal(normal);
return pointInTriangle(vertices, lnormal, &lp);
}
///combined discrete/continuous sphere-triangle
bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
{
const btVector3* vertices = &m_triangle->getVertexPtr(0);
const btVector3& c = sphereCenter;
btScalar r = m_sphere->getRadius();
btVector3 delta (0,0,0);
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
btVector3 p1ToCentre = c - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
btScalar contactMargin = contactBreakingThreshold;
bool isInsideContactPlane = distanceFromPlane < r + contactMargin;
bool isInsideShellPlane = distanceFromPlane < r;
btScalar deltaDotNormal = delta.dot(normal);
if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0))
return false;
// Check for contact / intersection
bool hasContact = false;
btVector3 contactPoint;
if (isInsideContactPlane) {
if (facecontains(c,vertices,normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = c - normal*distanceFromPlane;
} else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin);
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i,pa,pb);
btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
}
}
}
}
if (hasContact) {
btVector3 contactToCentre = c - contactPoint;
btScalar distanceSqr = contactToCentre.length2();
if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) {
btScalar distance = btSqrt(distanceSqr);
resultNormal = contactToCentre;
resultNormal.normalize();
point = contactPoint;
depth = -(r-distance);
return true;
}
if (delta.dot(contactToCentre) >= btScalar(0.0))
return false;
// Moving towards the contact point -> collision
point = contactPoint;
timeOfImpact = btScalar(0.0);
return true;
}
return false;
}
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
{
const btVector3* p1 = &vertices[0];
const btVector3* p2 = &vertices[1];
const btVector3* p3 = &vertices[2];
btVector3 edge1( *p2 - *p1 );
btVector3 edge2( *p3 - *p2 );
btVector3 edge3( *p1 - *p3 );
btVector3 p1_to_p( *p - *p1 );
btVector3 p2_to_p( *p - *p2 );
btVector3 p3_to_p( *p - *p3 );
btVector3 edge1_normal( edge1.cross(normal));
btVector3 edge2_normal( edge2.cross(normal));
btVector3 edge3_normal( edge3.cross(normal));
btScalar r1, r2, r3;
r1 = edge1_normal.dot( p1_to_p );
r2 = edge2_normal.dot( p2_to_p );
r3 = edge3_normal.dot( p3_to_p );
if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
return true;
return false;
}

View File

@@ -1,47 +1,47 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btActivatingCollisionAlgorithm.h"
#include "btCollisionDispatcher.h"
#include "btCollisionObject.h"
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
}
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
}
btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
{
// m_colObj0->activate();
// m_colObj1->activate();
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btActivatingCollisionAlgorithm.h"
#include "btCollisionDispatcher.h"
#include "btCollisionObject.h"
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
}
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
}
btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
{
// m_colObj0->activate();
// m_colObj1->activate();
}

View File

@@ -1,36 +1,36 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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_ACTIVATING_COLLISION_ALGORITHM_H
#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
{
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
public:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1);
virtual ~btActivatingCollisionAlgorithm();
};
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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_ACTIVATING_COLLISION_ALGORITHM_H
#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
{
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
public:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1);
virtual ~btActivatingCollisionAlgorithm();
};
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H

View File

@@ -1,85 +1,85 @@
/*
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 "btBoxBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "btBoxBoxDetector.h"
#define USE_PERSISTENT_CONTACTS 1
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
: btActivatingCollisionAlgorithm(ci,obj0,obj1),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
m_ownManifold = true;
}
}
btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
btCollisionObject* col0 = body0;
btCollisionObject* col1 = body1;
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = 1e30f;
input.m_transformA = body0->getWorldTransform();
input.m_transformB = body1->getWorldTransform();
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
}
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}
/*
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 "btBoxBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "btBoxBoxDetector.h"
#define USE_PERSISTENT_CONTACTS 1
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
: btActivatingCollisionAlgorithm(ci,obj0,obj1),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
m_ownManifold = true;
}
}
btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
btCollisionObject* col0 = body0;
btCollisionObject* col1 = body1;
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = 1e30f;
input.m_transformA = body0->getWorldTransform();
input.m_transformB = body1->getWorldTransform();
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
}
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}

View File

@@ -1,66 +1,66 @@
/*
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 BOX_BOX__COLLISION_ALGORITHM_H
#define BOX_BOX__COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
virtual ~btBoxBoxCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //BOX_BOX__COLLISION_ALGORITHM_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.
*/
#ifndef BOX_BOX__COLLISION_ALGORITHM_H
#define BOX_BOX__COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
virtual ~btBoxBoxCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //BOX_BOX__COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,44 @@
/*
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
* All rights reserved. Email: russ@q12.org Web: www.q12.org
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 BOX_BOX_DETECTOR_H
#define BOX_BOX_DETECTOR_H
class btBoxShape;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
/// btBoxBoxDetector wraps the ODE box-box collision detector
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
{
btBoxShape* m_box1;
btBoxShape* m_box2;
public:
btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
};
#endif //BT_BOX_BOX_DETECTOR_H
/*
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
* All rights reserved. Email: russ@q12.org Web: www.q12.org
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 BOX_BOX_DETECTOR_H
#define BOX_BOX_DETECTOR_H
class btBoxShape;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
/// btBoxBoxDetector wraps the ODE box-box collision detector
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
{
btBoxShape* m_box1;
btBoxShape* m_box2;
public:
btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
};
#endif //BT_BOX_BOX_DETECTOR_H

View File

@@ -1,155 +1,155 @@
/*
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 "btConvexPlaneCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
//#include <stdio.h>
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
btCollisionObject* convexObj = m_isSwapped? col1 : col0;
btCollisionObject* planeObj = m_isSwapped? col0 : col1;
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
m_ownManifold = true;
}
}
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
btCollisionObject* planeObj = m_isSwapped? body0: body1;
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform convexWorldTransform = convexObj->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
btTransform planeInConvex;
planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
}
void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
btCollisionObject* planeObj = m_isSwapped? body0: body1;
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
//first perform a collision query with the non-perturbated collision objects
{
btQuaternion rotq(0,0,0,1);
collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut);
}
if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
{
btVector3 v0,v1;
btPlaneSpace1(planeNormal,v0,v1);
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
const btScalar angleLimit = 0.125f * SIMD_PI;
btScalar perturbeAngle;
btScalar radius = convexShape->getAngularMotionDisc();
perturbeAngle = gContactBreakingThreshold / radius;
if ( perturbeAngle > angleLimit )
perturbeAngle = angleLimit;
btQuaternion perturbeRot(v0,perturbeAngle);
for (int i=0;i<m_numPerturbationIterations;i++)
{
btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal,iterationAngle);
collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut);
}
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}
/*
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 "btConvexPlaneCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
//#include <stdio.h>
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
btCollisionObject* convexObj = m_isSwapped? col1 : col0;
btCollisionObject* planeObj = m_isSwapped? col0 : col1;
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
m_ownManifold = true;
}
}
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
btCollisionObject* planeObj = m_isSwapped? body0: body1;
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform convexWorldTransform = convexObj->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
btTransform planeInConvex;
planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
}
void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
btCollisionObject* planeObj = m_isSwapped? body0: body1;
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
//first perform a collision query with the non-perturbated collision objects
{
btQuaternion rotq(0,0,0,1);
collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut);
}
if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
{
btVector3 v0,v1;
btPlaneSpace1(planeNormal,v0,v1);
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
const btScalar angleLimit = 0.125f * SIMD_PI;
btScalar perturbeAngle;
btScalar radius = convexShape->getAngularMotionDisc();
perturbeAngle = gContactBreakingThreshold / radius;
if ( perturbeAngle > angleLimit )
perturbeAngle = angleLimit;
btQuaternion perturbeRot(v0,perturbeAngle);
for (int i=0;i<m_numPerturbationIterations;i++)
{
btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal,iterationAngle);
collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut);
}
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}

View File

@@ -1,84 +1,84 @@
/*
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 CONVEX_PLANE_COLLISION_ALGORITHM_H
#define CONVEX_PLANE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
public:
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc()
: m_numPerturbationIterations(3),
m_minimumPointsPerturbationThreshold(3)
{
}
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
} else
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
}
};
};
#endif //CONVEX_PLANE_COLLISION_ALGORITHM_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.
*/
#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H
#define CONVEX_PLANE_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
public:
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc()
: m_numPerturbationIterations(3),
m_minimumPointsPerturbationThreshold(3)
{
}
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
} else
{
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
}
};
};
#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H

View File

@@ -1,170 +1,170 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btGhostObject.h"
#include "btCollisionWorld.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "LinearMath/btAabbUtil2.h"
btGhostObject::btGhostObject()
{
m_internalType = CO_GHOST_OBJECT;
}
btGhostObject::~btGhostObject()
{
///btGhostObject should have been removed from the world, so no overlapping objects
btAssert(!m_overlappingObjects.size());
}
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index==m_overlappingObjects.size())
{
//not found
m_overlappingObjects.push_back(otherObject);
}
}
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
}
}
btPairCachingGhostObject::btPairCachingGhostObject()
{
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
}
btPairCachingGhostObject::~btPairCachingGhostObject()
{
btAlignedFree( m_hashPairCache );
}
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btAssert(actualThisProxy);
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index==m_overlappingObjects.size())
{
m_overlappingObjects.push_back(otherObject);
m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
}
}
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
btAssert(actualThisProxy);
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
}
}
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
btTransform convexFromTrans,convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransform R;
R.setIdentity ();
R.setRotation (convexFromTrans.getRotation());
castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
}
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
}
}
}
}
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
{
btTransform rayFromTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
btTransform rayToTrans;
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
int i;
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
}
}
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btGhostObject.h"
#include "btCollisionWorld.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "LinearMath/btAabbUtil2.h"
btGhostObject::btGhostObject()
{
m_internalType = CO_GHOST_OBJECT;
}
btGhostObject::~btGhostObject()
{
///btGhostObject should have been removed from the world, so no overlapping objects
btAssert(!m_overlappingObjects.size());
}
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index==m_overlappingObjects.size())
{
//not found
m_overlappingObjects.push_back(otherObject);
}
}
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
}
}
btPairCachingGhostObject::btPairCachingGhostObject()
{
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
}
btPairCachingGhostObject::~btPairCachingGhostObject()
{
btAlignedFree( m_hashPairCache );
}
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btAssert(actualThisProxy);
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index==m_overlappingObjects.size())
{
m_overlappingObjects.push_back(otherObject);
m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
}
}
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
btAssert(actualThisProxy);
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
}
}
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
btTransform convexFromTrans,convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransform R;
R.setIdentity ();
R.setRotation (convexFromTrans.getRotation());
castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
}
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
}
}
}
}
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
{
btTransform rayFromTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
btTransform rayToTrans;
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
int i;
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
}
}
}

View File

@@ -1,174 +1,174 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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_GHOST_OBJECT_H
#define BT_GHOST_OBJECT_H
#include "btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "LinearMath/btAlignedAllocator.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "btCollisionWorld.h"
class btConvexShape;
class btDispatcher;
///The btGhostObject can keep track of all objects that are overlapping
///By default, this overlap is based on the AABB
///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
///We plan on adding rayTest and other queries for the btGhostObject
ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
{
protected:
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
public:
btGhostObject();
virtual ~btGhostObject();
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
///this method is mainly for expert/internal use only.
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
int getNumOverlappingObjects() const
{
return m_overlappingObjects.size();
}
btCollisionObject* getOverlappingObject(int index)
{
return m_overlappingObjects[index];
}
const btCollisionObject* getOverlappingObject(int index) const
{
return m_overlappingObjects[index];
}
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
{
return m_overlappingObjects;
}
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
{
return m_overlappingObjects;
}
//
// internal cast
//
static const btGhostObject* upcast(const btCollisionObject* colObj)
{
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (const btGhostObject*)colObj;
return 0;
}
static btGhostObject* upcast(btCollisionObject* colObj)
{
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (btGhostObject*)colObj;
return 0;
}
};
class btPairCachingGhostObject : public btGhostObject
{
btHashedOverlappingPairCache* m_hashPairCache;
public:
btPairCachingGhostObject();
virtual ~btPairCachingGhostObject();
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
btHashedOverlappingPairCache* getOverlappingPairCache()
{
return m_hashPairCache;
}
};
///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
class btGhostPairCallback : public btOverlappingPairCallback
{
public:
btGhostPairCallback()
{
}
virtual ~btGhostPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->addOverlappingObjectInternal(proxy1, proxy0);
if (ghost1)
ghost1->addOverlappingObjectInternal(proxy0, proxy1);
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
if (ghost1)
ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher)
{
btAssert(0);
//need to keep track of all ghost objects and call them here
//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
};
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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_GHOST_OBJECT_H
#define BT_GHOST_OBJECT_H
#include "btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "LinearMath/btAlignedAllocator.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "btCollisionWorld.h"
class btConvexShape;
class btDispatcher;
///The btGhostObject can keep track of all objects that are overlapping
///By default, this overlap is based on the AABB
///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
///We plan on adding rayTest and other queries for the btGhostObject
ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
{
protected:
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
public:
btGhostObject();
virtual ~btGhostObject();
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
///this method is mainly for expert/internal use only.
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
int getNumOverlappingObjects() const
{
return m_overlappingObjects.size();
}
btCollisionObject* getOverlappingObject(int index)
{
return m_overlappingObjects[index];
}
const btCollisionObject* getOverlappingObject(int index) const
{
return m_overlappingObjects[index];
}
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
{
return m_overlappingObjects;
}
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
{
return m_overlappingObjects;
}
//
// internal cast
//
static const btGhostObject* upcast(const btCollisionObject* colObj)
{
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (const btGhostObject*)colObj;
return 0;
}
static btGhostObject* upcast(btCollisionObject* colObj)
{
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (btGhostObject*)colObj;
return 0;
}
};
class btPairCachingGhostObject : public btGhostObject
{
btHashedOverlappingPairCache* m_hashPairCache;
public:
btPairCachingGhostObject();
virtual ~btPairCachingGhostObject();
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
btHashedOverlappingPairCache* getOverlappingPairCache()
{
return m_hashPairCache;
}
};
///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
class btGhostPairCallback : public btOverlappingPairCallback
{
public:
btGhostPairCallback()
{
}
virtual ~btGhostPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->addOverlappingObjectInternal(proxy1, proxy0);
if (ghost1)
ghost1->addOverlappingObjectInternal(proxy0, proxy1);
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
if (ghost1)
ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher)
{
btAssert(0);
//need to keep track of all ghost objects and call them here
//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
};
#endif

View File

@@ -1,390 +1,390 @@
/*
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 "LinearMath/btScalar.h"
#include "btSimulationIslandManager.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager():
m_splitIslands(true)
{
}
btSimulationIslandManager::~btSimulationIslandManager()
{
}
void btSimulationIslandManager::initUnionFind(int n)
{
m_unionFind.reset(n);
}
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{
{
for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
{
btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
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())))
{
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
}
}
}
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
{
int index = 0;
int i;
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
{
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
collisionObject->setIslandTag(index);
collisionObject->setCompanionId(-1);
collisionObject->setHitFraction(btScalar(1.));
index++;
}
}
// do the union find
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1);
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
}
index++;
}
}
}
inline int getIslandId(const btPersistentManifold* lhs)
{
int islandId;
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
return islandId;
}
/// function object that routes calls to operator<
class btPersistentManifoldSortPredicate
{
public:
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
{
return getIslandId(lhs) < getIslandId(rhs);
}
};
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
{
BT_PROFILE("islandUnionFindAndQuickSort");
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
m_islandmanifold.resize(0);
//we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
int endIslandIndex=1;
int startIslandIndex;
//update the sleeping state for bodies, if all are sleeping
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
}
//int numSleeping = 0;
bool allSleeping = true;
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
}
}
}
if (allSleeping)
{
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
colObj0->setActivationState( ISLAND_SLEEPING );
}
}
} else
{
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
{
colObj0->setActivationState( WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
}
}
}
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
{
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
colObj1->activate();
}
if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
{
colObj0->activate();
}
if(m_splitIslands)
{
//filtering for response
if (dispatcher->needsResponse(colObj0,colObj1))
m_islandmanifold.push_back(manifold);
}
}
}
}
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
{
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
buildIslands(dispatcher,collisionWorld);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
if(!m_splitIslands)
{
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
int maxNumManifolds = dispatcher->getNumManifolds();
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))
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
int startManifoldIndex = 0;
int endManifoldIndex = 1;
//int islandId;
// 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 islandId = getUnionFind().getElement(startIslandIndex).m_id;
bool islandSleeping = false;
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (!colObj0->isActive())
islandSleeping = true;
}
//find the accompanying contact manifold for this islandId
int numIslandManifolds = 0;
btPersistentManifold** startManifold = 0;
if (startManifoldIndex<numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
/// Process the actual simulation, only if not sleeping/deactivated
numIslandManifolds = endManifoldIndex-startManifoldIndex;
}
}
if (!islandSleeping)
{
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;
}
m_islandBodies.resize(0);
}
} // else if(!splitIslands)
}
/*
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 "LinearMath/btScalar.h"
#include "btSimulationIslandManager.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager():
m_splitIslands(true)
{
}
btSimulationIslandManager::~btSimulationIslandManager()
{
}
void btSimulationIslandManager::initUnionFind(int n)
{
m_unionFind.reset(n);
}
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{
{
for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
{
btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
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())))
{
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
}
}
}
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
{
int index = 0;
int i;
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
{
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
collisionObject->setIslandTag(index);
collisionObject->setCompanionId(-1);
collisionObject->setHitFraction(btScalar(1.));
index++;
}
}
// do the union find
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (!collisionObject->isStaticOrKinematicObject())
{
collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1);
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
}
index++;
}
}
}
inline int getIslandId(const btPersistentManifold* lhs)
{
int islandId;
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
return islandId;
}
/// function object that routes calls to operator<
class btPersistentManifoldSortPredicate
{
public:
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
{
return getIslandId(lhs) < getIslandId(rhs);
}
};
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
{
BT_PROFILE("islandUnionFindAndQuickSort");
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
m_islandmanifold.resize(0);
//we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
int endIslandIndex=1;
int startIslandIndex;
//update the sleeping state for bodies, if all are sleeping
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
}
//int numSleeping = 0;
bool allSleeping = true;
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
}
}
}
if (allSleeping)
{
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
colObj0->setActivationState( ISLAND_SLEEPING );
}
}
} else
{
int idx;
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
{
colObj0->setActivationState( WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
}
}
}
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
{
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
colObj1->activate();
}
if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
{
colObj0->activate();
}
if(m_splitIslands)
{
//filtering for response
if (dispatcher->needsResponse(colObj0,colObj1))
m_islandmanifold.push_back(manifold);
}
}
}
}
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
{
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
buildIslands(dispatcher,collisionWorld);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
if(!m_splitIslands)
{
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
int maxNumManifolds = dispatcher->getNumManifolds();
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))
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
int startManifoldIndex = 0;
int endManifoldIndex = 1;
//int islandId;
// 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 islandId = getUnionFind().getElement(startIslandIndex).m_id;
bool islandSleeping = false;
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (!colObj0->isActive())
islandSleeping = true;
}
//find the accompanying contact manifold for this islandId
int numIslandManifolds = 0;
btPersistentManifold** startManifold = 0;
if (startManifoldIndex<numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
/// Process the actual simulation, only if not sleeping/deactivated
numIslandManifolds = endManifoldIndex-startManifoldIndex;
}
}
if (!islandSleeping)
{
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;
}
m_islandBodies.resize(0);
}
} // else if(!splitIslands)
}

View File

@@ -1,260 +1,260 @@
/*
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 "btSphereBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
//#include <stdio.h>
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
btCollisionObject* boxObj = m_isSwapped? col0 : col1;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
m_ownManifold = true;
}
}
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
btCollisionObject* boxObj = m_isSwapped? body0 : body1;
btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
btVector3 normalOnSurfaceB;
btVector3 pOnBox,pOnSphere;
btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
btScalar radius = sphere0->getRadius();
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->addContactPoint(normalOnSurfaceB,pOnBox,dist);
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}
btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius )
{
btScalar margins;
btVector3 bounds[2];
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
bounds[1] = boxShape->getHalfExtentsWithoutMargin();
margins = boxShape->getMargin();//also add sphereShape margin?
const btTransform& m44T = boxObj->getWorldTransform();
btVector3 boundsVec[2];
btScalar fPenetration;
boundsVec[0] = bounds[0];
boundsVec[1] = bounds[1];
btVector3 marginsVec( margins, margins, margins );
// add margins
bounds[0] += marginsVec;
bounds[1] -= marginsVec;
/////////////////////////////////////////////////
btVector3 tmp, prel, n[6], normal, v3P;
btScalar fSep = btScalar(10000000.0), fSepThis;
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) );
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
// convert point in local space
prel = m44T.invXform( sphereCenter);
bool bFound = false;
v3P = prel;
for (int i=0;i<6;i++)
{
int j = i<3? 0:1;
if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
{
v3P = v3P - n[i]*fSepThis;
bFound = true;
}
}
//
if ( bFound )
{
bounds[0] = boundsVec[0];
bounds[1] = boundsVec[1];
normal = (prel - v3P).normalize();
pointOnBox = v3P + normal*margins;
v3PointOnSphere = prel - normal*fRadius;
if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
{
return btScalar(1.0);
}
// transform back in world space
tmp = m44T( pointOnBox);
pointOnBox = tmp;
tmp = m44T( v3PointOnSphere);
v3PointOnSphere = tmp;
btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
//if this fails, fallback into deeper penetration case, below
if (fSeps2 > SIMD_EPSILON)
{
fSep = - btSqrt(fSeps2);
normal = (pointOnBox-v3PointOnSphere);
normal *= btScalar(1.)/fSep;
}
return fSep;
}
//////////////////////////////////////////////////
// Deep penetration case
fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
bounds[0] = boundsVec[0];
bounds[1] = boundsVec[1];
if ( fPenetration <= btScalar(0.0) )
return (fPenetration-margins);
else
return btScalar(1.0);
}
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax)
{
btVector3 bounds[2];
bounds[0] = aabbMin;
bounds[1] = aabbMax;
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) );
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
const btTransform& m44T = boxObj->getWorldTransform();
// convert point in local space
prel = m44T.invXform( sphereCenter);
///////////
for (int i=0;i<6;i++)
{
int j = i<3 ? 0:1;
if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0);
if ( fSepThis > fSep )
{
p0 = bounds[j]; normal = (btVector3&)n[i];
fSep = fSepThis;
}
}
pointOnBox = prel - normal*(normal.dot((prel-p0)));
v3PointOnSphere = pointOnBox + normal*fSep;
// transform back in world space
tmp = m44T( pointOnBox);
pointOnBox = tmp;
tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp;
normal = (pointOnBox-v3PointOnSphere).normalize();
return fSep;
}
/*
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 "btSphereBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
//#include <stdio.h>
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
btCollisionObject* boxObj = m_isSwapped? col0 : col1;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
m_ownManifold = true;
}
}
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
btCollisionObject* boxObj = m_isSwapped? body0 : body1;
btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
btVector3 normalOnSurfaceB;
btVector3 pOnBox,pOnSphere;
btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
btScalar radius = sphere0->getRadius();
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->addContactPoint(normalOnSurfaceB,pOnBox,dist);
}
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
}
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}
btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius )
{
btScalar margins;
btVector3 bounds[2];
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
bounds[1] = boxShape->getHalfExtentsWithoutMargin();
margins = boxShape->getMargin();//also add sphereShape margin?
const btTransform& m44T = boxObj->getWorldTransform();
btVector3 boundsVec[2];
btScalar fPenetration;
boundsVec[0] = bounds[0];
boundsVec[1] = bounds[1];
btVector3 marginsVec( margins, margins, margins );
// add margins
bounds[0] += marginsVec;
bounds[1] -= marginsVec;
/////////////////////////////////////////////////
btVector3 tmp, prel, n[6], normal, v3P;
btScalar fSep = btScalar(10000000.0), fSepThis;
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) );
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
// convert point in local space
prel = m44T.invXform( sphereCenter);
bool bFound = false;
v3P = prel;
for (int i=0;i<6;i++)
{
int j = i<3? 0:1;
if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
{
v3P = v3P - n[i]*fSepThis;
bFound = true;
}
}
//
if ( bFound )
{
bounds[0] = boundsVec[0];
bounds[1] = boundsVec[1];
normal = (prel - v3P).normalize();
pointOnBox = v3P + normal*margins;
v3PointOnSphere = prel - normal*fRadius;
if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
{
return btScalar(1.0);
}
// transform back in world space
tmp = m44T( pointOnBox);
pointOnBox = tmp;
tmp = m44T( v3PointOnSphere);
v3PointOnSphere = tmp;
btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
//if this fails, fallback into deeper penetration case, below
if (fSeps2 > SIMD_EPSILON)
{
fSep = - btSqrt(fSeps2);
normal = (pointOnBox-v3PointOnSphere);
normal *= btScalar(1.)/fSep;
}
return fSep;
}
//////////////////////////////////////////////////
// Deep penetration case
fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
bounds[0] = boundsVec[0];
bounds[1] = boundsVec[1];
if ( fPenetration <= btScalar(0.0) )
return (fPenetration-margins);
else
return btScalar(1.0);
}
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax)
{
btVector3 bounds[2];
bounds[0] = aabbMin;
bounds[1] = aabbMax;
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) );
n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
const btTransform& m44T = boxObj->getWorldTransform();
// convert point in local space
prel = m44T.invXform( sphereCenter);
///////////
for (int i=0;i<6;i++)
{
int j = i<3 ? 0:1;
if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0);
if ( fSepThis > fSep )
{
p0 = bounds[j]; normal = (btVector3&)n[i];
fSep = fSepThis;
}
}
pointOnBox = prel - normal*(normal.dot((prel-p0)));
v3PointOnSphere = pointOnBox + normal*fSep;
// transform back in world space
tmp = m44T( pointOnBox);
pointOnBox = tmp;
tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp;
normal = (pointOnBox-v3PointOnSphere).normalize();
return fSep;
}

View File

@@ -1,75 +1,75 @@
/*
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 SPHERE_BOX_COLLISION_ALGORITHM_H
#define SPHERE_BOX_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
public:
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};
};
#endif //SPHERE_BOX_COLLISION_ALGORITHM_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.
*/
#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
#define SPHERE_BOX_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
public:
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};
};
#endif //SPHERE_BOX_COLLISION_ALGORITHM_H

View File

@@ -1,105 +1,105 @@
/*
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 "btSphereSphereCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
m_ownManifold = true;
}
}
btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
resultOut->setPersistentManifold(m_manifoldPtr);
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
}
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
}
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)col0;
(void)col1;
(void)dispatchInfo;
(void)resultOut;
//not yet
return btScalar(1.);
}
/*
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 "btSphereSphereCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
m_ownManifold = true;
}
}
btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
resultOut->setPersistentManifold(m_manifoldPtr);
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
}
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
}
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)col0;
(void)col1;
(void)dispatchInfo;
(void)resultOut;
//not yet
return btScalar(1.);
}

View File

@@ -1,66 +1,66 @@
/*
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 SPHERE_SPHERE_COLLISION_ALGORITHM_H
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
class btPersistentManifold;
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_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.
*/
#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
class btPersistentManifold;
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
/// Other features are frame-coherency (persistent data) and collision response.
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H

View File

@@ -1,84 +1,84 @@
/*
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 "btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "SphereTriangleDetector.h"
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
m_ownManifold = true;
}
}
btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
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);
SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(1e30);///@todo: tighter bounds
input.m_transformA = sphereObj->getWorldTransform();
input.m_transformB = triObj->getWorldTransform();
bool swapResults = m_swapped;
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
}
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}
/*
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 "btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "SphereTriangleDetector.h"
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
: btActivatingCollisionAlgorithm(ci,col0,col1),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
m_ownManifold = true;
}
}
btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
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);
SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(1e30);///@todo: tighter bounds
input.m_transformA = sphereObj->getWorldTransform();
input.m_transformB = triObj->getWorldTransform();
bool swapResults = m_swapped;
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
}
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}

View File

@@ -1,69 +1,69 @@
/*
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 SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.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.
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
public:
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
}
};
};
#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_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.
*/
#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#include "btActivatingCollisionAlgorithm.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.
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
public:
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
}
};
};
#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H

View File

@@ -1,171 +1,171 @@
/*
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 "btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
{
m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
}
btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(0,0,0);
btScalar maxDot(btScalar(-1e30));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
btVector3 vtx;
btScalar newDot;
btScalar radius = getRadius();
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
btScalar radius = getRadius();
for (int j=0;j<numVectors;j++)
{
btScalar maxDot(btScalar(-1e30));
const btVector3& vec = vectors[j];
btVector3 vtx;
btScalar newDot;
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supportVerticesOut[j] = vtx;
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supportVerticesOut[j] = vtx;
}
}
}
}
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//as an approximation, take the inertia of the box that bounds the spheres
btTransform ident;
ident.setIdentity();
btScalar radius = getRadius();
btVector3 halfExtents(radius,radius,radius);
halfExtents[getUpAxis()]+=getHalfHeight();
btScalar margin = CONVEX_DISTANCE_MARGIN;
btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(.08333333);
inertia[0] = scaledmass * (y2+z2);
inertia[1] = scaledmass * (x2+z2);
inertia[2] = scaledmass * (x2+y2);
}
btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
{
m_upAxis = 0;
m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
}
btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
{
m_upAxis = 2;
m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
}
/*
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 "btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
{
m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
}
btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(0,0,0);
btScalar maxDot(btScalar(-1e30));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
btVector3 vtx;
btScalar newDot;
btScalar radius = getRadius();
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
btScalar radius = getRadius();
for (int j=0;j<numVectors;j++)
{
btScalar maxDot(btScalar(-1e30));
const btVector3& vec = vectors[j];
btVector3 vtx;
btScalar newDot;
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supportVerticesOut[j] = vtx;
}
}
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supportVerticesOut[j] = vtx;
}
}
}
}
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//as an approximation, take the inertia of the box that bounds the spheres
btTransform ident;
ident.setIdentity();
btScalar radius = getRadius();
btVector3 halfExtents(radius,radius,radius);
halfExtents[getUpAxis()]+=getHalfHeight();
btScalar margin = CONVEX_DISTANCE_MARGIN;
btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(.08333333);
inertia[0] = scaledmass * (y2+z2);
inertia[1] = scaledmass * (x2+z2);
inertia[2] = scaledmass * (x2+y2);
}
btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
{
m_upAxis = 0;
m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
}
btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
{
m_upAxis = 2;
m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
}

View File

@@ -1,118 +1,118 @@
/*
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_CAPSULE_SHAPE_H
#define BT_CAPSULE_SHAPE_H
#include "btConvexInternalShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
class btCapsuleShape : public btConvexInternalShape
{
protected:
int m_upAxis;
protected:
///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
public:
btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
/// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 halfExtents(getRadius(),getRadius(),getRadius());
halfExtents[m_upAxis] = getRadius() + getHalfHeight();
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
virtual const char* getName()const
{
return "CapsuleShape";
}
int getUpAxis() const
{
return m_upAxis;
}
btScalar getRadius() const
{
int radiusAxis = (m_upAxis+2)%3;
return m_implicitShapeDimensions[radiusAxis];
}
btScalar getHalfHeight() const
{
return m_implicitShapeDimensions[m_upAxis];
}
};
///btCapsuleShapeX represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeX : public btCapsuleShape
{
public:
btCapsuleShapeX(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleX";
}
};
///btCapsuleShapeZ represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeZ : public btCapsuleShape
{
public:
btCapsuleShapeZ(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleZ";
}
};
#endif //BT_CAPSULE_SHAPE_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.
*/
#ifndef BT_CAPSULE_SHAPE_H
#define BT_CAPSULE_SHAPE_H
#include "btConvexInternalShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
class btCapsuleShape : public btConvexInternalShape
{
protected:
int m_upAxis;
protected:
///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
public:
btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
/// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 halfExtents(getRadius(),getRadius(),getRadius());
halfExtents[m_upAxis] = getRadius() + getHalfHeight();
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
virtual const char* getName()const
{
return "CapsuleShape";
}
int getUpAxis() const
{
return m_upAxis;
}
btScalar getRadius() const
{
int radiusAxis = (m_upAxis+2)%3;
return m_implicitShapeDimensions[radiusAxis];
}
btScalar getHalfHeight() const
{
return m_implicitShapeDimensions[m_upAxis];
}
};
///btCapsuleShapeX represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeX : public btCapsuleShape
{
public:
btCapsuleShapeX(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleX";
}
};
///btCapsuleShapeZ represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeZ : public btCapsuleShape
{
public:
btCapsuleShapeZ(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleZ";
}
};
#endif //BT_CAPSULE_SHAPE_H

View File

@@ -1,156 +1,156 @@
/*
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 "btConvexPointCloudShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
recalcLocalAabb();
}
#ifndef __SPU__
btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
btScalar newDot,maxDot = btScalar(-1e30);
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
for (int i=0;i<m_numPoints;i++)
{
btVector3 vtx = getScaledPoint(i);
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
btScalar newDot;
//use 'w' component of supportVerticesOut?
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i][3] = btScalar(-1e30);
}
}
for (int i=0;i<m_numPoints;i++)
{
btVector3 vtx = getScaledPoint(i);
for (int j=0;j<numVectors;j++)
{
const btVector3& vec = vectors[j];
newDot = vec.dot(vtx);
if (newDot > supportVerticesOut[j][3])
{
//WARNING: don't swap next lines, the w component would get overwritten!
supportVerticesOut[j] = vtx;
supportVerticesOut[j][3] = newDot;
}
}
}
}
btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
}
#endif
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
int btConvexPointCloudShape::getNumVertices() const
{
return m_numPoints;
}
int btConvexPointCloudShape::getNumEdges() const
{
return 0;
}
void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
{
btAssert (0);
}
void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
{
vtx = m_unscaledPoints[i]*m_localScaling;
}
int btConvexPointCloudShape::getNumPlanes() const
{
return 0;
}
void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
{
btAssert(0);
}
//not yet
bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
{
btAssert(0);
return false;
}
/*
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 "btConvexPointCloudShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
recalcLocalAabb();
}
#ifndef __SPU__
btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
btScalar newDot,maxDot = btScalar(-1e30);
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
for (int i=0;i<m_numPoints;i++)
{
btVector3 vtx = getScaledPoint(i);
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
maxDot = newDot;
supVec = vtx;
}
}
return supVec;
}
void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
btScalar newDot;
//use 'w' component of supportVerticesOut?
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i][3] = btScalar(-1e30);
}
}
for (int i=0;i<m_numPoints;i++)
{
btVector3 vtx = getScaledPoint(i);
for (int j=0;j<numVectors;j++)
{
const btVector3& vec = vectors[j];
newDot = vec.dot(vtx);
if (newDot > supportVerticesOut[j][3])
{
//WARNING: don't swap next lines, the w component would get overwritten!
supportVerticesOut[j] = vtx;
supportVerticesOut[j][3] = newDot;
}
}
}
}
btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
}
#endif
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
int btConvexPointCloudShape::getNumVertices() const
{
return m_numPoints;
}
int btConvexPointCloudShape::getNumEdges() const
{
return 0;
}
void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
{
btAssert (0);
}
void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
{
vtx = m_unscaledPoints[i]*m_localScaling;
}
int btConvexPointCloudShape::getNumPlanes() const
{
return 0;
}
void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
{
btAssert(0);
}
//not yet
bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
{
btAssert(0);
return false;
}

View File

@@ -1,96 +1,96 @@
/*
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_CONVEX_POINT_CLOUD_SHAPE_H
#define BT_CONVEX_POINT_CLOUD_SHAPE_H
#include "btPolyhedralConvexShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexShape
{
btVector3* m_unscaledPoints;
int m_numPoints;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
{
m_localScaling = localScaling;
m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
m_unscaledPoints = points;
m_numPoints = numPoints;
if (computeAabb)
recalcLocalAabb();
}
void setPoints (btVector3* points, int numPoints, bool computeAabb = true)
{
m_unscaledPoints = points;
m_numPoints = numPoints;
if (computeAabb)
recalcLocalAabb();
}
SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
{
return m_unscaledPoints;
}
SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
{
return m_unscaledPoints;
}
SIMD_FORCE_INLINE int getNumPoints() const
{
return m_numPoints;
}
SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const
{
return m_unscaledPoints[index] * m_localScaling;
}
#ifndef __SPU__
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
#endif
//debugging
virtual const char* getName()const {return "ConvexPointCloud";}
virtual int getNumVertices() const;
virtual int getNumEdges() const;
virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
virtual void getVertex(int i,btVector3& vtx) const;
virtual int getNumPlanes() const;
virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
///in case we receive negative scaling
virtual void setLocalScaling(const btVector3& scaling);
};
#endif //BT_CONVEX_POINT_CLOUD_SHAPE_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.
*/
#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H
#define BT_CONVEX_POINT_CLOUD_SHAPE_H
#include "btPolyhedralConvexShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "LinearMath/btAlignedObjectArray.h"
///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexShape
{
btVector3* m_unscaledPoints;
int m_numPoints;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
{
m_localScaling = localScaling;
m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
m_unscaledPoints = points;
m_numPoints = numPoints;
if (computeAabb)
recalcLocalAabb();
}
void setPoints (btVector3* points, int numPoints, bool computeAabb = true)
{
m_unscaledPoints = points;
m_numPoints = numPoints;
if (computeAabb)
recalcLocalAabb();
}
SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
{
return m_unscaledPoints;
}
SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
{
return m_unscaledPoints;
}
SIMD_FORCE_INLINE int getNumPoints() const
{
return m_numPoints;
}
SIMD_FORCE_INLINE btVector3 getScaledPoint( int index) const
{
return m_unscaledPoints[index] * m_localScaling;
}
#ifndef __SPU__
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
#endif
//debugging
virtual const char* getName()const {return "ConvexPointCloud";}
virtual int getNumVertices() const;
virtual int getNumEdges() const;
virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
virtual void getVertex(int i,btVector3& vtx) const;
virtual int getNumPlanes() const;
virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
virtual bool isInside(const btVector3& pt,btScalar tolerance) const;
///in case we receive negative scaling
virtual void setLocalScaling(const btVector3& scaling);
};
#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H

View File

@@ -1,314 +1,314 @@
/*
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 "btConvexTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
: btPolyhedralConvexShape(), m_stridingMesh(meshInterface)
{
m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
if ( calcAabb )
recalcLocalAabb();
}
///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
///but then we are duplicating
class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
{
btVector3 m_supportVertexLocal;
public:
btScalar m_maxDot;
btVector3 m_supportVecLocal;
LocalSupportVertexCallback(const btVector3& supportVecLocal)
: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
m_maxDot(btScalar(-1e30)),
m_supportVecLocal(supportVecLocal)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
(void)triangleIndex;
(void)partId;
for (int i=0;i<3;i++)
{
btScalar dot = m_supportVecLocal.dot(triangle[i]);
if (dot > m_maxDot)
{
m_maxDot = dot;
m_supportVertexLocal = triangle[i];
}
}
}
btVector3 GetSupportVertexLocal()
{
return m_supportVertexLocal;
}
};
btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
LocalSupportVertexCallback supportCallback(vec);
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
supVec = supportCallback.GetSupportVertexLocal();
return supVec;
}
void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
//use 'w' component of supportVerticesOut?
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i][3] = btScalar(-1e30);
}
}
///@todo: could do the batch inside the callback!
for (int j=0;j<numVectors;j++)
{
const btVector3& vec = vectors[j];
LocalSupportVertexCallback supportCallback(vec);
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
}
}
btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
}
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
int btConvexTriangleMeshShape::getNumVertices() const
{
//cache this?
return 0;
}
int btConvexTriangleMeshShape::getNumEdges() const
{
return 0;
}
void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
{
btAssert(0);
}
void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
{
btAssert(0);
}
int btConvexTriangleMeshShape::getNumPlanes() const
{
return 0;
}
void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const
{
btAssert(0);
}
//not yet
bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
{
btAssert(0);
return false;
}
void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_stridingMesh->setScaling(scaling);
recalcLocalAabb();
}
const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
{
return m_stridingMesh->getScaling();
}
void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
{
class CenterCallback: public btInternalTriangleIndexCallback
{
bool first;
btVector3 ref;
btVector3 sum;
btScalar volume;
public:
CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
if (first)
{
ref = triangle[0];
first = false;
}
else
{
btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
volume += vol;
}
}
btVector3 getCenter()
{
return (volume > 0) ? sum / volume : ref;
}
btScalar getVolume()
{
return volume * btScalar(1. / 6);
}
};
class InertiaCallback: public btInternalTriangleIndexCallback
{
btMatrix3x3 sum;
btVector3 center;
public:
InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
btMatrix3x3 i;
btVector3 a = triangle[0] - center;
btVector3 b = triangle[1] - center;
btVector3 c = triangle[2] - center;
btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
for (int j = 0; j < 3; j++)
{
for (int k = 0; k <= j; k++)
{
i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+ btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
}
}
btScalar i00 = -i[0][0];
btScalar i11 = -i[1][1];
btScalar i22 = -i[2][2];
i[0][0] = i11 + i22;
i[1][1] = i22 + i00;
i[2][2] = i00 + i11;
sum[0] += i[0];
sum[1] += i[1];
sum[2] += i[2];
}
btMatrix3x3& getInertia()
{
return sum;
}
};
CenterCallback centerCallback;
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
btVector3 center = centerCallback.getCenter();
principal.setOrigin(center);
volume = centerCallback.getVolume();
InertiaCallback inertiaCallback(center);
m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
btMatrix3x3& i = inertiaCallback.getInertia();
i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(i[0][0], i[1][1], i[2][2]);
inertia /= volume;
}
/*
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 "btConvexTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
: btPolyhedralConvexShape(), m_stridingMesh(meshInterface)
{
m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
if ( calcAabb )
recalcLocalAabb();
}
///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
///but then we are duplicating
class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
{
btVector3 m_supportVertexLocal;
public:
btScalar m_maxDot;
btVector3 m_supportVecLocal;
LocalSupportVertexCallback(const btVector3& supportVecLocal)
: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
m_maxDot(btScalar(-1e30)),
m_supportVecLocal(supportVecLocal)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
(void)triangleIndex;
(void)partId;
for (int i=0;i<3;i++)
{
btScalar dot = m_supportVecLocal.dot(triangle[i]);
if (dot > m_maxDot)
{
m_maxDot = dot;
m_supportVertexLocal = triangle[i];
}
}
}
btVector3 GetSupportVertexLocal()
{
return m_supportVertexLocal;
}
};
btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
{
vec.setValue(1,0,0);
} else
{
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
LocalSupportVertexCallback supportCallback(vec);
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
supVec = supportCallback.GetSupportVertexLocal();
return supVec;
}
void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
//use 'w' component of supportVerticesOut?
{
for (int i=0;i<numVectors;i++)
{
supportVerticesOut[i][3] = btScalar(-1e30);
}
}
///@todo: could do the batch inside the callback!
for (int j=0;j<numVectors;j++)
{
const btVector3& vec = vectors[j];
LocalSupportVertexCallback supportCallback(vec);
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
}
}
btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
{
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
}
//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
int btConvexTriangleMeshShape::getNumVertices() const
{
//cache this?
return 0;
}
int btConvexTriangleMeshShape::getNumEdges() const
{
return 0;
}
void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
{
btAssert(0);
}
void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
{
btAssert(0);
}
int btConvexTriangleMeshShape::getNumPlanes() const
{
return 0;
}
void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int ) const
{
btAssert(0);
}
//not yet
bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
{
btAssert(0);
return false;
}
void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_stridingMesh->setScaling(scaling);
recalcLocalAabb();
}
const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
{
return m_stridingMesh->getScaling();
}
void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
{
class CenterCallback: public btInternalTriangleIndexCallback
{
bool first;
btVector3 ref;
btVector3 sum;
btScalar volume;
public:
CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
if (first)
{
ref = triangle[0];
first = false;
}
else
{
btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
volume += vol;
}
}
btVector3 getCenter()
{
return (volume > 0) ? sum / volume : ref;
}
btScalar getVolume()
{
return volume * btScalar(1. / 6);
}
};
class InertiaCallback: public btInternalTriangleIndexCallback
{
btMatrix3x3 sum;
btVector3 center;
public:
InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
btMatrix3x3 i;
btVector3 a = triangle[0] - center;
btVector3 b = triangle[1] - center;
btVector3 c = triangle[2] - center;
btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
for (int j = 0; j < 3; j++)
{
for (int k = 0; k <= j; k++)
{
i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+ btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
}
}
btScalar i00 = -i[0][0];
btScalar i11 = -i[1][1];
btScalar i22 = -i[2][2];
i[0][0] = i11 + i22;
i[1][1] = i22 + i00;
i[2][2] = i00 + i11;
sum[0] += i[0];
sum[1] += i[1];
sum[2] += i[2];
}
btMatrix3x3& getInertia()
{
return sum;
}
};
CenterCallback centerCallback;
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
btVector3 center = centerCallback.getCenter();
principal.setOrigin(center);
volume = centerCallback.getVolume();
InertiaCallback inertiaCallback(center);
m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
btMatrix3x3& i = inertiaCallback.getInertia();
i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(i[0][0], i[1][1], i[2][2]);
inertia /= volume;
}

View File

@@ -1,411 +1,411 @@
/*
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 "btHeightfieldTerrainShape.h"
#include "LinearMath/btTransformUtil.h"
btHeightfieldTerrainShape::btHeightfieldTerrainShape
(
int heightStickWidth, int heightStickLength, void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges
)
{
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
flipQuadEdges);
}
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
{
// legacy constructor: support only float or unsigned char,
// and min height is zero
PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
btScalar minHeight = 0.0;
// previously, height = uchar * maxHeight / 65535.
// So to preserve legacy behavior, heightScale = maxHeight / 65535
btScalar heightScale = maxHeight / 65535;
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
flipQuadEdges);
}
void btHeightfieldTerrainShape::initialize
(
int heightStickWidth, int heightStickLength, void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges
)
{
// validation
btAssert(heightStickWidth > 1 && "bad width");
btAssert(heightStickLength > 1 && "bad length");
btAssert(heightfieldData && "null heightfield data");
// btAssert(heightScale) -- do we care? Trust caller here
btAssert(minHeight <= maxHeight && "bad min/max height");
btAssert(upAxis >= 0 && upAxis < 3 &&
"bad upAxis--should be in range [0,2]");
btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
"Bad height data type enum");
// initialize member variables
m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
m_heightStickWidth = heightStickWidth;
m_heightStickLength = heightStickLength;
m_minHeight = minHeight;
m_maxHeight = maxHeight;
m_width = (btScalar) (heightStickWidth - 1);
m_length = (btScalar) (heightStickLength - 1);
m_heightScale = heightScale;
m_heightfieldDataUnknown = heightfieldData;
m_heightDataType = hdt;
m_flipQuadEdges = flipQuadEdges;
m_useDiamondSubdivision = false;
m_upAxis = upAxis;
m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
// determine min/max axis-aligned bounding box (aabb) values
switch (m_upAxis)
{
case 0:
{
m_localAabbMin.setValue(m_minHeight, 0, 0);
m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
break;
}
case 1:
{
m_localAabbMin.setValue(0, m_minHeight, 0);
m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
break;
};
case 2:
{
m_localAabbMin.setValue(0, 0, m_minHeight);
m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0 && "Bad m_upAxis");
}
}
// remember origin (defined as exact middle of aabb)
m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
}
btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
{
}
void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
btVector3 localOrigin(0, 0, 0);
localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
localOrigin *= m_localScaling;
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
/// This returns the "raw" (user's initial) height, not the actual height.
/// The actual height needs to be adjusted to be relative to the center
/// of the heightfield's AABB.
btScalar
btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
{
btScalar val = 0.f;
switch (m_heightDataType)
{
case PHY_FLOAT:
{
val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
break;
}
case PHY_UCHAR:
{
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
val = heightFieldValue * m_heightScale;
break;
}
case PHY_SHORT:
{
short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
val = hfValue * m_heightScale;
break;
}
default:
{
btAssert(!"Bad m_heightDataType");
}
}
return val;
}
/// this returns the vertex in bullet-local coordinates
void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
btAssert(x>=0);
btAssert(y>=0);
btAssert(x<m_heightStickWidth);
btAssert(y<m_heightStickLength);
btScalar height = getRawHeightFieldValue(x,y);
switch (m_upAxis)
{
case 0:
{
vertex.setValue(
height - m_localOrigin.getX(),
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0) ) + y
);
break;
}
case 1:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
height - m_localOrigin.getY(),
(-m_length/btScalar(2.0)) + y
);
break;
};
case 2:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0)) + y,
height - m_localOrigin.getZ()
);
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
vertex*=m_localScaling;
}
static inline int
getQuantized
(
btScalar x
)
{
if (x < 0.0) {
return (int) (x - 0.5);
}
return (int) (x + 0.5);
}
/// given input vector, return quantized version
/**
This routine is basically determining the gridpoint indices for a given
input vector, answering the question: "which gridpoint is closest to the
provided point?".
"with clamp" means that we restrict the point to be in the heightfield's
axis-aligned bounding box.
*/
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
{
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax);
out[0] = getQuantized(clampedPoint.getX());
out[1] = getQuantized(clampedPoint.getY());
out[2] = getQuantized(clampedPoint.getZ());
}
/// process all triangles within the provided axis-aligned bounding box
/**
basic algorithm:
- convert input aabb to local coordinates (scale down and shift for local origin)
- convert input aabb to a range of heightfield grid points (quantize)
- iterate over all triangles in that subset of the grid
*/
void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
// scale down the input aabb's so they are in local (non-scaled) coordinates
btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
// account for local origin
localAabbMin += m_localOrigin;
localAabbMax += m_localOrigin;
//quantize the aabbMin and aabbMax, and adjust the start/end ranges
int quantizedAabbMin[3];
int quantizedAabbMax[3];
quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
// expand the min/max quantized values
// this is to catch the case where the input aabb falls between grid points!
for (int i = 0; i < 3; ++i) {
quantizedAabbMin[i]--;
quantizedAabbMax[i]++;
}
int startX=0;
int endX=m_heightStickWidth-1;
int startJ=0;
int endJ=m_heightStickLength-1;
switch (m_upAxis)
{
case 0:
{
if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1];
if (quantizedAabbMax[1]<endX)
endX = quantizedAabbMax[1];
if (quantizedAabbMin[2]>startJ)
startJ = quantizedAabbMin[2];
if (quantizedAabbMax[2]<endJ)
endJ = quantizedAabbMax[2];
break;
}
case 1:
{
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)
endX = quantizedAabbMax[0];
if (quantizedAabbMin[2]>startJ)
startJ = quantizedAabbMin[2];
if (quantizedAabbMax[2]<endJ)
endJ = quantizedAabbMax[2];
break;
};
case 2:
{
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)
endX = quantizedAabbMax[0];
if (quantizedAabbMin[1]>startJ)
startJ = quantizedAabbMin[1];
if (quantizedAabbMax[1]<endJ)
endJ = quantizedAabbMax[1];
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
for(int j=startJ; j<endJ; j++)
{
for(int x=startX; x<endX; x++)
{
btVector3 vertices[3];
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
{
//first triangle
getVertex(x,j,vertices[0]);
getVertex(x+1,j,vertices[1]);
getVertex(x+1,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
//second triangle
getVertex(x,j,vertices[0]);
getVertex(x+1,j+1,vertices[1]);
getVertex(x,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
} else
{
//first triangle
getVertex(x,j,vertices[0]);
getVertex(x,j+1,vertices[1]);
getVertex(x+1,j,vertices[2]);
callback->processTriangle(vertices,x,j);
//second triangle
getVertex(x+1,j,vertices[0]);
getVertex(x,j+1,vertices[1]);
getVertex(x+1,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
}
}
}
}
void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
{
//moving concave objects not supported
inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
}
void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
{
return m_localScaling;
}
/*
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 "btHeightfieldTerrainShape.h"
#include "LinearMath/btTransformUtil.h"
btHeightfieldTerrainShape::btHeightfieldTerrainShape
(
int heightStickWidth, int heightStickLength, void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges
)
{
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
flipQuadEdges);
}
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
{
// legacy constructor: support only float or unsigned char,
// and min height is zero
PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
btScalar minHeight = 0.0;
// previously, height = uchar * maxHeight / 65535.
// So to preserve legacy behavior, heightScale = maxHeight / 65535
btScalar heightScale = maxHeight / 65535;
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
flipQuadEdges);
}
void btHeightfieldTerrainShape::initialize
(
int heightStickWidth, int heightStickLength, void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges
)
{
// validation
btAssert(heightStickWidth > 1 && "bad width");
btAssert(heightStickLength > 1 && "bad length");
btAssert(heightfieldData && "null heightfield data");
// btAssert(heightScale) -- do we care? Trust caller here
btAssert(minHeight <= maxHeight && "bad min/max height");
btAssert(upAxis >= 0 && upAxis < 3 &&
"bad upAxis--should be in range [0,2]");
btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
"Bad height data type enum");
// initialize member variables
m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
m_heightStickWidth = heightStickWidth;
m_heightStickLength = heightStickLength;
m_minHeight = minHeight;
m_maxHeight = maxHeight;
m_width = (btScalar) (heightStickWidth - 1);
m_length = (btScalar) (heightStickLength - 1);
m_heightScale = heightScale;
m_heightfieldDataUnknown = heightfieldData;
m_heightDataType = hdt;
m_flipQuadEdges = flipQuadEdges;
m_useDiamondSubdivision = false;
m_upAxis = upAxis;
m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
// determine min/max axis-aligned bounding box (aabb) values
switch (m_upAxis)
{
case 0:
{
m_localAabbMin.setValue(m_minHeight, 0, 0);
m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
break;
}
case 1:
{
m_localAabbMin.setValue(0, m_minHeight, 0);
m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
break;
};
case 2:
{
m_localAabbMin.setValue(0, 0, m_minHeight);
m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0 && "Bad m_upAxis");
}
}
// remember origin (defined as exact middle of aabb)
m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
}
btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
{
}
void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
btVector3 localOrigin(0, 0, 0);
localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
localOrigin *= m_localScaling;
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
}
/// This returns the "raw" (user's initial) height, not the actual height.
/// The actual height needs to be adjusted to be relative to the center
/// of the heightfield's AABB.
btScalar
btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
{
btScalar val = 0.f;
switch (m_heightDataType)
{
case PHY_FLOAT:
{
val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
break;
}
case PHY_UCHAR:
{
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
val = heightFieldValue * m_heightScale;
break;
}
case PHY_SHORT:
{
short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
val = hfValue * m_heightScale;
break;
}
default:
{
btAssert(!"Bad m_heightDataType");
}
}
return val;
}
/// this returns the vertex in bullet-local coordinates
void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
btAssert(x>=0);
btAssert(y>=0);
btAssert(x<m_heightStickWidth);
btAssert(y<m_heightStickLength);
btScalar height = getRawHeightFieldValue(x,y);
switch (m_upAxis)
{
case 0:
{
vertex.setValue(
height - m_localOrigin.getX(),
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0) ) + y
);
break;
}
case 1:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
height - m_localOrigin.getY(),
(-m_length/btScalar(2.0)) + y
);
break;
};
case 2:
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0)) + y,
height - m_localOrigin.getZ()
);
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
vertex*=m_localScaling;
}
static inline int
getQuantized
(
btScalar x
)
{
if (x < 0.0) {
return (int) (x - 0.5);
}
return (int) (x + 0.5);
}
/// given input vector, return quantized version
/**
This routine is basically determining the gridpoint indices for a given
input vector, answering the question: "which gridpoint is closest to the
provided point?".
"with clamp" means that we restrict the point to be in the heightfield's
axis-aligned bounding box.
*/
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
{
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax);
out[0] = getQuantized(clampedPoint.getX());
out[1] = getQuantized(clampedPoint.getY());
out[2] = getQuantized(clampedPoint.getZ());
}
/// process all triangles within the provided axis-aligned bounding box
/**
basic algorithm:
- convert input aabb to local coordinates (scale down and shift for local origin)
- convert input aabb to a range of heightfield grid points (quantize)
- iterate over all triangles in that subset of the grid
*/
void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
// scale down the input aabb's so they are in local (non-scaled) coordinates
btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
// account for local origin
localAabbMin += m_localOrigin;
localAabbMax += m_localOrigin;
//quantize the aabbMin and aabbMax, and adjust the start/end ranges
int quantizedAabbMin[3];
int quantizedAabbMax[3];
quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
// expand the min/max quantized values
// this is to catch the case where the input aabb falls between grid points!
for (int i = 0; i < 3; ++i) {
quantizedAabbMin[i]--;
quantizedAabbMax[i]++;
}
int startX=0;
int endX=m_heightStickWidth-1;
int startJ=0;
int endJ=m_heightStickLength-1;
switch (m_upAxis)
{
case 0:
{
if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1];
if (quantizedAabbMax[1]<endX)
endX = quantizedAabbMax[1];
if (quantizedAabbMin[2]>startJ)
startJ = quantizedAabbMin[2];
if (quantizedAabbMax[2]<endJ)
endJ = quantizedAabbMax[2];
break;
}
case 1:
{
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)
endX = quantizedAabbMax[0];
if (quantizedAabbMin[2]>startJ)
startJ = quantizedAabbMin[2];
if (quantizedAabbMax[2]<endJ)
endJ = quantizedAabbMax[2];
break;
};
case 2:
{
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)
endX = quantizedAabbMax[0];
if (quantizedAabbMin[1]>startJ)
startJ = quantizedAabbMin[1];
if (quantizedAabbMax[1]<endJ)
endJ = quantizedAabbMax[1];
break;
}
default:
{
//need to get valid m_upAxis
btAssert(0);
}
}
for(int j=startJ; j<endJ; j++)
{
for(int x=startX; x<endX; x++)
{
btVector3 vertices[3];
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
{
//first triangle
getVertex(x,j,vertices[0]);
getVertex(x+1,j,vertices[1]);
getVertex(x+1,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
//second triangle
getVertex(x,j,vertices[0]);
getVertex(x+1,j+1,vertices[1]);
getVertex(x,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
} else
{
//first triangle
getVertex(x,j,vertices[0]);
getVertex(x,j+1,vertices[1]);
getVertex(x+1,j,vertices[2]);
callback->processTriangle(vertices,x,j);
//second triangle
getVertex(x+1,j,vertices[0]);
getVertex(x,j+1,vertices[1]);
getVertex(x+1,j+1,vertices[2]);
callback->processTriangle(vertices,x,j);
}
}
}
}
void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
{
//moving concave objects not supported
inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
}
void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
{
return m_localScaling;
}

View File

@@ -1,161 +1,161 @@
/*
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 HEIGHTFIELD_TERRAIN_SHAPE_H
#define HEIGHTFIELD_TERRAIN_SHAPE_H
#include "btConcaveShape.h"
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
/**
The caller is responsible for maintaining the heightfield array; this
class does not make a copy.
The heightfield can be dynamic so long as the min/max height values
capture the extremes (heights must always be in that range).
The local origin of the heightfield is assumed to be the exact
center (as determined by width and length and height, with each
axis multiplied by the localScaling).
\b NOTE: be careful with coordinates. If you have a heightfield with a local
min height of -100m, and a max height of +500m, you may be tempted to place it
at the origin (0,0) and expect the heights in world coordinates to be
-100 to +500 meters.
Actually, the heights will be -300 to +300m, because bullet will re-center
the heightfield based on its AABB (which is determined by the min/max
heights). So keep in mind that once you create a btHeightfieldTerrainShape
object, the heights will be adjusted relative to the center of the AABB. This
is different to the behavior of many rendering engines, but is useful for
physics engines.
Most (but not all) rendering and heightfield libraries assume upAxis = 1
(that is, the y-axis is "up"). This class allows any of the 3 coordinates
to be "up". Make sure your choice of axis is consistent with your rendering
system.
The heightfield heights are determined from the data type used for the
heightfieldData array.
- PHY_UCHAR: height at a point is the uchar value at the
grid point, multipled by heightScale. uchar isn't recommended
because of its inability to deal with negative values, and
low resolution (8-bit).
- PHY_SHORT: height at a point is the short int value at that grid
point, multipled by heightScale.
- PHY_FLOAT: height at a point is the float value at that grid
point. heightScale is ignored when using the float heightfield
data type.
Whatever the caller specifies as minHeight and maxHeight will be honored.
The class will not inspect the heightfield to discover the actual minimum
or maximum heights. These values are used to determine the heightfield's
axis-aligned bounding box, multiplied by localScaling.
For usage and testing see the TerrainDemo.
*/
class btHeightfieldTerrainShape : public btConcaveShape
{
protected:
btVector3 m_localAabbMin;
btVector3 m_localAabbMax;
btVector3 m_localOrigin;
///terrain data
int m_heightStickWidth;
int m_heightStickLength;
btScalar m_minHeight;
btScalar m_maxHeight;
btScalar m_width;
btScalar m_length;
btScalar m_heightScale;
union
{
unsigned char* m_heightfieldDataUnsignedChar;
short* m_heightfieldDataShort;
btScalar* m_heightfieldDataFloat;
void* m_heightfieldDataUnknown;
};
PHY_ScalarType m_heightDataType;
bool m_flipQuadEdges;
bool m_useDiamondSubdivision;
int m_upAxis;
btVector3 m_localScaling;
virtual btScalar getRawHeightFieldValue(int x,int y) const;
void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
void getVertex(int x,int y,btVector3& vertex) const;
/// protected initialization
/**
Handles the work of constructors so that public constructors can be
backwards-compatible without a lot of copy/paste.
*/
void initialize(int heightStickWidth, int heightStickLength,
void* heightfieldData, btScalar heightScale,
btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType heightDataType, bool flipQuadEdges);
public:
/// preferred constructor
/**
This constructor supports a range of heightfield
data types, and allows for a non-zero minimum height value.
heightScale is needed for any integer-based heightfield data types.
*/
btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
void* heightfieldData, btScalar heightScale,
btScalar minHeight, btScalar maxHeight,
int upAxis, PHY_ScalarType heightDataType,
bool flipQuadEdges);
/// legacy constructor
/**
The legacy constructor assumes the heightfield has a minimum height
of zero. Only unsigned char or floats are supported. For legacy
compatibility reasons, heightScale is calculated as maxHeight / 65535
(and is only used when useFloatData = false).
*/
btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape();
void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
//debugging
virtual const char* getName()const {return "HEIGHTFIELD";}
};
#endif //HEIGHTFIELD_TERRAIN_SHAPE_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.
*/
#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H
#define HEIGHTFIELD_TERRAIN_SHAPE_H
#include "btConcaveShape.h"
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
/**
The caller is responsible for maintaining the heightfield array; this
class does not make a copy.
The heightfield can be dynamic so long as the min/max height values
capture the extremes (heights must always be in that range).
The local origin of the heightfield is assumed to be the exact
center (as determined by width and length and height, with each
axis multiplied by the localScaling).
\b NOTE: be careful with coordinates. If you have a heightfield with a local
min height of -100m, and a max height of +500m, you may be tempted to place it
at the origin (0,0) and expect the heights in world coordinates to be
-100 to +500 meters.
Actually, the heights will be -300 to +300m, because bullet will re-center
the heightfield based on its AABB (which is determined by the min/max
heights). So keep in mind that once you create a btHeightfieldTerrainShape
object, the heights will be adjusted relative to the center of the AABB. This
is different to the behavior of many rendering engines, but is useful for
physics engines.
Most (but not all) rendering and heightfield libraries assume upAxis = 1
(that is, the y-axis is "up"). This class allows any of the 3 coordinates
to be "up". Make sure your choice of axis is consistent with your rendering
system.
The heightfield heights are determined from the data type used for the
heightfieldData array.
- PHY_UCHAR: height at a point is the uchar value at the
grid point, multipled by heightScale. uchar isn't recommended
because of its inability to deal with negative values, and
low resolution (8-bit).
- PHY_SHORT: height at a point is the short int value at that grid
point, multipled by heightScale.
- PHY_FLOAT: height at a point is the float value at that grid
point. heightScale is ignored when using the float heightfield
data type.
Whatever the caller specifies as minHeight and maxHeight will be honored.
The class will not inspect the heightfield to discover the actual minimum
or maximum heights. These values are used to determine the heightfield's
axis-aligned bounding box, multiplied by localScaling.
For usage and testing see the TerrainDemo.
*/
class btHeightfieldTerrainShape : public btConcaveShape
{
protected:
btVector3 m_localAabbMin;
btVector3 m_localAabbMax;
btVector3 m_localOrigin;
///terrain data
int m_heightStickWidth;
int m_heightStickLength;
btScalar m_minHeight;
btScalar m_maxHeight;
btScalar m_width;
btScalar m_length;
btScalar m_heightScale;
union
{
unsigned char* m_heightfieldDataUnsignedChar;
short* m_heightfieldDataShort;
btScalar* m_heightfieldDataFloat;
void* m_heightfieldDataUnknown;
};
PHY_ScalarType m_heightDataType;
bool m_flipQuadEdges;
bool m_useDiamondSubdivision;
int m_upAxis;
btVector3 m_localScaling;
virtual btScalar getRawHeightFieldValue(int x,int y) const;
void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
void getVertex(int x,int y,btVector3& vertex) const;
/// protected initialization
/**
Handles the work of constructors so that public constructors can be
backwards-compatible without a lot of copy/paste.
*/
void initialize(int heightStickWidth, int heightStickLength,
void* heightfieldData, btScalar heightScale,
btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType heightDataType, bool flipQuadEdges);
public:
/// preferred constructor
/**
This constructor supports a range of heightfield
data types, and allows for a non-zero minimum height value.
heightScale is needed for any integer-based heightfield data types.
*/
btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
void* heightfieldData, btScalar heightScale,
btScalar minHeight, btScalar maxHeight,
int upAxis, PHY_ScalarType heightDataType,
bool flipQuadEdges);
/// legacy constructor
/**
The legacy constructor assumes the heightfield has a minimum height
of zero. Only unsigned char or floats are supported. For legacy
compatibility reasons, heightScale is calculated as maxHeight / 65535
(and is only used when useFloatData = false).
*/
btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape();
void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
//debugging
virtual const char* getName()const {return "HEIGHTFIELD";}
};
#endif //HEIGHTFIELD_TERRAIN_SHAPE_H

View File

@@ -1,34 +1,34 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#ifndef MATERIAL_H
#define MATERIAL_H
// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
class btMaterial
{
// public members so that materials can change due to world events
public:
btScalar m_friction;
btScalar m_restitution;
int pad[2];
btMaterial(){}
btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
};
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#ifndef MATERIAL_H
#define MATERIAL_H
// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
class btMaterial
{
// public members so that materials can change due to world events
public:
btScalar m_friction;
btScalar m_restitution;
int pad[2];
btMaterial(){}
btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
};
#endif // MATERIAL_H

View File

@@ -1,45 +1,45 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
///Obtains the material for a specific triangle
const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
{
const unsigned char * materialBase = 0;
int numMaterials;
PHY_ScalarType materialType;
int materialStride;
const unsigned char * triangleMaterialBase = 0;
int numTriangles;
int triangleMaterialStride;
PHY_ScalarType triangleType;
((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
&triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
// return the pointer to the place with the friction for the triangle
// TODO: This depends on whether it's a moving mesh or not
// BUG IN GIMPACT
//return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
return (matVal);
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
///Obtains the material for a specific triangle
const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
{
const unsigned char * materialBase = 0;
int numMaterials;
PHY_ScalarType materialType;
int materialStride;
const unsigned char * triangleMaterialBase = 0;
int numTriangles;
int triangleMaterialStride;
PHY_ScalarType triangleType;
((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
&triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
// return the pointer to the place with the friction for the triangle
// TODO: This depends on whether it's a moving mesh or not
// BUG IN GIMPACT
//return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
return (matVal);
}

View File

@@ -1,123 +1,123 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
#include "btBvhTriangleMeshShape.h"
#include "btMaterial.h"
///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
{
btAlignedObjectArray <btMaterial*> m_materialList;
int ** m_triangleMaterials;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;}
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
{
m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
{
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
i);
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
}
}
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
{
m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
{
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
i);
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
}
}
virtual ~btMultimaterialTriangleMeshShape()
{
/*
for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
{
btAlignedFree(m_materialValues[i]);
m_materialLookup[i] = NULL;
}
btAlignedFree(m_materialValues);
m_materialLookup = NULL;
*/
}
//debugging
virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
///Obtains the material for a specific triangle
const btMaterial * getMaterialProperties(int partID, int triIndex);
}
;
#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/// This file was created by Alex Silverman
#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
#include "btBvhTriangleMeshShape.h"
#include "btMaterial.h"
///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
{
btAlignedObjectArray <btMaterial*> m_materialList;
int ** m_triangleMaterials;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;}
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
{
m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
{
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
i);
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
}
}
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
{
m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
{
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
i);
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
}
}
virtual ~btMultimaterialTriangleMeshShape()
{
/*
for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
{
btAlignedFree(m_materialValues[i]);
m_materialLookup[i] = NULL;
}
btAlignedFree(m_materialValues);
m_materialLookup = NULL;
*/
}
//debugging
virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
///Obtains the material for a specific triangle
const btMaterial * getMaterialProperties(int partID, int triIndex);
}
;
#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H

View File

@@ -1,120 +1,120 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 "btScaledBvhTriangleMeshShape.h"
btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
{
m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
{
}
class btScaledTriangleCallback : public btTriangleCallback
{
btTriangleCallback* m_originalCallback;
btVector3 m_localScaling;
public:
btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
:m_originalCallback(originalCallback),
m_localScaling(localScaling)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
btVector3 newTriangle[3];
newTriangle[0] = triangle[0]*m_localScaling;
newTriangle[1] = triangle[1]*m_localScaling;
newTriangle[2] = triangle[2]*m_localScaling;
m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
}
};
void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
btScaledTriangleCallback scaledCallback(callback,m_localScaling);
btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
btVector3 scaledAabbMin,scaledAabbMax;
///support negative scaling
scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
}
void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
btScalar margin = m_bvhTriMeshShape->getMargin();
localHalfExtents += btVector3(margin,margin,margin);
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
{
return m_localScaling;
}
void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
///don't make this a movable object!
// btAssert(0);
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 "btScaledBvhTriangleMeshShape.h"
btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
{
m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
{
}
class btScaledTriangleCallback : public btTriangleCallback
{
btTriangleCallback* m_originalCallback;
btVector3 m_localScaling;
public:
btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
:m_originalCallback(originalCallback),
m_localScaling(localScaling)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
btVector3 newTriangle[3];
newTriangle[0] = triangle[0]*m_localScaling;
newTriangle[1] = triangle[1]*m_localScaling;
newTriangle[2] = triangle[2]*m_localScaling;
m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
}
};
void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
btScaledTriangleCallback scaledCallback(callback,m_localScaling);
btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
btVector3 scaledAabbMin,scaledAabbMax;
///support negative scaling
scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
}
void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
btScalar margin = m_bvhTriMeshShape->getMargin();
localHalfExtents += btVector3(margin,margin,margin);
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
{
return m_localScaling;
}
void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
///don't make this a movable object!
// btAssert(0);
}

View File

@@ -1,62 +1,62 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 SCALED_BVH_TRIANGLE_MESH_SHAPE_H
#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
{
btVector3 m_localScaling;
btBvhTriangleMeshShape* m_bvhTriMeshShape;
public:
btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
virtual ~btScaledBvhTriangleMeshShape();
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
btBvhTriangleMeshShape* getChildShape()
{
return m_bvhTriMeshShape;
}
const btBvhTriangleMeshShape* getChildShape() const
{
return m_bvhTriMeshShape;
}
//debugging
virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}
};
#endif //BVH_TRIANGLE_MESH_SHAPE_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 SCALED_BVH_TRIANGLE_MESH_SHAPE_H
#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
{
btVector3 m_localScaling;
btBvhTriangleMeshShape* m_bvhTriMeshShape;
public:
btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
virtual ~btScaledBvhTriangleMeshShape();
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
btBvhTriangleMeshShape* getChildShape()
{
return m_bvhTriMeshShape;
}
const btBvhTriangleMeshShape* getChildShape() const
{
return m_bvhTriMeshShape;
}
//debugging
virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}
};
#endif //BVH_TRIANGLE_MESH_SHAPE_H

View File

@@ -1,164 +1,164 @@
/*
btbtShapeHull implemented by John McCutchan.
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btShapeHull.h"
#include "LinearMath/btConvexHull.h"
#define NUM_UNITSPHERE_POINTS 42
static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
{
btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
};
btShapeHull::btShapeHull (const btConvexShape* shape)
{
m_shape = shape;
m_vertices.clear ();
m_indices.clear();
m_numIndices = 0;
}
btShapeHull::~btShapeHull ()
{
m_indices.clear();
m_vertices.clear ();
}
bool
btShapeHull::buildHull (btScalar /*margin*/)
{
int numSampleDirections = NUM_UNITSPHERE_POINTS;
{
int numPDA = m_shape->getNumPreferredPenetrationDirections();
if (numPDA)
{
for (int i=0;i<numPDA;i++)
{
btVector3 norm;
m_shape->getPreferredPenetrationDirection(i,norm);
btUnitSpherePoints[numSampleDirections] = norm;
numSampleDirections++;
}
}
}
btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
int i;
for (i = 0; i < numSampleDirections; i++)
{
supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]);
}
HullDesc hd;
hd.mFlags = QF_TRIANGLES;
hd.mVcount = static_cast<unsigned int>(numSampleDirections);
#ifdef BT_USE_DOUBLE_PRECISION
hd.mVertices = &supportPoints[0];
hd.mVertexStride = sizeof(btVector3);
#else
hd.mVertices = &supportPoints[0];
hd.mVertexStride = sizeof (btVector3);
#endif
HullLibrary hl;
HullResult hr;
if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
{
return false;
}
m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
{
m_vertices[i] = hr.m_OutputVertices[i];
}
m_numIndices = hr.mNumIndices;
m_indices.resize(static_cast<int>(m_numIndices));
for (i = 0; i < static_cast<int>(m_numIndices); i++)
{
m_indices[i] = hr.m_Indices[i];
}
// free temporary hull result that we just copied
hl.ReleaseResult (hr);
return true;
}
int
btShapeHull::numTriangles () const
{
return static_cast<int>(m_numIndices / 3);
}
int
btShapeHull::numVertices () const
{
return m_vertices.size ();
}
int
btShapeHull::numIndices () const
{
return static_cast<int>(m_numIndices);
}
/*
btbtShapeHull implemented by John McCutchan.
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "btShapeHull.h"
#include "LinearMath/btConvexHull.h"
#define NUM_UNITSPHERE_POINTS 42
static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
{
btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
};
btShapeHull::btShapeHull (const btConvexShape* shape)
{
m_shape = shape;
m_vertices.clear ();
m_indices.clear();
m_numIndices = 0;
}
btShapeHull::~btShapeHull ()
{
m_indices.clear();
m_vertices.clear ();
}
bool
btShapeHull::buildHull (btScalar /*margin*/)
{
int numSampleDirections = NUM_UNITSPHERE_POINTS;
{
int numPDA = m_shape->getNumPreferredPenetrationDirections();
if (numPDA)
{
for (int i=0;i<numPDA;i++)
{
btVector3 norm;
m_shape->getPreferredPenetrationDirection(i,norm);
btUnitSpherePoints[numSampleDirections] = norm;
numSampleDirections++;
}
}
}
btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
int i;
for (i = 0; i < numSampleDirections; i++)
{
supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]);
}
HullDesc hd;
hd.mFlags = QF_TRIANGLES;
hd.mVcount = static_cast<unsigned int>(numSampleDirections);
#ifdef BT_USE_DOUBLE_PRECISION
hd.mVertices = &supportPoints[0];
hd.mVertexStride = sizeof(btVector3);
#else
hd.mVertices = &supportPoints[0];
hd.mVertexStride = sizeof (btVector3);
#endif
HullLibrary hl;
HullResult hr;
if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
{
return false;
}
m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
{
m_vertices[i] = hr.m_OutputVertices[i];
}
m_numIndices = hr.mNumIndices;
m_indices.resize(static_cast<int>(m_numIndices));
for (i = 0; i < static_cast<int>(m_numIndices); i++)
{
m_indices[i] = hr.m_Indices[i];
}
// free temporary hull result that we just copied
hl.ReleaseResult (hr);
return true;
}
int
btShapeHull::numTriangles () const
{
return static_cast<int>(m_numIndices / 3);
}
int
btShapeHull::numVertices () const
{
return m_vertices.size ();
}
int
btShapeHull::numIndices () const
{
return static_cast<int>(m_numIndices);
}

View File

@@ -1,56 +1,56 @@
/*
btShapeHull implemented by John McCutchan.
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 _SHAPE_HULL_H
#define _SHAPE_HULL_H
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
///It approximates the convex hull using the supporting vertex of 42 directions.
class btShapeHull
{
public:
btShapeHull (const btConvexShape* shape);
~btShapeHull ();
bool buildHull (btScalar margin);
int numTriangles () const;
int numVertices () const;
int numIndices () const;
const btVector3* getVertexPointer() const
{
return &m_vertices[0];
}
const unsigned int* getIndexPointer() const
{
return &m_indices[0];
}
protected:
btAlignedObjectArray<btVector3> m_vertices;
btAlignedObjectArray<unsigned int> m_indices;
unsigned int m_numIndices;
const btConvexShape* m_shape;
};
#endif //_SHAPE_HULL_H
/*
btShapeHull implemented by John McCutchan.
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 _SHAPE_HULL_H
#define _SHAPE_HULL_H
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
///It approximates the convex hull using the supporting vertex of 42 directions.
class btShapeHull
{
public:
btShapeHull (const btConvexShape* shape);
~btShapeHull ();
bool buildHull (btScalar margin);
int numTriangles () const;
int numVertices () const;
int numIndices () const;
const btVector3* getVertexPointer() const
{
return &m_vertices[0];
}
const unsigned int* getIndexPointer() const
{
return &m_indices[0];
}
protected:
btAlignedObjectArray<btVector3> m_vertices;
btAlignedObjectArray<unsigned int> m_indices;
unsigned int m_numIndices;
const btConvexShape* m_shape;
};
#endif //_SHAPE_HULL_H

View File

@@ -1,35 +1,35 @@
/*
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 "btTriangleBuffer.h"
void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int triangleIndex)
{
btTriangle tri;
tri.m_vertex0 = triangle[0];
tri.m_vertex1 = triangle[1];
tri.m_vertex2 = triangle[2];
tri.m_partId = partId;
tri.m_triangleIndex = triangleIndex;
m_triangleBuffer.push_back(tri);
}
/*
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 "btTriangleBuffer.h"
void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int triangleIndex)
{
btTriangle tri;
tri.m_vertex0 = triangle[0];
tri.m_vertex1 = triangle[1];
tri.m_vertex2 = triangle[2];
tri.m_partId = partId;
tri.m_triangleIndex = triangleIndex;
m_triangleBuffer.push_back(tri);
}

View File

@@ -1,69 +1,69 @@
/*
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_TRIANGLE_BUFFER_H
#define BT_TRIANGLE_BUFFER_H
#include "btTriangleCallback.h"
#include "LinearMath/btAlignedObjectArray.h"
struct btTriangle
{
btVector3 m_vertex0;
btVector3 m_vertex1;
btVector3 m_vertex2;
int m_partId;
int m_triangleIndex;
};
///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
///Example usage of this class:
/// btTriangleBuffer triBuf;
/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
/// for (int i=0;i<triBuf.getNumTriangles();i++)
/// {
/// const btTriangle& tri = triBuf.getTriangle(i);
/// //do something useful here with the triangle
/// }
class btTriangleBuffer : public btTriangleCallback
{
btAlignedObjectArray<btTriangle> m_triangleBuffer;
public:
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
int getNumTriangles() const
{
return int(m_triangleBuffer.size());
}
const btTriangle& getTriangle(int index) const
{
return m_triangleBuffer[index];
}
void clearBuffer()
{
m_triangleBuffer.clear();
}
};
#endif //BT_TRIANGLE_BUFFER_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.
*/
#ifndef BT_TRIANGLE_BUFFER_H
#define BT_TRIANGLE_BUFFER_H
#include "btTriangleCallback.h"
#include "LinearMath/btAlignedObjectArray.h"
struct btTriangle
{
btVector3 m_vertex0;
btVector3 m_vertex1;
btVector3 m_vertex2;
int m_partId;
int m_triangleIndex;
};
///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
///Example usage of this class:
/// btTriangleBuffer triBuf;
/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
/// for (int i=0;i<triBuf.getNumTriangles();i++)
/// {
/// const btTriangle& tri = triBuf.getTriangle(i);
/// //do something useful here with the triangle
/// }
class btTriangleBuffer : public btTriangleCallback
{
btAlignedObjectArray<btTriangle> m_triangleBuffer;
public:
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
int getNumTriangles() const
{
return int(m_triangleBuffer.size());
}
const btTriangle& getTriangle(int index) const
{
return m_triangleBuffer[index];
}
void clearBuffer()
{
m_triangleBuffer.clear();
}
};
#endif //BT_TRIANGLE_BUFFER_H

View File

@@ -82,6 +82,7 @@ bool btTriangleIndexVertexArray::hasPremadeAabb() const
return (m_hasAabb == 1);
}
void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
{
m_aabbMin = aabbMin;

View File

@@ -1,86 +1,87 @@
/*
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.
*/
///This file was created by Alex Silverman
#include "btTriangleIndexVertexMaterialArray.h"
btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
int numVertices,btScalar* vertexBase,int vertexStride,
int numMaterials, unsigned char* materialBase, int materialStride,
int* triangleMaterialsBase, int materialIndexStride) :
btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
{
btMaterialProperties mat;
mat.m_numMaterials = numMaterials;
mat.m_materialBase = materialBase;
mat.m_materialStride = materialStride;
#ifdef BT_USE_DOUBLE_PRECISION
mat.m_materialType = PHY_DOUBLE;
#else
mat.m_materialType = PHY_FLOAT;
#endif
mat.m_numTriangles = numTriangles;
mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
mat.m_triangleMaterialStride = materialIndexStride;
mat.m_triangleType = PHY_INTEGER;
addMaterialProperties(mat);
}
void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
btAssert(subpart< getNumSubParts() );
btMaterialProperties& mats = m_materials[subpart];
numMaterials = mats.m_numMaterials;
(*materialBase) = (unsigned char *) mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
materialType = PHY_DOUBLE;
#else
materialType = PHY_FLOAT;
#endif
materialStride = mats.m_materialStride;
numTriangles = mats.m_numTriangles;
(*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
triangleMaterialStride = mats.m_triangleMaterialStride;
triangleType = mats.m_triangleType;
}
void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
btMaterialProperties& mats = m_materials[subpart];
numMaterials = mats.m_numMaterials;
(*materialBase) = (const unsigned char *) mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
materialType = PHY_DOUBLE;
#else
materialType = PHY_FLOAT;
#endif
materialStride = mats.m_materialStride;
numTriangles = mats.m_numTriangles;
(*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
triangleMaterialStride = mats.m_triangleMaterialStride;
triangleType = mats.m_triangleType;
}
/*
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.
*/
///This file was created by Alex Silverman
#include "btTriangleIndexVertexMaterialArray.h"
btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
int numVertices,btScalar* vertexBase,int vertexStride,
int numMaterials, unsigned char* materialBase, int materialStride,
int* triangleMaterialsBase, int materialIndexStride) :
btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
{
btMaterialProperties mat;
mat.m_numMaterials = numMaterials;
mat.m_materialBase = materialBase;
mat.m_materialStride = materialStride;
#ifdef BT_USE_DOUBLE_PRECISION
mat.m_materialType = PHY_DOUBLE;
#else
mat.m_materialType = PHY_FLOAT;
#endif
mat.m_numTriangles = numTriangles;
mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
mat.m_triangleMaterialStride = materialIndexStride;
mat.m_triangleType = PHY_INTEGER;
addMaterialProperties(mat);
}
void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
btAssert(subpart< getNumSubParts() );
btMaterialProperties& mats = m_materials[subpart];
numMaterials = mats.m_numMaterials;
(*materialBase) = (unsigned char *) mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
materialType = PHY_DOUBLE;
#else
materialType = PHY_FLOAT;
#endif
materialStride = mats.m_materialStride;
numTriangles = mats.m_numTriangles;
(*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
triangleMaterialStride = mats.m_triangleMaterialStride;
triangleType = mats.m_triangleType;
}
void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
{
btMaterialProperties& mats = m_materials[subpart];
numMaterials = mats.m_numMaterials;
(*materialBase) = (const unsigned char *) mats.m_materialBase;
#ifdef BT_USE_DOUBLE_PRECISION
materialType = PHY_DOUBLE;
#else
materialType = PHY_FLOAT;
#endif
materialStride = mats.m_materialStride;
numTriangles = mats.m_numTriangles;
(*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
triangleMaterialStride = mats.m_triangleMaterialStride;
triangleType = mats.m_triangleType;
}

View File

@@ -1,84 +1,84 @@
/*
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.
*/
///This file was created by Alex Silverman
#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
#include "btTriangleIndexVertexArray.h"
ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
{
///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
int m_numMaterials;
const unsigned char * m_materialBase;
int m_materialStride;
PHY_ScalarType m_materialType;
///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
/// padding the structure, it can be reproduced at no real cost
///m_triangleMaterials =====> 1 integer value makes up one entry
/// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
int m_numTriangles;
const unsigned char * m_triangleMaterialsBase;
int m_triangleMaterialStride;
///m_triangleType <========== Automatically set in addMaterialProperties
PHY_ScalarType m_triangleType;
};
typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
///The addition of a material array allows for the utilization of the partID and
///triangleIndex that are returned in the ContactAddedCallback. As with
///TriangleIndexVertexArray, no duplicate is made of the material data, so it
///is the users responsibility to maintain the array during the lifetime of the
///TriangleIndexVertexMaterialArray.
ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
{
protected:
MaterialArray m_materials;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btTriangleIndexVertexMaterialArray()
{
}
btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
int numVertices,btScalar* vertexBase,int vertexStride,
int numMaterials, unsigned char* materialBase, int materialStride,
int* triangleMaterialsBase, int materialIndexStride);
virtual ~btTriangleIndexVertexMaterialArray() {}
void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
{
m_materials.push_back(mat);
m_materials[m_materials.size()-1].m_triangleType = triangleType;
}
virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
}
;
#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_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.
*/
///This file was created by Alex Silverman
#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
#include "btTriangleIndexVertexArray.h"
ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
{
///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
int m_numMaterials;
const unsigned char * m_materialBase;
int m_materialStride;
PHY_ScalarType m_materialType;
///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
/// padding the structure, it can be reproduced at no real cost
///m_triangleMaterials =====> 1 integer value makes up one entry
/// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
int m_numTriangles;
const unsigned char * m_triangleMaterialsBase;
int m_triangleMaterialStride;
///m_triangleType <========== Automatically set in addMaterialProperties
PHY_ScalarType m_triangleType;
};
typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
///The addition of a material array allows for the utilization of the partID and
///triangleIndex that are returned in the ContactAddedCallback. As with
///TriangleIndexVertexArray, no duplicate is made of the material data, so it
///is the users responsibility to maintain the array during the lifetime of the
///TriangleIndexVertexMaterialArray.
ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
{
protected:
MaterialArray m_materials;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btTriangleIndexVertexMaterialArray()
{
}
btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
int numVertices,btScalar* vertexBase,int vertexStride,
int numMaterials, unsigned char* materialBase, int materialStride,
int* triangleMaterialsBase, int materialIndexStride);
virtual ~btTriangleIndexVertexMaterialArray() {}
void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
{
m_materials.push_back(mat);
m_materials[m_materials.size()-1].m_triangleType = triangleType;
}
virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
}
;
#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,71 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/*
GJK-EPA collision solver by Nathanael Presson, 2008
*/
#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
#include "BulletCollision/CollisionShapes/btConvexShape.h"
///btGjkEpaSolver contributed under zlib by Nathanael Presson
struct btGjkEpaSolver2
{
struct sResults
{
enum eStatus
{
Separated, /* Shapes doesnt penetrate */
Penetrating, /* Shapes are penetrating */
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
} status;
btVector3 witnesses[2];
btVector3 normal;
btScalar distance;
};
static int StackSizeRequirement();
static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results);
static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results,
bool usemargins=true);
static btScalar SignedDistance( const btVector3& position,
btScalar margin,
const btConvexShape* shape,
const btTransform& wtrs,
sResults& results);
static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results);
};
#endif
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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.
*/
/*
GJK-EPA collision solver by Nathanael Presson, 2008
*/
#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
#include "BulletCollision/CollisionShapes/btConvexShape.h"
///btGjkEpaSolver contributed under zlib by Nathanael Presson
struct btGjkEpaSolver2
{
struct sResults
{
enum eStatus
{
Separated, /* Shapes doesnt penetrate */
Penetrating, /* Shapes are penetrating */
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
} status;
btVector3 witnesses[2];
btVector3 normal;
btScalar distance;
};
static int StackSizeRequirement();
static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results);
static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results,
bool usemargins=true);
static btScalar SignedDistance( const btVector3& position,
btScalar margin,
const btConvexShape* shape,
const btTransform& wtrs,
sResults& results);
static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
const btConvexShape* shape1,const btTransform& wtrs1,
const btVector3& guess,
sResults& results);
};
#endif

View File

@@ -1,54 +1,54 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
EPA Copyright (c) Ricardo Padrela 2006
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 "BulletCollision/CollisionShapes/btConvexShape.h"
#include "btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
const btTransform& transformA, const btTransform& transformB,
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc )
{
(void)debugDraw;
(void)v;
(void)simplexSolver;
const btScalar radialmargin(btScalar(0.));
btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin());
btGjkEpaSolver2::sResults results;
if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
pConvexB,transformB,
guessVector,results))
{
// debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
wWitnessOnA = results.witnesses[0];
wWitnessOnB = results.witnesses[1];
return true;
}
return false;
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
EPA Copyright (c) Ricardo Padrela 2006
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 "BulletCollision/CollisionShapes/btConvexShape.h"
#include "btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
const btTransform& transformA, const btTransform& transformB,
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc )
{
(void)debugDraw;
(void)v;
(void)simplexSolver;
const btScalar radialmargin(btScalar(0.));
btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin());
btGjkEpaSolver2::sResults results;
if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
pConvexB,transformB,
guessVector,results))
{
// debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
wWitnessOnA = results.witnesses[0];
wWitnessOnB = results.witnesses[1];
return true;
}
return false;
}

View File

@@ -1,43 +1,43 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 CHARACTER_CONTROLLER_INTERFACE_H
#define CHARACTER_CONTROLLER_INTERFACE_H
#include "LinearMath/btVector3.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCharacterControllerInterface
{
public:
btCharacterControllerInterface () {};
virtual ~btCharacterControllerInterface () {};
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0;
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
virtual bool canJump () const = 0;
virtual void jump () = 0;
virtual bool onGround () const = 0;
};
#endif
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 CHARACTER_CONTROLLER_INTERFACE_H
#define CHARACTER_CONTROLLER_INTERFACE_H
#include "LinearMath/btVector3.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCharacterControllerInterface
{
public:
btCharacterControllerInterface () {};
virtual ~btCharacterControllerInterface () {};
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0;
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
virtual bool canJump () const = 0;
virtual void jump () = 0;
virtual bool onGround () const = 0;
};
#endif

View File

@@ -1,471 +1,471 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "LinearMath/btDefaultMotionState.h"
#include "btKinematicCharacterController.h"
static btVector3 upAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly
///More realistic (or maybe just a config option) falling
/// -> Should integrate falling velocity manually and use that in stepDown()
///Support jumping
///Support ducking
class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
public:
btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_me)
return 1.0;
return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
};
class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{
public:
btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
{
if (convexResult.m_hitCollisionObject == m_me)
return 1.0;
return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
};
/*
* Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
*
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
*/
btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
{
return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
}
/*
* Returns the portion of 'direction' that is parallel to 'normal'
*/
btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
{
btScalar magnitude = direction.dot(normal);
return normal * magnitude;
}
/*
* Returns the portion of 'direction' that is perpindicular to 'normal'
*/
btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
{
return direction - parallelComponent(direction, normal);
}
btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis)
{
m_upAxis = upAxis;
m_addedMargin = 0.02f;
m_walkDirection.setValue(0,0,0);
m_useGhostObjectSweepTest = true;
m_ghostObject = ghostObject;
m_stepHeight = stepHeight;
m_turnAngle = btScalar(0.0);
m_convexShape=convexShape;
}
btKinematicCharacterController::~btKinematicCharacterController ()
{
}
btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
{
return m_ghostObject;
}
bool btKinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld)
{
bool penetration = false;
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
btScalar maxPen = btScalar(0.0);
for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
{
m_manifoldArray.resize(0);
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
for (int j=0;j<m_manifoldArray.size();j++)
{
btPersistentManifold* manifold = m_manifoldArray[j];
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
for (int p=0;p<manifold->getNumContacts();p++)
{
const btManifoldPoint&pt = manifold->getContactPoint(p);
if (pt.getDistance() < 0.0)
{
if (pt.getDistance() < maxPen)
{
maxPen = pt.getDistance();
m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
}
m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2);
penetration = true;
} else {
//printf("touching %f\n", pt.getDistance());
}
}
//manifold->clearManifold();
}
}
btTransform newTrans = m_ghostObject->getWorldTransform();
newTrans.setOrigin(m_currentPosition);
m_ghostObject->setWorldTransform(newTrans);
// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
return penetration;
}
void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
{
// phase 1: up
btTransform start, end;
m_targetPosition = m_currentPosition + upAxisDirection[m_upAxis] * m_stepHeight;
start.setIdentity ();
end.setIdentity ();
/* FIXME: Handle penetration properly */
start.setOrigin (m_currentPosition + upAxisDirection[m_upAxis] * btScalar(0.1f));
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
}
else
{
world->convexSweepTest (m_convexShape, start, end, callback);
}
if (callback.hasHit())
{
// we moved up only a fraction of the step height
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
} else {
m_currentStepOffset = m_stepHeight;
m_currentPosition = m_targetPosition;
}
}
void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
{
btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length();
if (movementLength>SIMD_EPSILON)
{
movementDirection.normalize();
btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
parallelDir = parallelComponent (reflectDir, hitNormal);
perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
if (0)//tangentMag != 0.0)
{
btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
m_targetPosition += parComponent;
}
if (normalMag != 0.0)
{
btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
m_targetPosition += perpComponent;
}
} else
{
// printf("movementLength don't normalize a zero vector\n");
}
}
void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
{
btVector3 originalDir = walkMove.normalized();
if (walkMove.length() < SIMD_EPSILON)
{
originalDir.setValue(0.f,0.f,0.f);
}
// printf("originalDir=%f,%f,%f\n",originalDir[0],originalDir[1],originalDir[2]);
// phase 2: forward and strafe
btTransform start, end;
m_targetPosition = m_currentPosition + walkMove;
start.setIdentity ();
end.setIdentity ();
btScalar fraction = 1.0;
btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
// printf("distance2=%f\n",distance2);
if (m_touchingContact)
{
if (originalDir.dot(m_touchingNormal) > btScalar(0.0))
updateTargetPositionBasedOnCollision (m_touchingNormal);
}
int maxIter = 10;
while (fraction > btScalar(0.01) && maxIter-- > 0)
{
start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
btScalar margin = m_convexShape->getMargin();
m_convexShape->setMargin(margin + m_addedMargin);
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
} else
{
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
m_convexShape->setMargin(margin);
fraction -= callback.m_closestHitFraction;
if (callback.hasHit())
{
// we moved only a fraction
btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
if (hitDistance<0.f)
{
// printf("neg dist?\n");
}
/* If the distance is farther than the collision margin, move */
if (hitDistance > m_addedMargin)
{
// printf("callback.m_closestHitFraction=%f\n",callback.m_closestHitFraction);
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
}
updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
btVector3 currentDir = m_targetPosition - m_currentPosition;
distance2 = currentDir.length2();
if (distance2 > SIMD_EPSILON)
{
currentDir.normalize();
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(originalDir) <= btScalar(0.0))
{
break;
}
} else
{
// printf("currentDir: don't normalize a zero vector\n");
break;
}
} else {
// we moved whole way
m_currentPosition = m_targetPosition;
}
// if (callback.m_closestHitFraction == 0.f)
// break;
}
}
void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform start, end;
// phase 3: down
btVector3 step_drop = upAxisDirection[m_upAxis] * m_currentStepOffset;
btVector3 gravity_drop = upAxisDirection[m_upAxis] * m_stepHeight;
m_targetPosition -= (step_drop + gravity_drop);
start.setIdentity ();
end.setIdentity ();
start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
} else
{
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
if (callback.hasHit())
{
// we dropped a fraction of the height -> hit floor
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
} else {
// we dropped the full height
m_currentPosition = m_targetPosition;
}
}
void btKinematicCharacterController::reset ()
{
}
void btKinematicCharacterController::warp (const btVector3& origin)
{
btTransform xform;
xform.setIdentity();
xform.setOrigin (origin);
m_ghostObject->setWorldTransform (xform);
}
void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
{
int numPenetrationLoops = 0;
m_touchingContact = false;
while (recoverFromPenetration (collisionWorld))
{
numPenetrationLoops++;
m_touchingContact = true;
if (numPenetrationLoops > 4)
{
// printf("character could not recover from penetration = %d\n", numPenetrationLoops);
break;
}
}
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
m_targetPosition = m_currentPosition;
// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
}
void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
// printf("walkSpeed=%f\n",walkSpeed);
stepUp (collisionWorld);
stepForwardAndStrafe (collisionWorld, m_walkDirection);
stepDown (collisionWorld, dt);
xform.setOrigin (m_currentPosition);
m_ghostObject->setWorldTransform (xform);
}
void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
{
m_fallSpeed = fallSpeed;
}
void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
{
m_jumpSpeed = jumpSpeed;
}
void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
{
m_maxJumpHeight = maxJumpHeight;
}
bool btKinematicCharacterController::canJump () const
{
return onGround();
}
void btKinematicCharacterController::jump ()
{
if (!canJump())
return;
#if 0
currently no jumping.
btTransform xform;
m_rigidBody->getMotionState()->getWorldTransform (xform);
btVector3 up = xform.getBasis()[1];
up.normalize ();
btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
m_rigidBody->applyCentralImpulse (up * magnitude);
#endif
}
bool btKinematicCharacterController::onGround () const
{
return true;
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "LinearMath/btDefaultMotionState.h"
#include "btKinematicCharacterController.h"
static btVector3 upAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly
///More realistic (or maybe just a config option) falling
/// -> Should integrate falling velocity manually and use that in stepDown()
///Support jumping
///Support ducking
class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
public:
btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_me)
return 1.0;
return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
};
class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{
public:
btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
{
if (convexResult.m_hitCollisionObject == m_me)
return 1.0;
return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
};
/*
* Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
*
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
*/
btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
{
return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
}
/*
* Returns the portion of 'direction' that is parallel to 'normal'
*/
btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
{
btScalar magnitude = direction.dot(normal);
return normal * magnitude;
}
/*
* Returns the portion of 'direction' that is perpindicular to 'normal'
*/
btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
{
return direction - parallelComponent(direction, normal);
}
btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis)
{
m_upAxis = upAxis;
m_addedMargin = 0.02f;
m_walkDirection.setValue(0,0,0);
m_useGhostObjectSweepTest = true;
m_ghostObject = ghostObject;
m_stepHeight = stepHeight;
m_turnAngle = btScalar(0.0);
m_convexShape=convexShape;
}
btKinematicCharacterController::~btKinematicCharacterController ()
{
}
btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
{
return m_ghostObject;
}
bool btKinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld)
{
bool penetration = false;
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
btScalar maxPen = btScalar(0.0);
for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
{
m_manifoldArray.resize(0);
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
for (int j=0;j<m_manifoldArray.size();j++)
{
btPersistentManifold* manifold = m_manifoldArray[j];
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
for (int p=0;p<manifold->getNumContacts();p++)
{
const btManifoldPoint&pt = manifold->getContactPoint(p);
if (pt.getDistance() < 0.0)
{
if (pt.getDistance() < maxPen)
{
maxPen = pt.getDistance();
m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
}
m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2);
penetration = true;
} else {
//printf("touching %f\n", pt.getDistance());
}
}
//manifold->clearManifold();
}
}
btTransform newTrans = m_ghostObject->getWorldTransform();
newTrans.setOrigin(m_currentPosition);
m_ghostObject->setWorldTransform(newTrans);
// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
return penetration;
}
void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
{
// phase 1: up
btTransform start, end;
m_targetPosition = m_currentPosition + upAxisDirection[m_upAxis] * m_stepHeight;
start.setIdentity ();
end.setIdentity ();
/* FIXME: Handle penetration properly */
start.setOrigin (m_currentPosition + upAxisDirection[m_upAxis] * btScalar(0.1f));
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
}
else
{
world->convexSweepTest (m_convexShape, start, end, callback);
}
if (callback.hasHit())
{
// we moved up only a fraction of the step height
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
} else {
m_currentStepOffset = m_stepHeight;
m_currentPosition = m_targetPosition;
}
}
void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
{
btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length();
if (movementLength>SIMD_EPSILON)
{
movementDirection.normalize();
btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
parallelDir = parallelComponent (reflectDir, hitNormal);
perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
if (0)//tangentMag != 0.0)
{
btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
m_targetPosition += parComponent;
}
if (normalMag != 0.0)
{
btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
m_targetPosition += perpComponent;
}
} else
{
// printf("movementLength don't normalize a zero vector\n");
}
}
void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
{
btVector3 originalDir = walkMove.normalized();
if (walkMove.length() < SIMD_EPSILON)
{
originalDir.setValue(0.f,0.f,0.f);
}
// printf("originalDir=%f,%f,%f\n",originalDir[0],originalDir[1],originalDir[2]);
// phase 2: forward and strafe
btTransform start, end;
m_targetPosition = m_currentPosition + walkMove;
start.setIdentity ();
end.setIdentity ();
btScalar fraction = 1.0;
btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
// printf("distance2=%f\n",distance2);
if (m_touchingContact)
{
if (originalDir.dot(m_touchingNormal) > btScalar(0.0))
updateTargetPositionBasedOnCollision (m_touchingNormal);
}
int maxIter = 10;
while (fraction > btScalar(0.01) && maxIter-- > 0)
{
start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
btScalar margin = m_convexShape->getMargin();
m_convexShape->setMargin(margin + m_addedMargin);
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
} else
{
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
m_convexShape->setMargin(margin);
fraction -= callback.m_closestHitFraction;
if (callback.hasHit())
{
// we moved only a fraction
btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
if (hitDistance<0.f)
{
// printf("neg dist?\n");
}
/* If the distance is farther than the collision margin, move */
if (hitDistance > m_addedMargin)
{
// printf("callback.m_closestHitFraction=%f\n",callback.m_closestHitFraction);
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
}
updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
btVector3 currentDir = m_targetPosition - m_currentPosition;
distance2 = currentDir.length2();
if (distance2 > SIMD_EPSILON)
{
currentDir.normalize();
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(originalDir) <= btScalar(0.0))
{
break;
}
} else
{
// printf("currentDir: don't normalize a zero vector\n");
break;
}
} else {
// we moved whole way
m_currentPosition = m_targetPosition;
}
// if (callback.m_closestHitFraction == 0.f)
// break;
}
}
void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform start, end;
// phase 3: down
btVector3 step_drop = upAxisDirection[m_upAxis] * m_currentStepOffset;
btVector3 gravity_drop = upAxisDirection[m_upAxis] * m_stepHeight;
m_targetPosition -= (step_drop + gravity_drop);
start.setIdentity ();
end.setIdentity ();
start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
} else
{
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
if (callback.hasHit())
{
// we dropped a fraction of the height -> hit floor
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
} else {
// we dropped the full height
m_currentPosition = m_targetPosition;
}
}
void btKinematicCharacterController::reset ()
{
}
void btKinematicCharacterController::warp (const btVector3& origin)
{
btTransform xform;
xform.setIdentity();
xform.setOrigin (origin);
m_ghostObject->setWorldTransform (xform);
}
void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
{
int numPenetrationLoops = 0;
m_touchingContact = false;
while (recoverFromPenetration (collisionWorld))
{
numPenetrationLoops++;
m_touchingContact = true;
if (numPenetrationLoops > 4)
{
// printf("character could not recover from penetration = %d\n", numPenetrationLoops);
break;
}
}
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
m_targetPosition = m_currentPosition;
// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
}
void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
// printf("walkSpeed=%f\n",walkSpeed);
stepUp (collisionWorld);
stepForwardAndStrafe (collisionWorld, m_walkDirection);
stepDown (collisionWorld, dt);
xform.setOrigin (m_currentPosition);
m_ghostObject->setWorldTransform (xform);
}
void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
{
m_fallSpeed = fallSpeed;
}
void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
{
m_jumpSpeed = jumpSpeed;
}
void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
{
m_maxJumpHeight = maxJumpHeight;
}
bool btKinematicCharacterController::canJump () const
{
return onGround();
}
void btKinematicCharacterController::jump ()
{
if (!canJump())
return;
#if 0
currently no jumping.
btTransform xform;
m_rigidBody->getMotionState()->getWorldTransform (xform);
btVector3 up = xform.getBasis()[1];
up.normalize ();
btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
m_rigidBody->applyCentralImpulse (up * magnitude);
#endif
}
bool btKinematicCharacterController::onGround () const
{
return true;
}

View File

@@ -1,116 +1,116 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 KINEMATIC_CHARACTER_CONTROLLER_H
#define KINEMATIC_CHARACTER_CONTROLLER_H
#include "LinearMath/btVector3.h"
#include "btCharacterControllerInterface.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCollisionDispatcher;
class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
class btKinematicCharacterController : public btCharacterControllerInterface
{
protected:
btScalar m_halfHeight;
btPairCachingGhostObject* m_ghostObject;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_fallSpeed;
btScalar m_jumpSpeed;
btScalar m_maxJumpHeight;
btScalar m_turnAngle;
btScalar m_stepHeight;
btScalar m_addedMargin;//@todo: remove this and fix the code
///this is the desired walk direction, set by the user
btVector3 m_walkDirection;
//some internal variables
btVector3 m_currentPosition;
btScalar m_currentStepOffset;
btVector3 m_targetPosition;
///keep track of the contact manifolds
btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
bool m_useGhostObjectSweepTest;
int m_upAxis;
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
bool recoverFromPenetration (btCollisionWorld* collisionWorld);
void stepUp (btCollisionWorld* collisionWorld);
void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
public:
btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1);
~btKinematicCharacterController ();
void setUpAxis (int axis)
{
if (axis < 0)
axis = 0;
if (axis > 2)
axis = 2;
m_upAxis = axis;
}
virtual void setWalkDirection(const btVector3& walkDirection)
{
m_walkDirection = walkDirection;
}
void reset ();
void warp (const btVector3& origin);
void preStep ( btCollisionWorld* collisionWorld);
void playerStep (btCollisionWorld* collisionWorld, btScalar dt);
void setFallSpeed (btScalar fallSpeed);
void setJumpSpeed (btScalar jumpSpeed);
void setMaxJumpHeight (btScalar maxJumpHeight);
bool canJump () const;
void jump ();
btPairCachingGhostObject* getGhostObject();
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
bool onGround () const;
};
#endif // KINEMATIC_CHARACTER_CONTROLLER_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
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 KINEMATIC_CHARACTER_CONTROLLER_H
#define KINEMATIC_CHARACTER_CONTROLLER_H
#include "LinearMath/btVector3.h"
#include "btCharacterControllerInterface.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCollisionDispatcher;
class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
class btKinematicCharacterController : public btCharacterControllerInterface
{
protected:
btScalar m_halfHeight;
btPairCachingGhostObject* m_ghostObject;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_fallSpeed;
btScalar m_jumpSpeed;
btScalar m_maxJumpHeight;
btScalar m_turnAngle;
btScalar m_stepHeight;
btScalar m_addedMargin;//@todo: remove this and fix the code
///this is the desired walk direction, set by the user
btVector3 m_walkDirection;
//some internal variables
btVector3 m_currentPosition;
btScalar m_currentStepOffset;
btVector3 m_targetPosition;
///keep track of the contact manifolds
btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
bool m_useGhostObjectSweepTest;
int m_upAxis;
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
bool recoverFromPenetration (btCollisionWorld* collisionWorld);
void stepUp (btCollisionWorld* collisionWorld);
void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
public:
btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1);
~btKinematicCharacterController ();
void setUpAxis (int axis)
{
if (axis < 0)
axis = 0;
if (axis > 2)
axis = 2;
m_upAxis = axis;
}
virtual void setWalkDirection(const btVector3& walkDirection)
{
m_walkDirection = walkDirection;
}
void reset ();
void warp (const btVector3& origin);
void preStep ( btCollisionWorld* collisionWorld);
void playerStep (btCollisionWorld* collisionWorld, btScalar dt);
void setFallSpeed (btScalar fallSpeed);
void setJumpSpeed (btScalar jumpSpeed);
void setMaxJumpHeight (btScalar maxJumpHeight);
bool canJump () const;
void jump ();
btPairCachingGhostObject* getGhostObject();
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
bool onGround () const;
};
#endif // KINEMATIC_CHARACTER_CONTROLLER_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,229 +1,229 @@
/*
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.
*/
/*
Added by Roman Ponomarev (rponom@gmail.com)
April 04, 2008
TODO:
- add clamping od accumulated impulse to improve stability
- add conversion for ODE constraint solver
*/
#ifndef SLIDER_CONSTRAINT_H
#define SLIDER_CONSTRAINT_H
//-----------------------------------------------------------------------------
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
#include "btTypedConstraint.h"
//-----------------------------------------------------------------------------
class btRigidBody;
//-----------------------------------------------------------------------------
#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
//-----------------------------------------------------------------------------
class btSliderConstraint : public btTypedConstraint
{
protected:
///for backwards compatibility during the transition to 'getInfo/getInfo2'
bool m_useSolveConstraintObsolete;
btTransform m_frameInA;
btTransform m_frameInB;
// use frameA fo define limits, if true
bool m_useLinearReferenceFrameA;
// linear limits
btScalar m_lowerLinLimit;
btScalar m_upperLinLimit;
// angular limits
btScalar m_lowerAngLimit;
btScalar m_upperAngLimit;
// softness, restitution and damping for different cases
// DirLin - moving inside linear limits
// LimLin - hitting linear limit
// DirAng - moving inside angular limits
// LimAng - hitting angular limit
// OrthoLin, OrthoAng - against constraint axis
btScalar m_softnessDirLin;
btScalar m_restitutionDirLin;
btScalar m_dampingDirLin;
btScalar m_softnessDirAng;
btScalar m_restitutionDirAng;
btScalar m_dampingDirAng;
btScalar m_softnessLimLin;
btScalar m_restitutionLimLin;
btScalar m_dampingLimLin;
btScalar m_softnessLimAng;
btScalar m_restitutionLimAng;
btScalar m_dampingLimAng;
btScalar m_softnessOrthoLin;
btScalar m_restitutionOrthoLin;
btScalar m_dampingOrthoLin;
btScalar m_softnessOrthoAng;
btScalar m_restitutionOrthoAng;
btScalar m_dampingOrthoAng;
// for interlal use
bool m_solveLinLim;
bool m_solveAngLim;
btJacobianEntry m_jacLin[3];
btScalar m_jacLinDiagABInv[3];
btJacobianEntry m_jacAng[3];
btScalar m_timeStep;
btTransform m_calculatedTransformA;
btTransform m_calculatedTransformB;
btVector3 m_sliderAxis;
btVector3 m_realPivotAInW;
btVector3 m_realPivotBInW;
btVector3 m_projPivotInW;
btVector3 m_delta;
btVector3 m_depth;
btVector3 m_relPosA;
btVector3 m_relPosB;
btScalar m_linPos;
btScalar m_angPos;
btScalar m_angDepth;
btScalar m_kAngle;
bool m_poweredLinMotor;
btScalar m_targetLinMotorVelocity;
btScalar m_maxLinMotorForce;
btScalar m_accumulatedLinMotorImpulse;
bool m_poweredAngMotor;
btScalar m_targetAngMotorVelocity;
btScalar m_maxAngMotorForce;
btScalar m_accumulatedAngMotorImpulse;
//------------------------
void initParams();
public:
// constructors
btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
btSliderConstraint();
// overrides
virtual void buildJacobian();
virtual void getInfo1 (btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
// access
const btRigidBody& getRigidBodyA() const { return m_rbA; }
const btRigidBody& getRigidBodyB() const { return m_rbB; }
const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
const btTransform & getFrameOffsetA() const { return m_frameInA; }
const btTransform & getFrameOffsetB() const { return m_frameInB; }
btTransform & getFrameOffsetA() { return m_frameInA; }
btTransform & getFrameOffsetB() { return m_frameInB; }
btScalar getLowerLinLimit() { return m_lowerLinLimit; }
void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
btScalar getUpperLinLimit() { return m_upperLinLimit; }
void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
btScalar getLowerAngLimit() { return m_lowerAngLimit; }
void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; }
btScalar getUpperAngLimit() { return m_upperAngLimit; }
void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; }
bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
btScalar getSoftnessDirLin() { return m_softnessDirLin; }
btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
btScalar getDampingDirLin() { return m_dampingDirLin ; }
btScalar getSoftnessDirAng() { return m_softnessDirAng; }
btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
btScalar getDampingDirAng() { return m_dampingDirAng; }
btScalar getSoftnessLimLin() { return m_softnessLimLin; }
btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
btScalar getDampingLimLin() { return m_dampingLimLin; }
btScalar getSoftnessLimAng() { return m_softnessLimAng; }
btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
btScalar getDampingLimAng() { return m_dampingLimAng; }
btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
bool getPoweredLinMotor() { return m_poweredLinMotor; }
void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
bool getPoweredAngMotor() { return m_poweredAngMotor; }
void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
btScalar getLinearPos() { return m_linPos; }
// access for ODE solver
bool getSolveLinLimit() { return m_solveLinLim; }
btScalar getLinDepth() { return m_depth[0]; }
bool getSolveAngLimit() { return m_solveAngLim; }
btScalar getAngDepth() { return m_angDepth; }
// internal
void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);
void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB);
// shared code used by ODE solver
void calculateTransforms(void);
void testLinLimits(void);
void testLinLimits2(btConstraintInfo2* info);
void testAngLimits(void);
// access for PE Solver
btVector3 getAncorInA(void);
btVector3 getAncorInB(void);
};
//-----------------------------------------------------------------------------
#endif //SLIDER_CONSTRAINT_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.
*/
/*
Added by Roman Ponomarev (rponom@gmail.com)
April 04, 2008
TODO:
- add clamping od accumulated impulse to improve stability
- add conversion for ODE constraint solver
*/
#ifndef SLIDER_CONSTRAINT_H
#define SLIDER_CONSTRAINT_H
//-----------------------------------------------------------------------------
#include "LinearMath/btVector3.h"
#include "btJacobianEntry.h"
#include "btTypedConstraint.h"
//-----------------------------------------------------------------------------
class btRigidBody;
//-----------------------------------------------------------------------------
#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
//-----------------------------------------------------------------------------
class btSliderConstraint : public btTypedConstraint
{
protected:
///for backwards compatibility during the transition to 'getInfo/getInfo2'
bool m_useSolveConstraintObsolete;
btTransform m_frameInA;
btTransform m_frameInB;
// use frameA fo define limits, if true
bool m_useLinearReferenceFrameA;
// linear limits
btScalar m_lowerLinLimit;
btScalar m_upperLinLimit;
// angular limits
btScalar m_lowerAngLimit;
btScalar m_upperAngLimit;
// softness, restitution and damping for different cases
// DirLin - moving inside linear limits
// LimLin - hitting linear limit
// DirAng - moving inside angular limits
// LimAng - hitting angular limit
// OrthoLin, OrthoAng - against constraint axis
btScalar m_softnessDirLin;
btScalar m_restitutionDirLin;
btScalar m_dampingDirLin;
btScalar m_softnessDirAng;
btScalar m_restitutionDirAng;
btScalar m_dampingDirAng;
btScalar m_softnessLimLin;
btScalar m_restitutionLimLin;
btScalar m_dampingLimLin;
btScalar m_softnessLimAng;
btScalar m_restitutionLimAng;
btScalar m_dampingLimAng;
btScalar m_softnessOrthoLin;
btScalar m_restitutionOrthoLin;
btScalar m_dampingOrthoLin;
btScalar m_softnessOrthoAng;
btScalar m_restitutionOrthoAng;
btScalar m_dampingOrthoAng;
// for interlal use
bool m_solveLinLim;
bool m_solveAngLim;
btJacobianEntry m_jacLin[3];
btScalar m_jacLinDiagABInv[3];
btJacobianEntry m_jacAng[3];
btScalar m_timeStep;
btTransform m_calculatedTransformA;
btTransform m_calculatedTransformB;
btVector3 m_sliderAxis;
btVector3 m_realPivotAInW;
btVector3 m_realPivotBInW;
btVector3 m_projPivotInW;
btVector3 m_delta;
btVector3 m_depth;
btVector3 m_relPosA;
btVector3 m_relPosB;
btScalar m_linPos;
btScalar m_angPos;
btScalar m_angDepth;
btScalar m_kAngle;
bool m_poweredLinMotor;
btScalar m_targetLinMotorVelocity;
btScalar m_maxLinMotorForce;
btScalar m_accumulatedLinMotorImpulse;
bool m_poweredAngMotor;
btScalar m_targetAngMotorVelocity;
btScalar m_maxAngMotorForce;
btScalar m_accumulatedAngMotorImpulse;
//------------------------
void initParams();
public:
// constructors
btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
btSliderConstraint();
// overrides
virtual void buildJacobian();
virtual void getInfo1 (btConstraintInfo1* info);
virtual void getInfo2 (btConstraintInfo2* info);
virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
// access
const btRigidBody& getRigidBodyA() const { return m_rbA; }
const btRigidBody& getRigidBodyB() const { return m_rbB; }
const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
const btTransform & getFrameOffsetA() const { return m_frameInA; }
const btTransform & getFrameOffsetB() const { return m_frameInB; }
btTransform & getFrameOffsetA() { return m_frameInA; }
btTransform & getFrameOffsetB() { return m_frameInB; }
btScalar getLowerLinLimit() { return m_lowerLinLimit; }
void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
btScalar getUpperLinLimit() { return m_upperLinLimit; }
void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
btScalar getLowerAngLimit() { return m_lowerAngLimit; }
void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; }
btScalar getUpperAngLimit() { return m_upperAngLimit; }
void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; }
bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
btScalar getSoftnessDirLin() { return m_softnessDirLin; }
btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
btScalar getDampingDirLin() { return m_dampingDirLin ; }
btScalar getSoftnessDirAng() { return m_softnessDirAng; }
btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
btScalar getDampingDirAng() { return m_dampingDirAng; }
btScalar getSoftnessLimLin() { return m_softnessLimLin; }
btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
btScalar getDampingLimLin() { return m_dampingLimLin; }
btScalar getSoftnessLimAng() { return m_softnessLimAng; }
btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
btScalar getDampingLimAng() { return m_dampingLimAng; }
btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
bool getPoweredLinMotor() { return m_poweredLinMotor; }
void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
bool getPoweredAngMotor() { return m_poweredAngMotor; }
void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
btScalar getLinearPos() { return m_linPos; }
// access for ODE solver
bool getSolveLinLimit() { return m_solveLinLim; }
btScalar getLinDepth() { return m_depth[0]; }
bool getSolveAngLimit() { return m_solveAngLim; }
btScalar getAngDepth() { return m_angDepth; }
// internal
void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);
void solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB);
// shared code used by ODE solver
void calculateTransforms(void);
void testLinLimits(void);
void testLinLimits2(btConstraintInfo2* info);
void testAngLimits(void);
// access for PE Solver
btVector3 getAncorInA(void);
btVector3 getAncorInB(void);
};
//-----------------------------------------------------------------------------
#endif //SLIDER_CONSTRAINT_H

View File

@@ -1,179 +1,179 @@
/*
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_SOLVER_BODY_H
#define BT_SOLVER_BODY_H
class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btTransformUtil.h"
///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
#ifdef BT_USE_SSE
#define USE_SIMD 1
#endif //
#ifdef USE_SIMD
struct btSimdScalar
{
SIMD_FORCE_INLINE btSimdScalar()
{
}
SIMD_FORCE_INLINE btSimdScalar(float fl)
:m_vec128 (_mm_set1_ps(fl))
{
}
SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
:m_vec128(v128)
{
}
union
{
__m128 m_vec128;
float m_floats[4];
int m_ints[4];
btScalar m_unusedPadding;
};
SIMD_FORCE_INLINE __m128 get128()
{
return m_vec128;
}
SIMD_FORCE_INLINE const __m128 get128() const
{
return m_vec128;
}
SIMD_FORCE_INLINE void set128(__m128 v128)
{
m_vec128 = v128;
}
SIMD_FORCE_INLINE operator __m128()
{
return m_vec128;
}
SIMD_FORCE_INLINE operator const __m128() const
{
return m_vec128;
}
SIMD_FORCE_INLINE operator float() const
{
return m_floats[0];
}
};
///@brief Return the elementwise product of two btSimdScalar
SIMD_FORCE_INLINE btSimdScalar
operator*(const btSimdScalar& v1, const btSimdScalar& v2)
{
return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
}
///@brief Return the elementwise product of two btSimdScalar
SIMD_FORCE_INLINE btSimdScalar
operator+(const btSimdScalar& v1, const btSimdScalar& v2)
{
return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
}
#else
#define btSimdScalar btScalar
#endif
///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
ATTRIBUTE_ALIGNED16 (struct) btSolverBody
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 m_deltaLinearVelocity;
btVector3 m_deltaAngularVelocity;
btScalar m_angularFactor;
btScalar m_invMass;
btScalar m_friction;
btRigidBody* m_originalBody;
btVector3 m_pushVelocity;
//btVector3 m_turnVelocity;
SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
{
if (m_originalBody)
velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
else
velocity.setValue(0,0,0);
}
SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const
{
if (m_originalBody)
angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity;
else
angVel.setValue(0,0,0);
}
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
{
//if (m_invMass)
{
m_deltaLinearVelocity += linearComponent*impulseMagnitude;
m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
}
}
/*
void writebackVelocity()
{
if (m_invMass)
{
m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
//m_originalBody->setCompanionId(-1);
}
}
*/
void writebackVelocity(btScalar timeStep=0)
{
if (m_invMass)
{
m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+m_deltaLinearVelocity);
m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
//m_originalBody->setCompanionId(-1);
}
}
};
#endif //BT_SOLVER_BODY_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.
*/
#ifndef BT_SOLVER_BODY_H
#define BT_SOLVER_BODY_H
class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btTransformUtil.h"
///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
#ifdef BT_USE_SSE
#define USE_SIMD 1
#endif //
#ifdef USE_SIMD
struct btSimdScalar
{
SIMD_FORCE_INLINE btSimdScalar()
{
}
SIMD_FORCE_INLINE btSimdScalar(float fl)
:m_vec128 (_mm_set1_ps(fl))
{
}
SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
:m_vec128(v128)
{
}
union
{
__m128 m_vec128;
float m_floats[4];
int m_ints[4];
btScalar m_unusedPadding;
};
SIMD_FORCE_INLINE __m128 get128()
{
return m_vec128;
}
SIMD_FORCE_INLINE const __m128 get128() const
{
return m_vec128;
}
SIMD_FORCE_INLINE void set128(__m128 v128)
{
m_vec128 = v128;
}
SIMD_FORCE_INLINE operator __m128()
{
return m_vec128;
}
SIMD_FORCE_INLINE operator const __m128() const
{
return m_vec128;
}
SIMD_FORCE_INLINE operator float() const
{
return m_floats[0];
}
};
///@brief Return the elementwise product of two btSimdScalar
SIMD_FORCE_INLINE btSimdScalar
operator*(const btSimdScalar& v1, const btSimdScalar& v2)
{
return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
}
///@brief Return the elementwise product of two btSimdScalar
SIMD_FORCE_INLINE btSimdScalar
operator+(const btSimdScalar& v1, const btSimdScalar& v2)
{
return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
}
#else
#define btSimdScalar btScalar
#endif
///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
ATTRIBUTE_ALIGNED16 (struct) btSolverBody
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 m_deltaLinearVelocity;
btVector3 m_deltaAngularVelocity;
btScalar m_angularFactor;
btScalar m_invMass;
btScalar m_friction;
btRigidBody* m_originalBody;
btVector3 m_pushVelocity;
//btVector3 m_turnVelocity;
SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
{
if (m_originalBody)
velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
else
velocity.setValue(0,0,0);
}
SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const
{
if (m_originalBody)
angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity;
else
angVel.setValue(0,0,0);
}
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
{
//if (m_invMass)
{
m_deltaLinearVelocity += linearComponent*impulseMagnitude;
m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
}
}
/*
void writebackVelocity()
{
if (m_invMass)
{
m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
//m_originalBody->setCompanionId(-1);
}
}
*/
void writebackVelocity(btScalar timeStep=0)
{
if (m_invMass)
{
m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+m_deltaLinearVelocity);
m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
//m_originalBody->setCompanionId(-1);
}
}
};
#endif //BT_SOLVER_BODY_H

View File

@@ -19,7 +19,7 @@ subject to the following restrictions:
static btRigidBody s_fixed(0, 0,0);
#define DEFAULT_DEBUGDRAW_SIZE btScalar(5.f)
#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f)
btTypedConstraint::btTypedConstraint(btTypedConstraintType type)
:m_userConstraintType(-1),

File diff suppressed because it is too large Load Diff

View File

@@ -1,176 +1,176 @@
/*
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_DISCRETE_DYNAMICS_WORLD_H
#define BT_DISCRETE_DYNAMICS_WORLD_H
#include "btDynamicsWorld.h"
class btDispatcher;
class btOverlappingPairCache;
class btConstraintSolver;
class btSimulationIslandManager;
class btTypedConstraint;
class btRaycastVehicle;
class btCharacterControllerInterface;
class btIDebugDraw;
#include "LinearMath/btAlignedObjectArray.h"
///btDiscreteDynamicsWorld provides discrete rigid body simulation
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
class btDiscreteDynamicsWorld : public btDynamicsWorld
{
protected:
btConstraintSolver* m_constraintSolver;
btSimulationIslandManager* m_islandManager;
btAlignedObjectArray<btTypedConstraint*> m_constraints;
btVector3 m_gravity;
//for variable timesteps
btScalar m_localTime;
//for variable timesteps
bool m_ownsIslandManager;
bool m_ownsConstraintSolver;
btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
btAlignedObjectArray<btCharacterControllerInterface*> m_characters;
int m_profileTimings;
virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void integrateTransforms(btScalar timeStep);
virtual void calculateSimulationIslands();
virtual void solveConstraints(btContactSolverInfo& solverInfo);
void updateActivationState(btScalar timeStep);
void updateVehicles(btScalar timeStep);
void updateCharacters(btScalar timeStep);
void startProfiling(btScalar timeStep);
virtual void internalSingleStepSimulation( btScalar timeStep);
virtual void saveKinematicState(btScalar timeStep);
void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color);
public:
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
virtual ~btDiscreteDynamicsWorld();
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
virtual void synchronizeMotionStates();
///this can be useful to synchronize a single rigid body -> graphics object
void synchronizeSingleMotionState(btRigidBody* body);
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
virtual void removeConstraint(btTypedConstraint* constraint);
virtual void addVehicle(btRaycastVehicle* vehicle);
virtual void removeVehicle(btRaycastVehicle* vehicle);
virtual void addCharacter(btCharacterControllerInterface* character);
virtual void removeCharacter(btCharacterControllerInterface* character);
btSimulationIslandManager* getSimulationIslandManager()
{
return m_islandManager;
}
const btSimulationIslandManager* getSimulationIslandManager() const
{
return m_islandManager;
}
btCollisionWorld* getCollisionWorld()
{
return this;
}
virtual void setGravity(const btVector3& gravity);
virtual btVector3 getGravity () const;
virtual void addRigidBody(btRigidBody* body);
virtual void addRigidBody(btRigidBody* body, short group, short mask);
virtual void removeRigidBody(btRigidBody* body);
void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
void debugDrawConstraint(btTypedConstraint* constraint);
virtual void debugDrawWorld();
virtual void setConstraintSolver(btConstraintSolver* solver);
virtual btConstraintSolver* getConstraintSolver();
virtual int getNumConstraints() const;
virtual btTypedConstraint* getConstraint(int index) ;
virtual const btTypedConstraint* getConstraint(int index) const;
virtual btDynamicsWorldType getWorldType() const
{
return BT_DISCRETE_DYNAMICS_WORLD;
}
///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
virtual void clearForces();
///apply gravity, call this once per timestep
virtual void applyGravity();
virtual void setNumTasks(int numTasks)
{
(void) numTasks;
}
};
#endif //BT_DISCRETE_DYNAMICS_WORLD_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.
*/
#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
#define BT_DISCRETE_DYNAMICS_WORLD_H
#include "btDynamicsWorld.h"
class btDispatcher;
class btOverlappingPairCache;
class btConstraintSolver;
class btSimulationIslandManager;
class btTypedConstraint;
class btRaycastVehicle;
class btCharacterControllerInterface;
class btIDebugDraw;
#include "LinearMath/btAlignedObjectArray.h"
///btDiscreteDynamicsWorld provides discrete rigid body simulation
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
class btDiscreteDynamicsWorld : public btDynamicsWorld
{
protected:
btConstraintSolver* m_constraintSolver;
btSimulationIslandManager* m_islandManager;
btAlignedObjectArray<btTypedConstraint*> m_constraints;
btVector3 m_gravity;
//for variable timesteps
btScalar m_localTime;
//for variable timesteps
bool m_ownsIslandManager;
bool m_ownsConstraintSolver;
btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
btAlignedObjectArray<btCharacterControllerInterface*> m_characters;
int m_profileTimings;
virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void integrateTransforms(btScalar timeStep);
virtual void calculateSimulationIslands();
virtual void solveConstraints(btContactSolverInfo& solverInfo);
void updateActivationState(btScalar timeStep);
void updateVehicles(btScalar timeStep);
void updateCharacters(btScalar timeStep);
void startProfiling(btScalar timeStep);
virtual void internalSingleStepSimulation( btScalar timeStep);
virtual void saveKinematicState(btScalar timeStep);
void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color);
public:
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
virtual ~btDiscreteDynamicsWorld();
///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
virtual void synchronizeMotionStates();
///this can be useful to synchronize a single rigid body -> graphics object
void synchronizeSingleMotionState(btRigidBody* body);
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
virtual void removeConstraint(btTypedConstraint* constraint);
virtual void addVehicle(btRaycastVehicle* vehicle);
virtual void removeVehicle(btRaycastVehicle* vehicle);
virtual void addCharacter(btCharacterControllerInterface* character);
virtual void removeCharacter(btCharacterControllerInterface* character);
btSimulationIslandManager* getSimulationIslandManager()
{
return m_islandManager;
}
const btSimulationIslandManager* getSimulationIslandManager() const
{
return m_islandManager;
}
btCollisionWorld* getCollisionWorld()
{
return this;
}
virtual void setGravity(const btVector3& gravity);
virtual btVector3 getGravity () const;
virtual void addRigidBody(btRigidBody* body);
virtual void addRigidBody(btRigidBody* body, short group, short mask);
virtual void removeRigidBody(btRigidBody* body);
void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
void debugDrawConstraint(btTypedConstraint* constraint);
virtual void debugDrawWorld();
virtual void setConstraintSolver(btConstraintSolver* solver);
virtual btConstraintSolver* getConstraintSolver();
virtual int getNumConstraints() const;
virtual btTypedConstraint* getConstraint(int index) ;
virtual const btTypedConstraint* getConstraint(int index) const;
virtual btDynamicsWorldType getWorldType() const
{
return BT_DISCRETE_DYNAMICS_WORLD;
}
///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
virtual void clearForces();
///apply gravity, call this once per timestep
virtual void applyGravity();
virtual void setNumTasks(int numTasks)
{
(void) numTasks;
}
};
#endif //BT_DISCRETE_DYNAMICS_WORLD_H

View File

@@ -1,136 +1,136 @@
/*
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_DYNAMICS_WORLD_H
#define BT_DYNAMICS_WORLD_H
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
class btTypedConstraint;
class btRaycastVehicle;
class btConstraintSolver;
class btDynamicsWorld;
class btCharacterControllerInterface;
/// Type for the callback for each tick
typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
enum btDynamicsWorldType
{
BT_SIMPLE_DYNAMICS_WORLD=1,
BT_DISCRETE_DYNAMICS_WORLD=2,
BT_CONTINUOUS_DYNAMICS_WORLD=3
};
///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
class btDynamicsWorld : public btCollisionWorld
{
protected:
btInternalTickCallback m_internalTickCallback;
void* m_worldUserInfo;
btContactSolverInfo m_solverInfo;
public:
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0)
{
}
virtual ~btDynamicsWorld()
{
}
///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
virtual void debugDrawWorld() = 0;
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
{
(void)constraint; (void)disableCollisionsBetweenLinkedBodies;
}
virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;}
virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;}
//once a rigidbody is added to the dynamics world, it will get this gravity assigned
//existing rigidbodies in the world get gravity assigned too, during this method
virtual void setGravity(const btVector3& gravity) = 0;
virtual btVector3 getGravity () const = 0;
virtual void synchronizeMotionStates() = 0;
virtual void addRigidBody(btRigidBody* body) = 0;
virtual void removeRigidBody(btRigidBody* body) = 0;
virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
virtual btConstraintSolver* getConstraintSolver() = 0;
virtual int getNumConstraints() const { return 0; }
virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
virtual btDynamicsWorldType getWorldType() const=0;
virtual void clearForces() = 0;
/// Set the callback for when an internal tick (simulation substep) happens, optional user info
void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0)
{
m_internalTickCallback = cb;
m_worldUserInfo = worldUserInfo;
}
void setWorldUserInfo(void* worldUserInfo)
{
m_worldUserInfo = worldUserInfo;
}
void* getWorldUserInfo() const
{
return m_worldUserInfo;
}
btContactSolverInfo& getSolverInfo()
{
return m_solverInfo;
}
};
#endif //BT_DYNAMICS_WORLD_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.
*/
#ifndef BT_DYNAMICS_WORLD_H
#define BT_DYNAMICS_WORLD_H
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
class btTypedConstraint;
class btRaycastVehicle;
class btConstraintSolver;
class btDynamicsWorld;
class btCharacterControllerInterface;
/// Type for the callback for each tick
typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
enum btDynamicsWorldType
{
BT_SIMPLE_DYNAMICS_WORLD=1,
BT_DISCRETE_DYNAMICS_WORLD=2,
BT_CONTINUOUS_DYNAMICS_WORLD=3
};
///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
class btDynamicsWorld : public btCollisionWorld
{
protected:
btInternalTickCallback m_internalTickCallback;
void* m_worldUserInfo;
btContactSolverInfo m_solverInfo;
public:
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0)
{
}
virtual ~btDynamicsWorld()
{
}
///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
virtual void debugDrawWorld() = 0;
virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
{
(void)constraint; (void)disableCollisionsBetweenLinkedBodies;
}
virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;}
virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;}
//once a rigidbody is added to the dynamics world, it will get this gravity assigned
//existing rigidbodies in the world get gravity assigned too, during this method
virtual void setGravity(const btVector3& gravity) = 0;
virtual btVector3 getGravity () const = 0;
virtual void synchronizeMotionStates() = 0;
virtual void addRigidBody(btRigidBody* body) = 0;
virtual void removeRigidBody(btRigidBody* body) = 0;
virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
virtual btConstraintSolver* getConstraintSolver() = 0;
virtual int getNumConstraints() const { return 0; }
virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
virtual btDynamicsWorldType getWorldType() const=0;
virtual void clearForces() = 0;
/// Set the callback for when an internal tick (simulation substep) happens, optional user info
void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0)
{
m_internalTickCallback = cb;
m_worldUserInfo = worldUserInfo;
}
void setWorldUserInfo(void* worldUserInfo)
{
m_worldUserInfo = worldUserInfo;
}
void* getWorldUserInfo() const
{
return m_worldUserInfo;
}
btContactSolverInfo& getSolverInfo()
{
return m_solverInfo;
}
};
#endif //BT_DYNAMICS_WORLD_H

View File

@@ -1,243 +1,243 @@
/*
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 "btSimpleDynamicsWorld.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
{
void btBulletDynamicsProbe ();
void btBulletDynamicsProbe () {}
}
btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
m_constraintSolver(constraintSolver),
m_ownsConstraintSolver(false),
m_gravity(0,0,-10)
{
}
btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
{
if (m_ownsConstraintSolver)
btAlignedFree( m_constraintSolver);
}
int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
{
(void)fixedTimeStep;
(void)maxSubSteps;
///apply gravity, predict motion
predictUnconstraintMotion(timeStep);
btDispatcherInfo& dispatchInfo = getDispatchInfo();
dispatchInfo.m_timeStep = timeStep;
dispatchInfo.m_stepCount = 0;
dispatchInfo.m_debugDraw = getDebugDrawer();
///perform collision detection
performDiscreteCollisionDetection();
///solve contact constraints
int numManifolds = m_dispatcher1->getNumManifolds();
if (numManifolds)
{
btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
btContactSolverInfo infoGlobal;
infoGlobal.m_timeStep = timeStep;
m_constraintSolver->prepareSolve(0,numManifolds);
m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1);
m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc);
}
///integrate transforms
integrateTransforms(timeStep);
updateAabbs();
synchronizeMotionStates();
clearForces();
return 1;
}
void btSimpleDynamicsWorld::clearForces()
{
///@todo: iterate over awake simulation islands!
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
body->clearForces();
}
}
}
void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
{
m_gravity = gravity;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
body->setGravity(gravity);
}
}
}
btVector3 btSimpleDynamicsWorld::getGravity () const
{
return m_gravity;
}
void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
{
removeCollisionObject(body);
}
void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
{
body->setGravity(m_gravity);
if (body->getCollisionShape())
{
addCollisionObject(body);
}
}
void btSimpleDynamicsWorld::updateAabbs()
{
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticObject()))
{
btVector3 minAabb,maxAabb;
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
btBroadphaseInterface* bp = getBroadphase();
bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
}
}
}
}
void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticObject()))
{
body->predictIntegratedTransform(timeStep, predictedTrans);
body->proceedToTransform( predictedTrans);
}
}
}
}
void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (!body->isStaticObject())
{
if (body->isActive())
{
body->applyGravity();
body->integrateVelocities( timeStep);
body->applyDamping(timeStep);
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
}
}
}
}
}
void btSimpleDynamicsWorld::synchronizeMotionStates()
{
///@todo: iterate over awake simulation islands!
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body && body->getMotionState())
{
if (body->getActivationState() != ISLAND_SLEEPING)
{
body->getMotionState()->setWorldTransform(body->getWorldTransform());
}
}
}
}
void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
{
if (m_ownsConstraintSolver)
{
btAlignedFree(m_constraintSolver);
}
m_ownsConstraintSolver = false;
m_constraintSolver = solver;
}
btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
{
return m_constraintSolver;
}
/*
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 "btSimpleDynamicsWorld.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
{
void btBulletDynamicsProbe ();
void btBulletDynamicsProbe () {}
}
btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
m_constraintSolver(constraintSolver),
m_ownsConstraintSolver(false),
m_gravity(0,0,-10)
{
}
btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
{
if (m_ownsConstraintSolver)
btAlignedFree( m_constraintSolver);
}
int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
{
(void)fixedTimeStep;
(void)maxSubSteps;
///apply gravity, predict motion
predictUnconstraintMotion(timeStep);
btDispatcherInfo& dispatchInfo = getDispatchInfo();
dispatchInfo.m_timeStep = timeStep;
dispatchInfo.m_stepCount = 0;
dispatchInfo.m_debugDraw = getDebugDrawer();
///perform collision detection
performDiscreteCollisionDetection();
///solve contact constraints
int numManifolds = m_dispatcher1->getNumManifolds();
if (numManifolds)
{
btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
btContactSolverInfo infoGlobal;
infoGlobal.m_timeStep = timeStep;
m_constraintSolver->prepareSolve(0,numManifolds);
m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1);
m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc);
}
///integrate transforms
integrateTransforms(timeStep);
updateAabbs();
synchronizeMotionStates();
clearForces();
return 1;
}
void btSimpleDynamicsWorld::clearForces()
{
///@todo: iterate over awake simulation islands!
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
body->clearForces();
}
}
}
void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
{
m_gravity = gravity;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
body->setGravity(gravity);
}
}
}
btVector3 btSimpleDynamicsWorld::getGravity () const
{
return m_gravity;
}
void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
{
removeCollisionObject(body);
}
void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
{
body->setGravity(m_gravity);
if (body->getCollisionShape())
{
addCollisionObject(body);
}
}
void btSimpleDynamicsWorld::updateAabbs()
{
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticObject()))
{
btVector3 minAabb,maxAabb;
colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
btBroadphaseInterface* bp = getBroadphase();
bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
}
}
}
}
void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
{
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticObject()))
{
body->predictIntegratedTransform(timeStep, predictedTrans);
body->proceedToTransform( predictedTrans);
}
}
}
}
void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body)
{
if (!body->isStaticObject())
{
if (body->isActive())
{
body->applyGravity();
body->integrateVelocities( timeStep);
body->applyDamping(timeStep);
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
}
}
}
}
}
void btSimpleDynamicsWorld::synchronizeMotionStates()
{
///@todo: iterate over awake simulation islands!
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body && body->getMotionState())
{
if (body->getActivationState() != ISLAND_SLEEPING)
{
body->getMotionState()->setWorldTransform(body->getWorldTransform());
}
}
}
}
void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
{
if (m_ownsConstraintSolver)
{
btAlignedFree(m_constraintSolver);
}
m_ownsConstraintSolver = false;
m_constraintSolver = solver;
}
btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
{
return m_constraintSolver;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,56 +1,56 @@
/*
* Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "btWheelInfo.h"
#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
btScalar btWheelInfo::getSuspensionRestLength() const
{
return m_suspensionRestLength1;
}
void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo)
{
(void)raycastInfo;
if (m_raycastInfo.m_isInContact)
{
btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
btVector3 chassis_velocity_at_contactPoint;
btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos );
btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
if ( project >= btScalar(-0.1))
{
m_suspensionRelativeVelocity = btScalar(0.0);
m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
}
else
{
btScalar inv = btScalar(-1.) / project;
m_suspensionRelativeVelocity = projVel * inv;
m_clippedInvContactDotSuspension = inv;
}
}
else // Not in contact : position wheel in a nice (rest length) position
{
m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
m_suspensionRelativeVelocity = btScalar(0.0);
m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
m_clippedInvContactDotSuspension = btScalar(1.0);
}
}
/*
* Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
* Erwin Coumans makes no representations about the suitability
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
#include "btWheelInfo.h"
#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
btScalar btWheelInfo::getSuspensionRestLength() const
{
return m_suspensionRestLength1;
}
void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo)
{
(void)raycastInfo;
if (m_raycastInfo.m_isInContact)
{
btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
btVector3 chassis_velocity_at_contactPoint;
btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos );
btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
if ( project >= btScalar(-0.1))
{
m_suspensionRelativeVelocity = btScalar(0.0);
m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
}
else
{
btScalar inv = btScalar(-1.) / project;
m_suspensionRelativeVelocity = projVel * inv;
m_clippedInvContactDotSuspension = inv;
}
}
else // Not in contact : position wheel in a nice (rest length) position
{
m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
m_suspensionRelativeVelocity = btScalar(0.0);
m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
m_clippedInvContactDotSuspension = btScalar(1.0);
}
}

View File

@@ -1,93 +1,93 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SequentialThreadSupport.h"
#include "SpuCollisionTaskProcess.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
SequentialThreadSupport::SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo)
{
startThreads(threadConstructionInfo);
}
///cleanup/shutdown Libspe2
SequentialThreadSupport::~SequentialThreadSupport()
{
stopSPU();
}
#include <stdio.h>
///send messages to SPUs
void SequentialThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
{
switch (uiCommand)
{
case CMD_GATHER_AND_PROCESS_PAIRLIST:
{
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr=(void*)uiArgument0;
spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
}
break;
default:
{
///not implemented
btAssert(0 && "Not implemented");
}
};
}
///check for messages from SPUs
void SequentialThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
{
btAssert(m_activeSpuStatus.size());
btSpuStatus& spuStatus = m_activeSpuStatus[0];
*puiArgument0 = spuStatus.m_taskId;
*puiArgument1 = spuStatus.m_status;
}
void SequentialThreadSupport::startThreads(SequentialThreadConstructionInfo& threadConstructionInfo)
{
m_activeSpuStatus.resize(1);
printf("STS: Not starting any threads\n");
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr = 0;
spuStatus.m_taskId = 0;
spuStatus.m_commandId = 0;
spuStatus.m_status = 0;
spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
printf("STS: Created local store at %p for task %s\n", spuStatus.m_lsMemory, threadConstructionInfo.m_uniqueName);
}
void SequentialThreadSupport::startSPU()
{
}
void SequentialThreadSupport::stopSPU()
{
m_activeSpuStatus.clear();
}
void SequentialThreadSupport::setNumTasks(int numTasks)
{
printf("SequentialThreadSupport::setNumTasks(%d) is not implemented and has no effect\n",numTasks);
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SequentialThreadSupport.h"
#include "SpuCollisionTaskProcess.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
SequentialThreadSupport::SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo)
{
startThreads(threadConstructionInfo);
}
///cleanup/shutdown Libspe2
SequentialThreadSupport::~SequentialThreadSupport()
{
stopSPU();
}
#include <stdio.h>
///send messages to SPUs
void SequentialThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
{
switch (uiCommand)
{
case CMD_GATHER_AND_PROCESS_PAIRLIST:
{
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr=(void*)uiArgument0;
spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
}
break;
default:
{
///not implemented
btAssert(0 && "Not implemented");
}
};
}
///check for messages from SPUs
void SequentialThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
{
btAssert(m_activeSpuStatus.size());
btSpuStatus& spuStatus = m_activeSpuStatus[0];
*puiArgument0 = spuStatus.m_taskId;
*puiArgument1 = spuStatus.m_status;
}
void SequentialThreadSupport::startThreads(SequentialThreadConstructionInfo& threadConstructionInfo)
{
m_activeSpuStatus.resize(1);
printf("STS: Not starting any threads\n");
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr = 0;
spuStatus.m_taskId = 0;
spuStatus.m_commandId = 0;
spuStatus.m_status = 0;
spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
printf("STS: Created local store at %p for task %s\n", spuStatus.m_lsMemory, threadConstructionInfo.m_uniqueName);
}
void SequentialThreadSupport::startSPU()
{
}
void SequentialThreadSupport::stopSPU()
{
m_activeSpuStatus.clear();
}
void SequentialThreadSupport::setNumTasks(int numTasks)
{
printf("SequentialThreadSupport::setNumTasks(%d) is not implemented and has no effect\n",numTasks);
}

View File

@@ -1,87 +1,87 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifndef SEQUENTIAL_THREAD_SUPPORT_H
#define SEQUENTIAL_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*SequentiallsMemorySetupFunc)();
///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface
///This is useful for debugging and porting SPU Tasks to other platforms.
class SequentialThreadSupport : public btThreadSupportInterface
{
public:
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
SequentialThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
public:
struct SequentialThreadConstructionInfo
{
SequentialThreadConstructionInfo (char* uniqueName,
SequentialThreadFunc userThreadFunc,
SequentiallsMemorySetupFunc lsMemoryFunc
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc)
{
}
char* m_uniqueName;
SequentialThreadFunc m_userThreadFunc;
SequentiallsMemorySetupFunc m_lsMemoryFunc;
};
SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo);
virtual ~SequentialThreadSupport();
void startThreads(SequentialThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks);
};
#endif //SEQUENTIAL_THREAD_SUPPORT_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifndef SEQUENTIAL_THREAD_SUPPORT_H
#define SEQUENTIAL_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*SequentialThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*SequentiallsMemorySetupFunc)();
///The SequentialThreadSupport is a portable non-parallel implementation of the btThreadSupportInterface
///This is useful for debugging and porting SPU Tasks to other platforms.
class SequentialThreadSupport : public btThreadSupportInterface
{
public:
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
SequentialThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using SequentiallsMemorySetupFunc
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
public:
struct SequentialThreadConstructionInfo
{
SequentialThreadConstructionInfo (char* uniqueName,
SequentialThreadFunc userThreadFunc,
SequentiallsMemorySetupFunc lsMemoryFunc
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc)
{
}
char* m_uniqueName;
SequentialThreadFunc m_userThreadFunc;
SequentiallsMemorySetupFunc m_lsMemoryFunc;
};
SequentialThreadSupport(SequentialThreadConstructionInfo& threadConstructionInfo);
virtual ~SequentialThreadSupport();
void startThreads(SequentialThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks);
};
#endif //SEQUENTIAL_THREAD_SUPPORT_H

View File

@@ -1,69 +1,69 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SpuContactManifoldCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
void SpuContactManifoldCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
}
btScalar SpuContactManifoldCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
return 1.f;
}
#ifndef __SPU__
SpuContactManifoldCollisionAlgorithm::SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1)
:btCollisionAlgorithm(ci)
#ifdef USE_SEPDISTANCE_UTIL
,m_sepDistance(body0->getCollisionShape()->getAngularMotionDisc(),body1->getCollisionShape()->getAngularMotionDisc())
#endif //USE_SEPDISTANCE_UTIL
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
m_shapeType0 = body0->getCollisionShape()->getShapeType();
m_shapeType1 = body1->getCollisionShape()->getShapeType();
m_collisionMargin0 = body0->getCollisionShape()->getMargin();
m_collisionMargin1 = body1->getCollisionShape()->getMargin();
m_collisionObject0 = body0;
m_collisionObject1 = body1;
if (body0->getCollisionShape()->isPolyhedral())
{
btPolyhedralConvexShape* convex0 = (btPolyhedralConvexShape*)body0->getCollisionShape();
m_shapeDimensions0 = convex0->getImplicitShapeDimensions();
}
if (body1->getCollisionShape()->isPolyhedral())
{
btPolyhedralConvexShape* convex1 = (btPolyhedralConvexShape*)body1->getCollisionShape();
m_shapeDimensions1 = convex1->getImplicitShapeDimensions();
}
}
#endif //__SPU__
SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm()
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SpuContactManifoldCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
void SpuContactManifoldCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
}
btScalar SpuContactManifoldCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
return 1.f;
}
#ifndef __SPU__
SpuContactManifoldCollisionAlgorithm::SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1)
:btCollisionAlgorithm(ci)
#ifdef USE_SEPDISTANCE_UTIL
,m_sepDistance(body0->getCollisionShape()->getAngularMotionDisc(),body1->getCollisionShape()->getAngularMotionDisc())
#endif //USE_SEPDISTANCE_UTIL
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
m_shapeType0 = body0->getCollisionShape()->getShapeType();
m_shapeType1 = body1->getCollisionShape()->getShapeType();
m_collisionMargin0 = body0->getCollisionShape()->getMargin();
m_collisionMargin1 = body1->getCollisionShape()->getMargin();
m_collisionObject0 = body0;
m_collisionObject1 = body1;
if (body0->getCollisionShape()->isPolyhedral())
{
btPolyhedralConvexShape* convex0 = (btPolyhedralConvexShape*)body0->getCollisionShape();
m_shapeDimensions0 = convex0->getImplicitShapeDimensions();
}
if (body1->getCollisionShape()->isPolyhedral())
{
btPolyhedralConvexShape* convex1 = (btPolyhedralConvexShape*)body1->getCollisionShape();
m_shapeDimensions1 = convex1->getImplicitShapeDimensions();
}
}
#endif //__SPU__
SpuContactManifoldCollisionAlgorithm::~SpuContactManifoldCollisionAlgorithm()
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}

View File

@@ -1,120 +1,120 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#define SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "LinearMath/btTransformUtil.h"
class btPersistentManifold;
//#define USE_SEPDISTANCE_UTIL 1
/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU.
ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm
{
btVector3 m_shapeDimensions0;
btVector3 m_shapeDimensions1;
btPersistentManifold* m_manifoldPtr;
int m_shapeType0;
int m_shapeType1;
float m_collisionMargin0;
float m_collisionMargin1;
btCollisionObject* m_collisionObject0;
btCollisionObject* m_collisionObject1;
public:
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
#ifdef USE_SEPDISTANCE_UTIL
btConvexSeparatingDistanceUtil m_sepDistance;
#endif //USE_SEPDISTANCE_UTIL
virtual ~SpuContactManifoldCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
btPersistentManifold* getContactManifoldPtr()
{
return m_manifoldPtr;
}
btCollisionObject* getCollisionObject0()
{
return m_collisionObject0;
}
btCollisionObject* getCollisionObject1()
{
return m_collisionObject1;
}
int getShapeType0() const
{
return m_shapeType0;
}
int getShapeType1() const
{
return m_shapeType1;
}
float getCollisionMargin0() const
{
return m_collisionMargin0;
}
float getCollisionMargin1() const
{
return m_collisionMargin1;
}
const btVector3& getShapeDimensions0() const
{
return m_shapeDimensions0;
}
const btVector3& getShapeDimensions1() const
{
return m_shapeDimensions1;
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm));
return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0,body1);
}
};
};
#endif //SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#define SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "LinearMath/btTransformUtil.h"
class btPersistentManifold;
//#define USE_SEPDISTANCE_UTIL 1
/// SpuContactManifoldCollisionAlgorithm provides contact manifold and should be processed on SPU.
ATTRIBUTE_ALIGNED16(class) SpuContactManifoldCollisionAlgorithm : public btCollisionAlgorithm
{
btVector3 m_shapeDimensions0;
btVector3 m_shapeDimensions1;
btPersistentManifold* m_manifoldPtr;
int m_shapeType0;
int m_shapeType1;
float m_collisionMargin0;
float m_collisionMargin1;
btCollisionObject* m_collisionObject0;
btCollisionObject* m_collisionObject1;
public:
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
SpuContactManifoldCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
#ifdef USE_SEPDISTANCE_UTIL
btConvexSeparatingDistanceUtil m_sepDistance;
#endif //USE_SEPDISTANCE_UTIL
virtual ~SpuContactManifoldCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr)
manifoldArray.push_back(m_manifoldPtr);
}
btPersistentManifold* getContactManifoldPtr()
{
return m_manifoldPtr;
}
btCollisionObject* getCollisionObject0()
{
return m_collisionObject0;
}
btCollisionObject* getCollisionObject1()
{
return m_collisionObject1;
}
int getShapeType0() const
{
return m_shapeType0;
}
int getShapeType1() const
{
return m_shapeType1;
}
float getCollisionMargin0() const
{
return m_collisionMargin0;
}
float getCollisionMargin1() const
{
return m_collisionMargin1;
}
const btVector3& getShapeDimensions0() const
{
return m_shapeDimensions0;
}
const btVector3& getShapeDimensions1() const
{
return m_shapeDimensions1;
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(SpuContactManifoldCollisionAlgorithm));
return new(mem) SpuContactManifoldCollisionAlgorithm(ci,body0,body1);
}
};
};
#endif //SPU_CONTACTMANIFOLD_COLLISION_ALGORITHM_H

View File

@@ -1,209 +1,209 @@
/*
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 "SpuFakeDma.h"
#include <LinearMath/btScalar.h> //for btAssert
//Disabling memcpy sometimes helps debugging DMA
#define USE_MEMCPY 1
#ifdef USE_MEMCPY
#endif
void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
cellDmaLargeGet(ls,ea,size,tag,tid,rid);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
mfc_get(ls,ea,size,tag,0,0);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
cellDmaGet(ls,ea,size,tag,tid,rid);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
///this unalignedDma should not be frequently used, only for small data. It handles alignment and performs check on size (<16 bytes)
int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size)
{
btAssert(size<32);
ATTRIBUTE_ALIGNED16(char tmpBuffer[32]);
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
uint32_t i;
///make sure last 4 bits are the same, for cellDmaSmallGet
uint32_t last4BitsOffset = ea & 0x0f;
char* tmpTarget = tmpBuffer + last4BitsOffset;
#if defined (__SPU__) || defined (USE_LIBSPE2)
int remainingSize = size;
//#define FORCE_cellDmaUnalignedGet 1
#ifdef FORCE_cellDmaUnalignedGet
cellDmaUnalignedGet(tmpTarget,ea,size,DMA_TAG(1),0,0);
#else
char* remainingTmpTarget = tmpTarget;
uint64_t remainingEa = ea;
while (remainingSize)
{
switch (remainingSize)
{
case 1:
case 2:
case 4:
case 8:
case 16:
{
mfc_get(remainingTmpTarget,remainingEa,remainingSize,DMA_TAG(1),0,0);
remainingSize=0;
break;
}
default:
{
//spu_printf("unaligned DMA with non-natural size:%d\n",remainingSize);
int actualSize = 0;
if (remainingSize > 16)
actualSize = 16;
else
if (remainingSize >8)
actualSize=8;
else
if (remainingSize >4)
actualSize=4;
else
if (remainingSize >2)
actualSize=2;
mfc_get(remainingTmpTarget,remainingEa,actualSize,DMA_TAG(1),0,0);
remainingSize-=actualSize;
remainingTmpTarget+=actualSize;
remainingEa += actualSize;
}
}
}
#endif//FORCE_cellDmaUnalignedGet
#else
//copy into final destination
#ifdef USE_MEMCPY
memcpy(tmpTarget,mainMem,size);
#else
for ( i=0;i<size;i++)
{
tmpTarget[i] = mainMem[i];
}
#endif //USE_MEMCPY
#endif
cellDmaWaitTagStatusAll(DMA_MASK(1));
//this is slowish, perhaps memcpy on SPU is smarter?
for (i=0; btLikely( i<size );i++)
{
localStore[i] = tmpTarget[i];
}
return 0;
}
#if defined (__SPU__) || defined (USE_LIBSPE2)
#else
int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
#ifdef USE_MEMCPY
memcpy(localStore,mainMem,size);
#else
for (uint32_t i=0;i<size;i++)
{
localStore[i] = mainMem[i];
}
#endif
return 0;
}
int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
#ifdef USE_MEMCPY
memcpy(localStore,mainMem,size);
#else
for (uint32_t i=0;i<size;i++)
{
localStore[i] = mainMem[i];
}
#endif //#ifdef USE_MEMCPY
return 0;
}
int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
const char* localStore = (const char*)ls;
#ifdef USE_MEMCPY
memcpy(mainMem,localStore,size);
#else
for (uint32_t i=0;i<size;i++)
{
mainMem[i] = localStore[i];
}
#endif //#ifdef USE_MEMCPY
return 0;
}
void cellDmaWaitTagStatusAll(int ignore)
{
}
#endif
/*
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 "SpuFakeDma.h"
#include <LinearMath/btScalar.h> //for btAssert
//Disabling memcpy sometimes helps debugging DMA
#define USE_MEMCPY 1
#ifdef USE_MEMCPY
#endif
void* cellDmaLargeGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
cellDmaLargeGet(ls,ea,size,tag,tid,rid);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
void* cellDmaSmallGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
mfc_get(ls,ea,size,tag,0,0);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
void* cellDmaGetReadOnly(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
#if defined (__SPU__) || defined (USE_LIBSPE2)
cellDmaGet(ls,ea,size,tag,tid,rid);
return ls;
#else
return (void*)(uint32_t)ea;
#endif
}
///this unalignedDma should not be frequently used, only for small data. It handles alignment and performs check on size (<16 bytes)
int stallingUnalignedDmaSmallGet(void *ls, uint64_t ea, uint32_t size)
{
btAssert(size<32);
ATTRIBUTE_ALIGNED16(char tmpBuffer[32]);
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
uint32_t i;
///make sure last 4 bits are the same, for cellDmaSmallGet
uint32_t last4BitsOffset = ea & 0x0f;
char* tmpTarget = tmpBuffer + last4BitsOffset;
#if defined (__SPU__) || defined (USE_LIBSPE2)
int remainingSize = size;
//#define FORCE_cellDmaUnalignedGet 1
#ifdef FORCE_cellDmaUnalignedGet
cellDmaUnalignedGet(tmpTarget,ea,size,DMA_TAG(1),0,0);
#else
char* remainingTmpTarget = tmpTarget;
uint64_t remainingEa = ea;
while (remainingSize)
{
switch (remainingSize)
{
case 1:
case 2:
case 4:
case 8:
case 16:
{
mfc_get(remainingTmpTarget,remainingEa,remainingSize,DMA_TAG(1),0,0);
remainingSize=0;
break;
}
default:
{
//spu_printf("unaligned DMA with non-natural size:%d\n",remainingSize);
int actualSize = 0;
if (remainingSize > 16)
actualSize = 16;
else
if (remainingSize >8)
actualSize=8;
else
if (remainingSize >4)
actualSize=4;
else
if (remainingSize >2)
actualSize=2;
mfc_get(remainingTmpTarget,remainingEa,actualSize,DMA_TAG(1),0,0);
remainingSize-=actualSize;
remainingTmpTarget+=actualSize;
remainingEa += actualSize;
}
}
}
#endif//FORCE_cellDmaUnalignedGet
#else
//copy into final destination
#ifdef USE_MEMCPY
memcpy(tmpTarget,mainMem,size);
#else
for ( i=0;i<size;i++)
{
tmpTarget[i] = mainMem[i];
}
#endif //USE_MEMCPY
#endif
cellDmaWaitTagStatusAll(DMA_MASK(1));
//this is slowish, perhaps memcpy on SPU is smarter?
for (i=0; btLikely( i<size );i++)
{
localStore[i] = tmpTarget[i];
}
return 0;
}
#if defined (__SPU__) || defined (USE_LIBSPE2)
#else
int cellDmaLargeGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
#ifdef USE_MEMCPY
memcpy(localStore,mainMem,size);
#else
for (uint32_t i=0;i<size;i++)
{
localStore[i] = mainMem[i];
}
#endif
return 0;
}
int cellDmaGet(void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
char* localStore = (char*)ls;
#ifdef USE_MEMCPY
memcpy(localStore,mainMem,size);
#else
for (uint32_t i=0;i<size;i++)
{
localStore[i] = mainMem[i];
}
#endif //#ifdef USE_MEMCPY
return 0;
}
int cellDmaLargePut(const void *ls, uint64_t ea, uint32_t size, uint32_t tag, uint32_t tid, uint32_t rid)
{
char* mainMem = (char*)ea;
const char* localStore = (const char*)ls;
#ifdef USE_MEMCPY
memcpy(mainMem,localStore,size);
#else
for (uint32_t i=0;i<size;i++)
{
mainMem[i] = localStore[i];
}
#endif //#ifdef USE_MEMCPY
return 0;
}
void cellDmaWaitTagStatusAll(int ignore)
{
}
#endif

View File

@@ -1,69 +1,69 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 SPU_GATHERING_COLLISION__DISPATCHER_H
#define SPU_GATHERING_COLLISION__DISPATCHER_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
///Tuning value to optimized SPU utilization
///Too small value means Task overhead is large compared to computation (too fine granularity)
///Too big value might render some SPUs are idle, while a few other SPUs are doing all work.
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16
#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024
class SpuCollisionTaskProcess;
///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection
///Time of Impact, Closest Points and Penetration Depth.
class SpuGatheringCollisionDispatcher : public btCollisionDispatcher
{
SpuCollisionTaskProcess* m_spuCollisionTaskProcess;
protected:
class btThreadSupportInterface* m_threadInterface;
unsigned int m_maxNumOutstandingTasks;
public:
//can be used by SPU collision algorithms
SpuCollisionTaskProcess* getSpuCollisionTaskProcess()
{
return m_spuCollisionTaskProcess;
}
SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration);
virtual ~SpuGatheringCollisionDispatcher();
bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
};
#endif //SPU_GATHERING_COLLISION__DISPATCHER_H
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 SPU_GATHERING_COLLISION__DISPATCHER_H
#define SPU_GATHERING_COLLISION__DISPATCHER_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
///Tuning value to optimized SPU utilization
///Too small value means Task overhead is large compared to computation (too fine granularity)
///Too big value might render some SPUs are idle, while a few other SPUs are doing all work.
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 8
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 16
#define SPU_BATCHSIZE_BROADPHASE_PAIRS 64
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 128
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 256
//#define SPU_BATCHSIZE_BROADPHASE_PAIRS 1024
class SpuCollisionTaskProcess;
///SpuGatheringCollisionDispatcher can use SPU to gather and calculate collision detection
///Time of Impact, Closest Points and Penetration Depth.
class SpuGatheringCollisionDispatcher : public btCollisionDispatcher
{
SpuCollisionTaskProcess* m_spuCollisionTaskProcess;
protected:
class btThreadSupportInterface* m_threadInterface;
unsigned int m_maxNumOutstandingTasks;
public:
//can be used by SPU collision algorithms
SpuCollisionTaskProcess* getSpuCollisionTaskProcess()
{
return m_spuCollisionTaskProcess;
}
SpuGatheringCollisionDispatcher (class btThreadSupportInterface* threadInterface, unsigned int maxNumOutstandingTasks,btCollisionConfiguration* collisionConfiguration);
virtual ~SpuGatheringCollisionDispatcher();
bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
};
#endif //SPU_GATHERING_COLLISION__DISPATCHER_H

View File

@@ -1 +1 @@
Empty placeholder for future Libspe2 SPU task
Empty placeholder for future Libspe2 SPU task

View File

@@ -1,164 +1,164 @@
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
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 __BOX_H__
#define __BOX_H__
#ifndef PE_REF
#define PE_REF(a) a&
#endif
#include <math.h>
#include <vectormath_aos.h>
using namespace Vectormath::Aos;
enum FeatureType { F, E, V };
//----------------------------------------------------------------------------
// Box
//----------------------------------------------------------------------------
///The Box is an internal class used by the boxBoxDistance calculation.
class Box
{
public:
Vector3 half;
inline Box()
{}
inline Box(PE_REF(Vector3) half_);
inline Box(float hx, float hy, float hz);
inline void Set(PE_REF(Vector3) half_);
inline void Set(float hx, float hy, float hz);
inline Vector3 GetAABB(const Matrix3& rotation) const;
};
inline
Box::Box(PE_REF(Vector3) half_)
{
Set(half_);
}
inline
Box::Box(float hx, float hy, float hz)
{
Set(hx, hy, hz);
}
inline
void
Box::Set(PE_REF(Vector3) half_)
{
half = half_;
}
inline
void
Box::Set(float hx, float hy, float hz)
{
half = Vector3(hx, hy, hz);
}
inline
Vector3
Box::GetAABB(const Matrix3& rotation) const
{
return absPerElem(rotation) * half;
}
//-------------------------------------------------------------------------------------------------
// BoxPoint
//-------------------------------------------------------------------------------------------------
///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation.
class BoxPoint
{
public:
BoxPoint() : localPoint(0.0f) {}
Point3 localPoint;
FeatureType featureType;
int featureIdx;
inline void setVertexFeature(int plusX, int plusY, int plusZ);
inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1);
inline void setFaceFeature(int dim, int plus);
inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const;
inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const;
inline void getFaceFeature(int & dim, int & plus) const;
};
inline
void
BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ)
{
featureType = V;
featureIdx = plusX << 2 | plusY << 1 | plusZ;
}
inline
void
BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1)
{
featureType = E;
if (dim0 > dim1) {
featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0;
} else {
featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1;
}
}
inline
void
BoxPoint::setFaceFeature(int dim, int plus)
{
featureType = F;
featureIdx = plus << 2 | dim;
}
inline
void
BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const
{
plusX = featureIdx >> 2;
plusY = featureIdx >> 1 & 1;
plusZ = featureIdx & 1;
}
inline
void
BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const
{
plus0 = featureIdx >> 5;
dim0 = featureIdx >> 3 & 3;
plus1 = featureIdx >> 2 & 1;
dim1 = featureIdx & 3;
}
inline
void
BoxPoint::getFaceFeature(int & dim, int & plus) const
{
plus = featureIdx >> 2;
dim = featureIdx & 3;
}
#endif /* __BOX_H__ */
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
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 __BOX_H__
#define __BOX_H__
#ifndef PE_REF
#define PE_REF(a) a&
#endif
#include <math.h>
#include <vectormath_aos.h>
using namespace Vectormath::Aos;
enum FeatureType { F, E, V };
//----------------------------------------------------------------------------
// Box
//----------------------------------------------------------------------------
///The Box is an internal class used by the boxBoxDistance calculation.
class Box
{
public:
Vector3 half;
inline Box()
{}
inline Box(PE_REF(Vector3) half_);
inline Box(float hx, float hy, float hz);
inline void Set(PE_REF(Vector3) half_);
inline void Set(float hx, float hy, float hz);
inline Vector3 GetAABB(const Matrix3& rotation) const;
};
inline
Box::Box(PE_REF(Vector3) half_)
{
Set(half_);
}
inline
Box::Box(float hx, float hy, float hz)
{
Set(hx, hy, hz);
}
inline
void
Box::Set(PE_REF(Vector3) half_)
{
half = half_;
}
inline
void
Box::Set(float hx, float hy, float hz)
{
half = Vector3(hx, hy, hz);
}
inline
Vector3
Box::GetAABB(const Matrix3& rotation) const
{
return absPerElem(rotation) * half;
}
//-------------------------------------------------------------------------------------------------
// BoxPoint
//-------------------------------------------------------------------------------------------------
///The BoxPoint class is an internally used class to contain feature information for boxBoxDistance calculation.
class BoxPoint
{
public:
BoxPoint() : localPoint(0.0f) {}
Point3 localPoint;
FeatureType featureType;
int featureIdx;
inline void setVertexFeature(int plusX, int plusY, int plusZ);
inline void setEdgeFeature(int dim0, int plus0, int dim1, int plus1);
inline void setFaceFeature(int dim, int plus);
inline void getVertexFeature(int & plusX, int & plusY, int & plusZ) const;
inline void getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const;
inline void getFaceFeature(int & dim, int & plus) const;
};
inline
void
BoxPoint::setVertexFeature(int plusX, int plusY, int plusZ)
{
featureType = V;
featureIdx = plusX << 2 | plusY << 1 | plusZ;
}
inline
void
BoxPoint::setEdgeFeature(int dim0, int plus0, int dim1, int plus1)
{
featureType = E;
if (dim0 > dim1) {
featureIdx = plus1 << 5 | dim1 << 3 | plus0 << 2 | dim0;
} else {
featureIdx = plus0 << 5 | dim0 << 3 | plus1 << 2 | dim1;
}
}
inline
void
BoxPoint::setFaceFeature(int dim, int plus)
{
featureType = F;
featureIdx = plus << 2 | dim;
}
inline
void
BoxPoint::getVertexFeature(int & plusX, int & plusY, int & plusZ) const
{
plusX = featureIdx >> 2;
plusY = featureIdx >> 1 & 1;
plusZ = featureIdx & 1;
}
inline
void
BoxPoint::getEdgeFeature(int & dim0, int & plus0, int & dim1, int & plus1) const
{
plus0 = featureIdx >> 5;
dim0 = featureIdx >> 3 & 3;
plus1 = featureIdx >> 2 & 1;
dim1 = featureIdx & 3;
}
inline
void
BoxPoint::getFaceFeature(int & dim, int & plus) const
{
plus = featureIdx >> 2;
dim = featureIdx & 3;
}
#endif /* __BOX_H__ */

View File

@@ -1,125 +1,125 @@
/*
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 __SPU_COLLISION_SHAPES_H
#define __SPU_COLLISION_SHAPES_H
#include "../SpuDoubleBuffer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#define MAX_NUM_SPU_CONVEX_POINTS 128
struct SpuConvexPolyhedronVertexData
{
void* gSpuConvexShapePtr;
btVector3* gConvexPoints;
int gNumConvexPoints;
ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]);
};
#define MAX_SHAPE_SIZE 256
struct CollisionShape_LocalStoreMemory
{
ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]);
};
struct CompoundShape_LocalStoreMemory
{
// Compound data
#define MAX_SPU_COMPOUND_SUBSHAPES 16
ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]);
ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]);
};
struct bvhMeshShape_LocalStoreMemory
{
//ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh);
ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]);
btOptimizedBvh* getOptimizedBvh()
{
return (btOptimizedBvh*) gOptimizedBvh;
}
ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage);
btTriangleIndexVertexArray* gTriangleMeshInterfacePtr;
///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment
ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh);
#define MAX_SPU_SUBTREE_HEADERS 32
//1024
ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]);
ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]);
};
btVector3 localGetSupportingVertexWithoutMargin(int shapeType, void* shape, const btVector3& localDir,struct SpuConvexPolyhedronVertexData* convexVertexData);//, int *featureIndex)
void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform);
void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape);
void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag);
void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag);
void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag);
int getShapeTypeSize(int shapeType);
void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU);
void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType);
void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
#define USE_BRANCHFREE_TEST 1
#ifdef USE_BRANCHFREE_TEST
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
#if defined(__CELLOS_LV2__) && defined (__SPU__)
vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0};
vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0};
vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax);
return spu_extract(spu_gather(isGt),0)==0;
#else
return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
1, 0);
#endif
}
#else
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
unsigned int overlap = 1;
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap;
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap;
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap;
return overlap;
}
#endif
void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex);
#endif
/*
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 __SPU_COLLISION_SHAPES_H
#define __SPU_COLLISION_SHAPES_H
#include "../SpuDoubleBuffer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
#include "BulletCollision/CollisionShapes/btCylinderShape.h"
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#define MAX_NUM_SPU_CONVEX_POINTS 128
struct SpuConvexPolyhedronVertexData
{
void* gSpuConvexShapePtr;
btVector3* gConvexPoints;
int gNumConvexPoints;
ATTRIBUTE_ALIGNED16(btVector3 g_convexPointBuffer[MAX_NUM_SPU_CONVEX_POINTS]);
};
#define MAX_SHAPE_SIZE 256
struct CollisionShape_LocalStoreMemory
{
ATTRIBUTE_ALIGNED16(char collisionShape[MAX_SHAPE_SIZE]);
};
struct CompoundShape_LocalStoreMemory
{
// Compound data
#define MAX_SPU_COMPOUND_SUBSHAPES 16
ATTRIBUTE_ALIGNED16(btCompoundShapeChild gSubshapes[MAX_SPU_COMPOUND_SUBSHAPES]);
ATTRIBUTE_ALIGNED16(char gSubshapeShape[MAX_SPU_COMPOUND_SUBSHAPES][MAX_SHAPE_SIZE]);
};
struct bvhMeshShape_LocalStoreMemory
{
//ATTRIBUTE_ALIGNED16(btOptimizedBvh gOptimizedBvh);
ATTRIBUTE_ALIGNED16(char gOptimizedBvh[sizeof(btOptimizedBvh)+16]);
btOptimizedBvh* getOptimizedBvh()
{
return (btOptimizedBvh*) gOptimizedBvh;
}
ATTRIBUTE_ALIGNED16(btTriangleIndexVertexArray gTriangleMeshInterfaceStorage);
btTriangleIndexVertexArray* gTriangleMeshInterfacePtr;
///only a single mesh part for now, we can add support for multiple parts, but quantized trees don't support this at the moment
ATTRIBUTE_ALIGNED16(btIndexedMesh gIndexMesh);
#define MAX_SPU_SUBTREE_HEADERS 32
//1024
ATTRIBUTE_ALIGNED16(btBvhSubtreeInfo gSubtreeHeaders[MAX_SPU_SUBTREE_HEADERS]);
ATTRIBUTE_ALIGNED16(btQuantizedBvhNode gSubtreeNodes[MAX_SUBTREE_SIZE_IN_BYTES/sizeof(btQuantizedBvhNode)]);
};
btVector3 localGetSupportingVertexWithoutMargin(int shapeType, void* shape, const btVector3& localDir,struct SpuConvexPolyhedronVertexData* convexVertexData);//, int *featureIndex)
void computeAabb (btVector3& aabbMin, btVector3& aabbMax, btConvexInternalShape* convexShape, ppu_address_t convexShapePtr, int shapeType, const btTransform& xform);
void dmaBvhShapeData (bvhMeshShape_LocalStoreMemory* bvhMeshShape, btBvhTriangleMeshShape* triMeshShape);
void dmaBvhIndexedMesh (btIndexedMesh* IndexMesh, IndexedMeshArray& indexArray, int index, uint32_t dmaTag);
void dmaBvhSubTreeHeaders (btBvhSubtreeInfo* subTreeHeaders, ppu_address_t subTreePtr, int batchSize, uint32_t dmaTag);
void dmaBvhSubTreeNodes (btQuantizedBvhNode* nodes, const btBvhSubtreeInfo& subtree, QuantizedNodeArray& nodeArray, int dmaTag);
int getShapeTypeSize(int shapeType);
void dmaConvexVertexData (SpuConvexPolyhedronVertexData* convexVertexData, btConvexHullShape* convexShapeSPU);
void dmaCollisionShape (void* collisionShapeLocation, ppu_address_t collisionShapePtr, uint32_t dmaTag, int shapeType);
void dmaCompoundShapeInfo (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
void dmaCompoundSubShapes (CompoundShape_LocalStoreMemory* compoundShapeLocation, btCompoundShape* spuCompoundShape, uint32_t dmaTag);
#define USE_BRANCHFREE_TEST 1
#ifdef USE_BRANCHFREE_TEST
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
#if defined(__CELLOS_LV2__) && defined (__SPU__)
vec_ushort8 vecMin = {aabbMin1[0],aabbMin2[0],aabbMin1[2],aabbMin2[2],aabbMin1[1],aabbMin2[1],0,0};
vec_ushort8 vecMax = {aabbMax2[0],aabbMax1[0],aabbMax2[2],aabbMax1[2],aabbMax2[1],aabbMax1[1],0,0};
vec_ushort8 isGt = spu_cmpgt(vecMin,vecMax);
return spu_extract(spu_gather(isGt),0)==0;
#else
return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
1, 0);
#endif
}
#else
SIMD_FORCE_INLINE unsigned int spuTestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
unsigned int overlap = 1;
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? 0 : overlap;
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? 0 : overlap;
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? 0 : overlap;
return overlap;
}
#endif
void spuWalkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,const btQuantizedBvhNode* rootNode,int startNodeIndex,int endNodeIndex);
#endif

View File

@@ -1,231 +1,231 @@
/*
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 "SpuContactResult.h"
//#define DEBUG_SPU_COLLISION_DETECTION 1
SpuContactResult::SpuContactResult()
{
m_manifoldAddress = 0;
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}
SpuContactResult::~SpuContactResult()
{
g_manifoldDmaExport.swapBuffers();
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1)
{
btScalar friction = friction0*friction1;
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1)
{
return restitution0*restitution1;
}
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped)
{
//spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress);
m_rootWorldTransform0 = worldTrans0;
m_rootWorldTransform1 = worldTrans1;
m_manifoldAddress = manifoldAddress;
m_spuManifold = spuManifold;
m_combinedFriction = calculateCombinedFriction(friction0,friction1);
m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1);
m_isSwapped = isSwapped;
}
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{
}
///return true if it requires a dma transfer back
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
const btVector3& pointInWorld,
float depth,
btPersistentManifold* manifoldPtr,
btTransform& transA,
btTransform& transB,
btScalar combinedFriction,
btScalar combinedRestitution,
bool isSwapped)
{
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: contactTreshold %f\n",contactTreshold);
#endif //DEBUG_SPU_COLLISION_DETECTION
if (depth > manifoldPtr->getContactBreakingThreshold())
return false;
//provide inverses or just calculate?
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
btVector3 pointA;
btVector3 localA;
btVector3 localB;
btVector3 normal;
if (isSwapped)
{
normal = normalOnBInWorld * -1;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
/*localA = transBInv(pointA );
localB = transAInv(pointInWorld);*/
}
else
{
normal = normalOnBInWorld;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
}
btManifoldPoint newPt(localA,localB,normal,depth);
int insertIndex = manifoldPtr->getCacheEntry(newPt);
if (insertIndex >= 0)
{
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
// return true;
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: same contact detected, nothing done\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
// This is not needed, just use the old info! saves a DMA transfer as well
} else
{
newPt.m_combinedFriction = combinedFriction;
newPt.m_combinedRestitution = combinedRestitution;
/*
///@todo: SPU callbacks, either immediate (local on the SPU), or deferred
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
(m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
{
//experimental feature info, for per-triangle material etc.
(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
}
*/
manifoldPtr->addManifoldPoint(newPt);
return true;
}
return false;
}
void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
{
///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place
///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly'
#if defined (__SPU__) || defined (USE_LIBSPE2)
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
g_manifoldDmaExport.swapBuffers();
ppu_address_t mmAddr = (ppu_address_t)mmManifold;
g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9));
// Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon?
//no, the swapBuffers does the wait
#endif
}
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,float depth)
{
//spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
#ifdef DEBUG_SPU_COLLISION_DETECTION
// int sman = sizeof(rage::phManifold);
// spu_printf("sizeof_manifold = %i\n",sman);
#endif //DEBUG_SPU_COLLISION_DETECTION
btPersistentManifold* localManifold = m_spuManifold;
btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
//process the contact point
const bool retVal = ManifoldResultAddContactPoint(normalB,
pointWrld,
depth,
localManifold,
m_rootWorldTransform0,
m_rootWorldTransform1,
m_combinedFriction,
m_combinedRestitution,
m_isSwapped);
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
}
void SpuContactResult::flush()
{
if (m_spuManifold && m_spuManifold->getNumContacts())
{
m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1);
m_RequiresWriteBack = true;
}
if (m_RequiresWriteBack)
{
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n");
spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts());
spu_printf("Manifold address: %llu\n", m_manifoldAddress);
#endif //DEBUG_SPU_COLLISION_DETECTION
// spu_printf("writeDoubleBufferedManifold\n");
writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Finished (Put) DMA\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
}
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}
/*
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 "SpuContactResult.h"
//#define DEBUG_SPU_COLLISION_DETECTION 1
SpuContactResult::SpuContactResult()
{
m_manifoldAddress = 0;
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}
SpuContactResult::~SpuContactResult()
{
g_manifoldDmaExport.swapBuffers();
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
inline btScalar calculateCombinedFriction(btScalar friction0,btScalar friction1)
{
btScalar friction = friction0*friction1;
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
inline btScalar calculateCombinedRestitution(btScalar restitution0,btScalar restitution1)
{
return restitution0*restitution1;
}
void SpuContactResult::setContactInfo(btPersistentManifold* spuManifold, ppu_address_t manifoldAddress,const btTransform& worldTrans0,const btTransform& worldTrans1, btScalar restitution0,btScalar restitution1, btScalar friction0,btScalar friction1, bool isSwapped)
{
//spu_printf("SpuContactResult::setContactInfo ManifoldAddress: %lu\n", manifoldAddress);
m_rootWorldTransform0 = worldTrans0;
m_rootWorldTransform1 = worldTrans1;
m_manifoldAddress = manifoldAddress;
m_spuManifold = spuManifold;
m_combinedFriction = calculateCombinedFriction(friction0,friction1);
m_combinedRestitution = calculateCombinedRestitution(restitution0,restitution1);
m_isSwapped = isSwapped;
}
void SpuContactResult::setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{
}
///return true if it requires a dma transfer back
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
const btVector3& pointInWorld,
float depth,
btPersistentManifold* manifoldPtr,
btTransform& transA,
btTransform& transB,
btScalar combinedFriction,
btScalar combinedRestitution,
bool isSwapped)
{
float contactTreshold = manifoldPtr->getContactBreakingThreshold();
//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: contactTreshold %f\n",contactTreshold);
#endif //DEBUG_SPU_COLLISION_DETECTION
if (depth > manifoldPtr->getContactBreakingThreshold())
return false;
//provide inverses or just calculate?
btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;
btVector3 pointA;
btVector3 localA;
btVector3 localB;
btVector3 normal;
if (isSwapped)
{
normal = normalOnBInWorld * -1;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
/*localA = transBInv(pointA );
localB = transAInv(pointInWorld);*/
}
else
{
normal = normalOnBInWorld;
pointA = pointInWorld + normal * depth;
localA = transAInv(pointA );
localB = transBInv(pointInWorld);
}
btManifoldPoint newPt(localA,localB,normal,depth);
int insertIndex = manifoldPtr->getCacheEntry(newPt);
if (insertIndex >= 0)
{
// manifoldPtr->replaceContactPoint(newPt,insertIndex);
// return true;
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: same contact detected, nothing done\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
// This is not needed, just use the old info! saves a DMA transfer as well
} else
{
newPt.m_combinedFriction = combinedFriction;
newPt.m_combinedRestitution = combinedRestitution;
/*
///@todo: SPU callbacks, either immediate (local on the SPU), or deferred
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
(m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
{
//experimental feature info, for per-triangle material etc.
(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
}
*/
manifoldPtr->addManifoldPoint(newPt);
return true;
}
return false;
}
void SpuContactResult::writeDoubleBufferedManifold(btPersistentManifold* lsManifold, btPersistentManifold* mmManifold)
{
///only write back the contact information on SPU. Other platforms avoid copying, and use the data in-place
///see SpuFakeDma.cpp 'cellDmaLargeGetReadOnly'
#if defined (__SPU__) || defined (USE_LIBSPE2)
memcpy(g_manifoldDmaExport.getFront(),lsManifold,sizeof(btPersistentManifold));
g_manifoldDmaExport.swapBuffers();
ppu_address_t mmAddr = (ppu_address_t)mmManifold;
g_manifoldDmaExport.backBufferDmaPut(mmAddr, sizeof(btPersistentManifold), DMA_TAG(9));
// Should there be any kind of wait here? What if somebody tries to use this tag again? What if we call this function again really soon?
//no, the swapBuffers does the wait
#endif
}
void SpuContactResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,float depth)
{
//spu_printf("*** SpuContactResult::addContactPoint: depth = %f\n",depth);
#ifdef DEBUG_SPU_COLLISION_DETECTION
// int sman = sizeof(rage::phManifold);
// spu_printf("sizeof_manifold = %i\n",sman);
#endif //DEBUG_SPU_COLLISION_DETECTION
btPersistentManifold* localManifold = m_spuManifold;
btVector3 normalB(normalOnBInWorld.getX(),normalOnBInWorld.getY(),normalOnBInWorld.getZ());
btVector3 pointWrld(pointInWorld.getX(),pointInWorld.getY(),pointInWorld.getZ());
//process the contact point
const bool retVal = ManifoldResultAddContactPoint(normalB,
pointWrld,
depth,
localManifold,
m_rootWorldTransform0,
m_rootWorldTransform1,
m_combinedFriction,
m_combinedRestitution,
m_isSwapped);
m_RequiresWriteBack = m_RequiresWriteBack || retVal;
}
void SpuContactResult::flush()
{
if (m_spuManifold && m_spuManifold->getNumContacts())
{
m_spuManifold->refreshContactPoints(m_rootWorldTransform0,m_rootWorldTransform1);
m_RequiresWriteBack = true;
}
if (m_RequiresWriteBack)
{
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Start SpuContactResult::flush (Put) DMA\n");
spu_printf("Num contacts:%d\n", m_spuManifold->getNumContacts());
spu_printf("Manifold address: %llu\n", m_manifoldAddress);
#endif //DEBUG_SPU_COLLISION_DETECTION
// spu_printf("writeDoubleBufferedManifold\n");
writeDoubleBufferedManifold(m_spuManifold, (btPersistentManifold*)m_manifoldAddress);
#ifdef DEBUG_SPU_COLLISION_DETECTION
spu_printf("SPU: Finished (Put) DMA\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
}
m_spuManifold = NULL;
m_RequiresWriteBack = false;
}

View File

@@ -1,66 +1,66 @@
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
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 __BOXBOXDISTANCE_H__
#define __BOXBOXDISTANCE_H__
#include "Box.h"
using namespace Vectormath::Aos;
//---------------------------------------------------------------------------
// boxBoxDistance:
//
// description:
// this computes info that can be used for the collision response of two boxes. when the boxes
// do not overlap, the points are set to the closest points of the boxes, and a positive
// distance between them is returned. if the boxes do overlap, a negative distance is returned
// and the points are set to two points that would touch after the boxes are translated apart.
// the contact normal gives the direction to repel or separate the boxes when they touch or
// overlap (it's being approximated here as one of the 15 "separating axis" directions).
//
// returns:
// positive or negative distance between two boxes.
//
// args:
// Vector3& normal: set to a unit contact normal pointing from box A to box B.
//
// BoxPoint& boxPointA, BoxPoint& boxPointB:
// set to a closest point or point of penetration on each box.
//
// Box boxA, Box boxB:
// boxes, represented as 3 half-widths
//
// const Transform3& transformA, const Transform3& transformB:
// box transformations, in world coordinates
//
// float distanceThreshold:
// the algorithm will exit early if it finds that the boxes are more distant than this
// threshold, and not compute a contact normal or points. if this distance returned
// exceeds the threshold, all the other output data may not have been computed. by
// default, this is set to MAX_FLOAT so it will have no effect.
//
//---------------------------------------------------------------------------
float
boxBoxDistance(Vector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB,
PE_REF(Box) boxA, const Transform3 & transformA, PE_REF(Box) boxB,
const Transform3 & transformB,
float distanceThreshold = FLT_MAX );
#endif /* __BOXBOXDISTANCE_H__ */
/*
Copyright (C) 2006, 2008 Sony Computer Entertainment Inc.
All rights reserved.
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 __BOXBOXDISTANCE_H__
#define __BOXBOXDISTANCE_H__
#include "Box.h"
using namespace Vectormath::Aos;
//---------------------------------------------------------------------------
// boxBoxDistance:
//
// description:
// this computes info that can be used for the collision response of two boxes. when the boxes
// do not overlap, the points are set to the closest points of the boxes, and a positive
// distance between them is returned. if the boxes do overlap, a negative distance is returned
// and the points are set to two points that would touch after the boxes are translated apart.
// the contact normal gives the direction to repel or separate the boxes when they touch or
// overlap (it's being approximated here as one of the 15 "separating axis" directions).
//
// returns:
// positive or negative distance between two boxes.
//
// args:
// Vector3& normal: set to a unit contact normal pointing from box A to box B.
//
// BoxPoint& boxPointA, BoxPoint& boxPointB:
// set to a closest point or point of penetration on each box.
//
// Box boxA, Box boxB:
// boxes, represented as 3 half-widths
//
// const Transform3& transformA, const Transform3& transformB:
// box transformations, in world coordinates
//
// float distanceThreshold:
// the algorithm will exit early if it finds that the boxes are more distant than this
// threshold, and not compute a contact normal or points. if this distance returned
// exceeds the threshold, all the other output data may not have been computed. by
// default, this is set to MAX_FLOAT so it will have no effect.
//
//---------------------------------------------------------------------------
float
boxBoxDistance(Vector3& normal, BoxPoint& boxPointA, BoxPoint& boxPointB,
PE_REF(Box) boxA, const Transform3 & transformA, PE_REF(Box) boxB,
const Transform3 & transformB,
float distanceThreshold = FLT_MAX );
#endif /* __BOXBOXDISTANCE_H__ */

View File

@@ -1 +1 @@
Empty placeholder for future Libspe2 SPU task
Empty placeholder for future Libspe2 SPU task

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,50 @@
#ifndef __SPU_RAYCAST_TASK_H
#define __SPU_RAYCAST_TASK_H
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "LinearMath/btVector3.h"
#include "../PlatformDefinitions.h"
ATTRIBUTE_ALIGNED16(struct) RaycastGatheredObjectData
{
ppu_address_t m_collisionShape;
void* m_spuCollisionShape;
btVector3 m_primitiveDimensions;
int m_shapeType;
float m_collisionMargin;
btTransform m_worldTransform;
};
ATTRIBUTE_ALIGNED16(struct) SpuRaycastTaskWorkUnitOut
{
btVector3 hitNormal; /* out */
btScalar hitFraction; /* out */
btCollisionWorld::LocalShapeInfo shapeInfo; /* out */
};
/* Perform a raycast on collision object */
ATTRIBUTE_ALIGNED16(struct) SpuRaycastTaskWorkUnit
{
btVector3 rayFrom; /* in */
btVector3 rayTo; /* in */
SpuRaycastTaskWorkUnitOut* output; /* out */
};
#define SPU_RAYCAST_WORK_UNITS_PER_TASK 16
ATTRIBUTE_ALIGNED128(struct) SpuRaycastTaskDesc
{
SpuRaycastTaskWorkUnit workUnits[SPU_RAYCAST_WORK_UNITS_PER_TASK];
unsigned int numWorkUnits;
void* spuCollisionObjectsWrappers;
unsigned int numSpuCollisionObjectWrappers;
int taskId;
};
void processRaycastTask (void* userPtr, void* lsMemory);
void* createRaycastLocalStoreMemory ();
#endif
#ifndef __SPU_RAYCAST_TASK_H
#define __SPU_RAYCAST_TASK_H
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "LinearMath/btVector3.h"
#include "../PlatformDefinitions.h"
ATTRIBUTE_ALIGNED16(struct) RaycastGatheredObjectData
{
ppu_address_t m_collisionShape;
void* m_spuCollisionShape;
btVector3 m_primitiveDimensions;
int m_shapeType;
float m_collisionMargin;
btTransform m_worldTransform;
};
ATTRIBUTE_ALIGNED16(struct) SpuRaycastTaskWorkUnitOut
{
btVector3 hitNormal; /* out */
btScalar hitFraction; /* out */
btCollisionWorld::LocalShapeInfo shapeInfo; /* out */
};
/* Perform a raycast on collision object */
ATTRIBUTE_ALIGNED16(struct) SpuRaycastTaskWorkUnit
{
btVector3 rayFrom; /* in */
btVector3 rayTo; /* in */
SpuRaycastTaskWorkUnitOut* output; /* out */
};
#define SPU_RAYCAST_WORK_UNITS_PER_TASK 16
ATTRIBUTE_ALIGNED128(struct) SpuRaycastTaskDesc
{
SpuRaycastTaskWorkUnit workUnits[SPU_RAYCAST_WORK_UNITS_PER_TASK];
unsigned int numWorkUnits;
void* spuCollisionObjectsWrappers;
unsigned int numSpuCollisionObjectWrappers;
int taskId;
};
void processRaycastTask (void* userPtr, void* lsMemory);
void* createRaycastLocalStoreMemory ();
#endif

View File

@@ -1,152 +1,152 @@
/*
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 "SpuSubSimplexConvexCast.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
SpuSubsimplexRayCast::SpuSubsimplexRayCast (void* shapeB, SpuConvexPolyhedronVertexData* convexDataB, int shapeTypeB, float marginB,
SpuVoronoiSimplexSolver* simplexSolver)
:m_simplexSolver(simplexSolver), m_shapeB(shapeB), m_convexDataB(convexDataB), m_shapeTypeB(shapeTypeB), m_marginB(marginB)
{
}
///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
#ifdef BT_USE_DOUBLE_PRECISION
#define MAX_ITERATIONS 64
#else
#define MAX_ITERATIONS 32
#endif
/* Returns the support point of the minkowski sum:
* MSUM(Pellet, ConvexShape)
*
*/
void supportPoints (const btTransform& xformRay,
const btTransform& xformB,
const int shapeType,
const void* shape,
SpuConvexPolyhedronVertexData* convexVertexData,
const btScalar marginB,
const btVector3& seperatingAxis,
btVector3& w,
btVector3& supVertexRay,
btVector3& supVertexB)
{
btVector3 saUnit = seperatingAxis;
saUnit.normalize();
btVector3 SupportPellet = xformRay(0.0001 * -saUnit);
btVector3 rotatedSeperatingAxis = seperatingAxis * xformB.getBasis();
btVector3 SupportShape = xformB(localGetSupportingVertexWithoutMargin(shapeType, (void*)shape, rotatedSeperatingAxis, convexVertexData));
SupportShape += saUnit * marginB;
w = SupportPellet - SupportShape;
supVertexRay = SupportPellet;
supVertexB = SupportShape;
}
bool SpuSubsimplexRayCast::calcTimeOfImpact(const btTransform& fromRay,
const btTransform& toRay,
const btTransform& fromB,
const btTransform& toB,
SpuCastResult& result)
{
m_simplexSolver->reset();
btVector3 linVelRay, linVelB;
linVelRay = toRay.getOrigin() - fromRay.getOrigin();
linVelB = toB.getOrigin() - fromB.getOrigin ();
btScalar lambda = btScalar(0.);
btTransform interpolatedTransRay = fromRay;
btTransform interpolatedTransB = fromB;
btVector3 r = (linVelRay-linVelB);
btVector3 supVertexRay;
btVector3 supVertexB;
btVector3 v;
supportPoints (fromRay, fromB, m_shapeTypeB, m_shapeB, m_convexDataB, m_marginB, r, v, supVertexRay, supVertexB);
btVector3 n;
n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
bool hasResult = false;
btVector3 c;
int maxIter = MAX_ITERATIONS;
btScalar lastLambda = lambda;
btScalar dist2 = v.length2();
#ifdef BT_USE_DOUBLE_PRECISION
btScalar epsilon = btScalar(0.0001);
#else
btScalar epsilon = btScalar(0.0001);
#endif //BT_USE_DOUBLE_PRECISION
btVector3 w,p;
btScalar VdotR;
while ( (dist2 > epsilon) && maxIter--)
{
supportPoints (interpolatedTransRay, interpolatedTransB, m_shapeTypeB, m_shapeB, m_convexDataB, m_marginB, v, w, supVertexRay, supVertexB);
btScalar VdotW = v.dot(w);
if (lambda > btScalar(1.0))
{
return false;
}
if ( VdotW > btScalar(0.))
{
VdotR = v.dot(r);
if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
return false;
else
{
lambda = lambda - VdotW / VdotR;
interpolatedTransRay.getOrigin().setInterpolate3(fromRay.getOrigin(), toRay.getOrigin(), lambda);
interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
lastLambda = lambda;
n = v;
hasResult = true;
}
}
m_simplexSolver->addVertex(w, supVertexRay, supVertexB);
if (m_simplexSolver->closest(v))
{
dist2 = v.length2();
hasResult = true;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices());
} else
{
dist2 = btScalar(0.);
}
}
result.m_fraction = lambda;
result.m_normal = n;
btVector3 hitRay, hitB;
m_simplexSolver->compute_points (hitRay, hitB);
/* TODO: We could output hit point here (hitB) */
return true;
}
/*
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 "SpuSubSimplexConvexCast.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
SpuSubsimplexRayCast::SpuSubsimplexRayCast (void* shapeB, SpuConvexPolyhedronVertexData* convexDataB, int shapeTypeB, float marginB,
SpuVoronoiSimplexSolver* simplexSolver)
:m_simplexSolver(simplexSolver), m_shapeB(shapeB), m_convexDataB(convexDataB), m_shapeTypeB(shapeTypeB), m_marginB(marginB)
{
}
///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
#ifdef BT_USE_DOUBLE_PRECISION
#define MAX_ITERATIONS 64
#else
#define MAX_ITERATIONS 32
#endif
/* Returns the support point of the minkowski sum:
* MSUM(Pellet, ConvexShape)
*
*/
void supportPoints (const btTransform& xformRay,
const btTransform& xformB,
const int shapeType,
const void* shape,
SpuConvexPolyhedronVertexData* convexVertexData,
const btScalar marginB,
const btVector3& seperatingAxis,
btVector3& w,
btVector3& supVertexRay,
btVector3& supVertexB)
{
btVector3 saUnit = seperatingAxis;
saUnit.normalize();
btVector3 SupportPellet = xformRay(0.0001 * -saUnit);
btVector3 rotatedSeperatingAxis = seperatingAxis * xformB.getBasis();
btVector3 SupportShape = xformB(localGetSupportingVertexWithoutMargin(shapeType, (void*)shape, rotatedSeperatingAxis, convexVertexData));
SupportShape += saUnit * marginB;
w = SupportPellet - SupportShape;
supVertexRay = SupportPellet;
supVertexB = SupportShape;
}
bool SpuSubsimplexRayCast::calcTimeOfImpact(const btTransform& fromRay,
const btTransform& toRay,
const btTransform& fromB,
const btTransform& toB,
SpuCastResult& result)
{
m_simplexSolver->reset();
btVector3 linVelRay, linVelB;
linVelRay = toRay.getOrigin() - fromRay.getOrigin();
linVelB = toB.getOrigin() - fromB.getOrigin ();
btScalar lambda = btScalar(0.);
btTransform interpolatedTransRay = fromRay;
btTransform interpolatedTransB = fromB;
btVector3 r = (linVelRay-linVelB);
btVector3 supVertexRay;
btVector3 supVertexB;
btVector3 v;
supportPoints (fromRay, fromB, m_shapeTypeB, m_shapeB, m_convexDataB, m_marginB, r, v, supVertexRay, supVertexB);
btVector3 n;
n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
bool hasResult = false;
btVector3 c;
int maxIter = MAX_ITERATIONS;
btScalar lastLambda = lambda;
btScalar dist2 = v.length2();
#ifdef BT_USE_DOUBLE_PRECISION
btScalar epsilon = btScalar(0.0001);
#else
btScalar epsilon = btScalar(0.0001);
#endif //BT_USE_DOUBLE_PRECISION
btVector3 w,p;
btScalar VdotR;
while ( (dist2 > epsilon) && maxIter--)
{
supportPoints (interpolatedTransRay, interpolatedTransB, m_shapeTypeB, m_shapeB, m_convexDataB, m_marginB, v, w, supVertexRay, supVertexB);
btScalar VdotW = v.dot(w);
if (lambda > btScalar(1.0))
{
return false;
}
if ( VdotW > btScalar(0.))
{
VdotR = v.dot(r);
if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
return false;
else
{
lambda = lambda - VdotW / VdotR;
interpolatedTransRay.getOrigin().setInterpolate3(fromRay.getOrigin(), toRay.getOrigin(), lambda);
interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
lastLambda = lambda;
n = v;
hasResult = true;
}
}
m_simplexSolver->addVertex(w, supVertexRay, supVertexB);
if (m_simplexSolver->closest(v))
{
dist2 = v.length2();
hasResult = true;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices());
} else
{
dist2 = btScalar(0.);
}
}
result.m_fraction = lambda;
result.m_normal = n;
btVector3 hitRay, hitB;
m_simplexSolver->compute_points (hitRay, hitB);
/* TODO: We could output hit point here (hitB) */
return true;
}

View File

@@ -1,60 +1,60 @@
/*
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 SPU_SUBSIMPLEX_RAY_CAST_H
#define SPU_SUBSIMPLEX_RAY_CAST_H
#include "../SpuNarrowPhaseCollisionTask/SpuVoronoiSimplexSolver.h"
#include "../SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
#include "SpuRaycastTask.h"
class btConvexShape;
struct SpuCastResult
{
float m_fraction;
btVector3 m_normal;
};
/// btSubsimplexConvexCast implements Gino van den Bergens' paper
///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
/// GJK based Ray Cast, optimized version
/// Objects should not start in overlap, otherwise results are not defined.
class SpuSubsimplexRayCast
{
SpuVoronoiSimplexSolver* m_simplexSolver;
void* m_shapeB;
SpuConvexPolyhedronVertexData* m_convexDataB;
int m_shapeTypeB;
float m_marginB;
public:
SpuSubsimplexRayCast (void* shapeB, SpuConvexPolyhedronVertexData* convexDataB, int shapeTypeB, float marginB,
SpuVoronoiSimplexSolver* simplexSolver);
//virtual ~btSubsimplexConvexCast();
///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
bool calcTimeOfImpact(const btTransform& fromRay,
const btTransform& toRay,
const btTransform& fromB,
const btTransform& toB,
SpuCastResult& result);
};
#endif //SUBSIMPLEX_RAY_CAST_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.
*/
#ifndef SPU_SUBSIMPLEX_RAY_CAST_H
#define SPU_SUBSIMPLEX_RAY_CAST_H
#include "../SpuNarrowPhaseCollisionTask/SpuVoronoiSimplexSolver.h"
#include "../SpuNarrowPhaseCollisionTask/SpuCollisionShapes.h"
#include "SpuRaycastTask.h"
class btConvexShape;
struct SpuCastResult
{
float m_fraction;
btVector3 m_normal;
};
/// btSubsimplexConvexCast implements Gino van den Bergens' paper
///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
/// GJK based Ray Cast, optimized version
/// Objects should not start in overlap, otherwise results are not defined.
class SpuSubsimplexRayCast
{
SpuVoronoiSimplexSolver* m_simplexSolver;
void* m_shapeB;
SpuConvexPolyhedronVertexData* m_convexDataB;
int m_shapeTypeB;
float m_marginB;
public:
SpuSubsimplexRayCast (void* shapeB, SpuConvexPolyhedronVertexData* convexDataB, int shapeTypeB, float marginB,
SpuVoronoiSimplexSolver* simplexSolver);
//virtual ~btSubsimplexConvexCast();
///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
bool calcTimeOfImpact(const btTransform& fromRay,
const btTransform& toRay,
const btTransform& fromB,
const btTransform& toB,
SpuCastResult& result);
};
#endif //SUBSIMPLEX_RAY_CAST_H

View File

@@ -1,189 +1,189 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SpuRaycastTaskProcess.h"
SpuRaycastTaskProcess::SpuRaycastTaskProcess(class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks)
:m_threadInterface(threadInterface),
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
{
m_workUnitTaskBuffers = (unsigned char *)0;
m_taskBusy.resize(m_maxNumOutstandingTasks);
m_spuRaycastTaskDesc.resize(m_maxNumOutstandingTasks);
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
m_threadInterface->startSPU();
//printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
//printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", sizeof(SpuGatherAndProcessWorkUnitInput));
}
SpuRaycastTaskProcess::~SpuRaycastTaskProcess()
{
if (m_workUnitTaskBuffers != 0)
{
btAlignedFree(m_workUnitTaskBuffers);
m_workUnitTaskBuffers = 0;
}
m_threadInterface->stopSPU();
}
void SpuRaycastTaskProcess::initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers)
{
m_spuCollisionObjectWrappers = spuCollisionObjectsWrappers;
m_numSpuCollisionObjectWrappers = numSpuCollisionObjectWrappers;
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
#ifdef DEBUG_SpuRaycastTaskProcess
m_initialized = true;
#endif
}
void SpuRaycastTaskProcess::issueTask2()
{
m_taskBusy[m_currentTask] = true;
m_numBusyTasks++;
SpuRaycastTaskDesc& taskDesc = m_spuRaycastTaskDesc[m_currentTask];
taskDesc.taskId = m_currentTask;
m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc,m_currentTask);
//printf("send thread requested for task %d\n", m_currentTask);
// if all tasks busy, wait for spu event to clear the task.
if (m_numBusyTasks >= m_maxNumOutstandingTasks)
{
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
m_threadInterface->waitForResponse(&taskId, &outputSize);
//printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
} else {
//printf("Sent request, not enough busy tasks\n");
}
}
void SpuRaycastTaskProcess::addWorkToTask(SpuRaycastTaskWorkUnit& workunit)
{
m_spuRaycastTaskDesc[m_currentTask].workUnits[m_currentWorkUnitInTask] = workunit;
m_currentWorkUnitInTask++;
if (m_currentWorkUnitInTask == SPU_RAYCAST_WORK_UNITS_PER_TASK)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
//printf("Task buffer full, issuing\n");
issueTask2 ();
//printf("Returned from issueTask2()\n");
m_currentWorkUnitInTask = 0;
// find new task buffer
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
if (!m_taskBusy[i])
{
m_currentTask = i;
//init the task data
break;
}
}
//printf("next task = %d\n", m_currentTask);
}
}
void
SpuRaycastTaskProcess::flush2()
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("\nSpuRaycastTaskProcess::flush()\n");
#endif //DEBUG_SPU_TASK_SCHEDULING
// if there's a partially filled task buffer, submit that task
//printf("Flushing... %d remaining\n", m_currentWorkUnitInTask);
if (m_currentWorkUnitInTask > 0)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
issueTask2();
m_currentWorkUnitInTask = 0;
}
// all tasks are issued, wait for all tasks to be complete
while(m_numBusyTasks > 0)
{
// Consolidating SPU code
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
//printf("Busy tasks... %d\n", m_numBusyTasks);
{
// SPURS support.
m_threadInterface->waitForResponse(&taskId, &outputSize);
}
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
//postProcess(taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
}
}
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "SpuRaycastTaskProcess.h"
SpuRaycastTaskProcess::SpuRaycastTaskProcess(class btThreadSupportInterface* threadInterface, int maxNumOutstandingTasks)
:m_threadInterface(threadInterface),
m_maxNumOutstandingTasks(maxNumOutstandingTasks)
{
m_workUnitTaskBuffers = (unsigned char *)0;
m_taskBusy.resize(m_maxNumOutstandingTasks);
m_spuRaycastTaskDesc.resize(m_maxNumOutstandingTasks);
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
m_threadInterface->startSPU();
//printf("sizeof vec_float4: %d\n", sizeof(vec_float4));
//printf("sizeof SpuGatherAndProcessWorkUnitInput: %d\n", sizeof(SpuGatherAndProcessWorkUnitInput));
}
SpuRaycastTaskProcess::~SpuRaycastTaskProcess()
{
if (m_workUnitTaskBuffers != 0)
{
btAlignedFree(m_workUnitTaskBuffers);
m_workUnitTaskBuffers = 0;
}
m_threadInterface->stopSPU();
}
void SpuRaycastTaskProcess::initialize2(void* spuCollisionObjectsWrappers, int numSpuCollisionObjectWrappers)
{
m_spuCollisionObjectWrappers = spuCollisionObjectsWrappers;
m_numSpuCollisionObjectWrappers = numSpuCollisionObjectWrappers;
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
m_taskBusy[i] = false;
}
m_numBusyTasks = 0;
m_currentTask = 0;
m_currentWorkUnitInTask = 0;
#ifdef DEBUG_SpuRaycastTaskProcess
m_initialized = true;
#endif
}
void SpuRaycastTaskProcess::issueTask2()
{
m_taskBusy[m_currentTask] = true;
m_numBusyTasks++;
SpuRaycastTaskDesc& taskDesc = m_spuRaycastTaskDesc[m_currentTask];
taskDesc.taskId = m_currentTask;
m_threadInterface->sendRequest(1, (ppu_address_t) &taskDesc,m_currentTask);
//printf("send thread requested for task %d\n", m_currentTask);
// if all tasks busy, wait for spu event to clear the task.
if (m_numBusyTasks >= m_maxNumOutstandingTasks)
{
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
m_threadInterface->waitForResponse(&taskId, &outputSize);
//printf("PPU: after issue, received event: %u %d\n", taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
} else {
//printf("Sent request, not enough busy tasks\n");
}
}
void SpuRaycastTaskProcess::addWorkToTask(SpuRaycastTaskWorkUnit& workunit)
{
m_spuRaycastTaskDesc[m_currentTask].workUnits[m_currentWorkUnitInTask] = workunit;
m_currentWorkUnitInTask++;
if (m_currentWorkUnitInTask == SPU_RAYCAST_WORK_UNITS_PER_TASK)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
//printf("Task buffer full, issuing\n");
issueTask2 ();
//printf("Returned from issueTask2()\n");
m_currentWorkUnitInTask = 0;
// find new task buffer
for (int i = 0; i < m_maxNumOutstandingTasks; i++)
{
if (!m_taskBusy[i])
{
m_currentTask = i;
//init the task data
break;
}
}
//printf("next task = %d\n", m_currentTask);
}
}
void
SpuRaycastTaskProcess::flush2()
{
#ifdef DEBUG_SPU_TASK_SCHEDULING
printf("\nSpuRaycastTaskProcess::flush()\n");
#endif //DEBUG_SPU_TASK_SCHEDULING
// if there's a partially filled task buffer, submit that task
//printf("Flushing... %d remaining\n", m_currentWorkUnitInTask);
if (m_currentWorkUnitInTask > 0)
{
m_spuRaycastTaskDesc[m_currentTask].numWorkUnits = m_currentWorkUnitInTask;
m_spuRaycastTaskDesc[m_currentTask].numSpuCollisionObjectWrappers = m_numSpuCollisionObjectWrappers;
m_spuRaycastTaskDesc[m_currentTask].spuCollisionObjectsWrappers = m_spuCollisionObjectWrappers;
issueTask2();
m_currentWorkUnitInTask = 0;
}
// all tasks are issued, wait for all tasks to be complete
while(m_numBusyTasks > 0)
{
// Consolidating SPU code
unsigned int taskId;
unsigned int outputSize;
for (int i=0;i<m_maxNumOutstandingTasks;i++)
{
if (m_taskBusy[i])
{
taskId = i;
break;
}
}
//printf("Busy tasks... %d\n", m_numBusyTasks);
{
// SPURS support.
m_threadInterface->waitForResponse(&taskId, &outputSize);
}
//printf("PPU: flushing, received event: %u %d\n", taskId, outputSize);
//postProcess(taskId, outputSize);
m_taskBusy[taskId] = false;
m_numBusyTasks--;
}
}

View File

@@ -1,214 +1,214 @@
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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 "SpuSampleTask.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "../PlatformDefinitions.h"
#include "../SpuFakeDma.h"
#include "LinearMath/btMinMax.h"
#ifdef __SPU__
#include <spu_printf.h>
#else
#include <stdio.h>
#define spu_printf printf
#endif
#define MAX_NUM_BODIES 8192
struct SampleTask_LocalStoreMemory
{
ATTRIBUTE_ALIGNED16(char gLocalRigidBody [sizeof(btRigidBody)+16]);
ATTRIBUTE_ALIGNED16(void* gPointerArray[MAX_NUM_BODIES]);
};
//-- MAIN METHOD
void processSampleTask(void* userPtr, void* lsMemory)
{
// BT_PROFILE("processSampleTask");
SampleTask_LocalStoreMemory* localMemory = (SampleTask_LocalStoreMemory*)lsMemory;
SpuSampleTaskDesc* taskDescPtr = (SpuSampleTaskDesc*)userPtr;
SpuSampleTaskDesc& taskDesc = *taskDescPtr;
switch (taskDesc.m_sampleCommand)
{
case CMD_SAMPLE_INTEGRATE_BODIES:
{
btTransform predictedTrans;
btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr;
int batchSize = taskDesc.m_sampleValue;
if (batchSize>MAX_NUM_BODIES)
{
spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n");
break;
}
int dmaArraySize = batchSize*sizeof(void*);
uint64_t ppuArrayAddress = reinterpret_cast<uint64_t>(eaPtr);
// spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize);
if (dmaArraySize>=16)
{
cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
} else
{
stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize);
}
for ( int i=0;i<batchSize;i++)
{
///DMA rigid body
void* localPtr = &localMemory->gLocalRigidBody[0];
void* shortAdd = localMemory->gPointerArray[i];
uint64_t ppuRigidBodyAddress = reinterpret_cast<uint64_t>(shortAdd);
// spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr);
int dmaBodySize = sizeof(btRigidBody);
cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
float timeStep = 1.f/60.f;
btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticOrKinematicObject()))
{
body->predictIntegratedTransform(timeStep, predictedTrans);
body->proceedToTransform( predictedTrans);
void* ptr = (void*)localPtr;
// spu_printf("cellDmaLargePut from %llx to LS %llx\n",ptr,ppuRigidBodyAddress);
cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
}
}
break;
}
case CMD_SAMPLE_PREDICT_MOTION_BODIES:
{
btTransform predictedTrans;
btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr;
int batchSize = taskDesc.m_sampleValue;
int dmaArraySize = batchSize*sizeof(void*);
if (batchSize>MAX_NUM_BODIES)
{
spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n");
break;
}
uint64_t ppuArrayAddress = reinterpret_cast<uint64_t>(eaPtr);
// spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize);
if (dmaArraySize>=16)
{
cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
} else
{
stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize);
}
for ( int i=0;i<batchSize;i++)
{
///DMA rigid body
void* localPtr = &localMemory->gLocalRigidBody[0];
void* shortAdd = localMemory->gPointerArray[i];
uint64_t ppuRigidBodyAddress = reinterpret_cast<uint64_t>(shortAdd);
// spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr);
int dmaBodySize = sizeof(btRigidBody);
cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
float timeStep = 1.f/60.f;
btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj);
if (body)
{
if (!body->isStaticOrKinematicObject())
{
if (body->isActive())
{
body->integrateVelocities( timeStep);
//damping
body->applyDamping(timeStep);
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
void* ptr = (void*)localPtr;
cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
}
}
}
break;
}
default:
{
}
};
}
#if defined(__CELLOS_LV2__) || defined (LIBSPE2)
ATTRIBUTE_ALIGNED16(SampleTask_LocalStoreMemory gLocalStoreMemory);
void* createSampleLocalStoreMemory()
{
return &gLocalStoreMemory;
}
#else
void* createSampleLocalStoreMemory()
{
return new SampleTask_LocalStoreMemory;
};
#endif
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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 "SpuSampleTask.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "../PlatformDefinitions.h"
#include "../SpuFakeDma.h"
#include "LinearMath/btMinMax.h"
#ifdef __SPU__
#include <spu_printf.h>
#else
#include <stdio.h>
#define spu_printf printf
#endif
#define MAX_NUM_BODIES 8192
struct SampleTask_LocalStoreMemory
{
ATTRIBUTE_ALIGNED16(char gLocalRigidBody [sizeof(btRigidBody)+16]);
ATTRIBUTE_ALIGNED16(void* gPointerArray[MAX_NUM_BODIES]);
};
//-- MAIN METHOD
void processSampleTask(void* userPtr, void* lsMemory)
{
// BT_PROFILE("processSampleTask");
SampleTask_LocalStoreMemory* localMemory = (SampleTask_LocalStoreMemory*)lsMemory;
SpuSampleTaskDesc* taskDescPtr = (SpuSampleTaskDesc*)userPtr;
SpuSampleTaskDesc& taskDesc = *taskDescPtr;
switch (taskDesc.m_sampleCommand)
{
case CMD_SAMPLE_INTEGRATE_BODIES:
{
btTransform predictedTrans;
btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr;
int batchSize = taskDesc.m_sampleValue;
if (batchSize>MAX_NUM_BODIES)
{
spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n");
break;
}
int dmaArraySize = batchSize*sizeof(void*);
uint64_t ppuArrayAddress = reinterpret_cast<uint64_t>(eaPtr);
// spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize);
if (dmaArraySize>=16)
{
cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
} else
{
stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize);
}
for ( int i=0;i<batchSize;i++)
{
///DMA rigid body
void* localPtr = &localMemory->gLocalRigidBody[0];
void* shortAdd = localMemory->gPointerArray[i];
uint64_t ppuRigidBodyAddress = reinterpret_cast<uint64_t>(shortAdd);
// spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr);
int dmaBodySize = sizeof(btRigidBody);
cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
float timeStep = 1.f/60.f;
btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj);
if (body)
{
if (body->isActive() && (!body->isStaticOrKinematicObject()))
{
body->predictIntegratedTransform(timeStep, predictedTrans);
body->proceedToTransform( predictedTrans);
void* ptr = (void*)localPtr;
// spu_printf("cellDmaLargePut from %llx to LS %llx\n",ptr,ppuRigidBodyAddress);
cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
}
}
break;
}
case CMD_SAMPLE_PREDICT_MOTION_BODIES:
{
btTransform predictedTrans;
btCollisionObject** eaPtr = (btCollisionObject**)taskDesc.m_mainMemoryPtr;
int batchSize = taskDesc.m_sampleValue;
int dmaArraySize = batchSize*sizeof(void*);
if (batchSize>MAX_NUM_BODIES)
{
spu_printf("SPU Error: exceed number of bodies, see MAX_NUM_BODIES in SpuSampleTask.cpp\n");
break;
}
uint64_t ppuArrayAddress = reinterpret_cast<uint64_t>(eaPtr);
// spu_printf("array location is at %llx, batchSize = %d, DMA size = %d\n",ppuArrayAddress,batchSize,dmaArraySize);
if (dmaArraySize>=16)
{
cellDmaLargeGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
} else
{
stallingUnalignedDmaSmallGet((void*)&localMemory->gPointerArray[0], ppuArrayAddress , dmaArraySize);
}
for ( int i=0;i<batchSize;i++)
{
///DMA rigid body
void* localPtr = &localMemory->gLocalRigidBody[0];
void* shortAdd = localMemory->gPointerArray[i];
uint64_t ppuRigidBodyAddress = reinterpret_cast<uint64_t>(shortAdd);
// spu_printf("cellDmaGet at CMD_SAMPLE_INTEGRATE_BODIES from %llx to %llx\n",ppuRigidBodyAddress,localPtr);
int dmaBodySize = sizeof(btRigidBody);
cellDmaGet((void*)localPtr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
float timeStep = 1.f/60.f;
btRigidBody* body = (btRigidBody*) localPtr;//btRigidBody::upcast(colObj);
if (body)
{
if (!body->isStaticOrKinematicObject())
{
if (body->isActive())
{
body->integrateVelocities( timeStep);
//damping
body->applyDamping(timeStep);
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
void* ptr = (void*)localPtr;
cellDmaLargePut(ptr, ppuRigidBodyAddress , dmaBodySize, DMA_TAG(1), 0, 0);
cellDmaWaitTagStatusAll(DMA_MASK(1));
}
}
}
}
break;
}
default:
{
}
};
}
#if defined(__CELLOS_LV2__) || defined (LIBSPE2)
ATTRIBUTE_ALIGNED16(SampleTask_LocalStoreMemory gLocalStoreMemory);
void* createSampleLocalStoreMemory()
{
return &gLocalStoreMemory;
}
#else
void* createSampleLocalStoreMemory()
{
return new SampleTask_LocalStoreMemory;
};
#endif

View File

@@ -1,54 +1,54 @@
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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 SPU_SAMPLE_TASK_H
#define SPU_SAMPLE_TASK_H
#include "../PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btAlignedAllocator.h"
enum
{
CMD_SAMPLE_INTEGRATE_BODIES = 1,
CMD_SAMPLE_PREDICT_MOTION_BODIES
};
ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_sampleCommand;
uint32_t m_taskId;
uint64_t m_mainMemoryPtr;
int m_sampleValue;
};
void processSampleTask(void* userPtr, void* lsMemory);
void* createSampleLocalStoreMemory();
#endif //SPU_SAMPLE_TASK_H
/*
Bullet Continuous Collision Detection and Physics Library, Copyright (c) 2007 Erwin Coumans
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 SPU_SAMPLE_TASK_H
#define SPU_SAMPLE_TASK_H
#include "../PlatformDefinitions.h"
#include "LinearMath/btScalar.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "LinearMath/btAlignedAllocator.h"
enum
{
CMD_SAMPLE_INTEGRATE_BODIES = 1,
CMD_SAMPLE_PREDICT_MOTION_BODIES
};
ATTRIBUTE_ALIGNED16(struct) SpuSampleTaskDesc
{
BT_DECLARE_ALIGNED_ALLOCATOR();
uint32_t m_sampleCommand;
uint32_t m_taskId;
uint64_t m_mainMemoryPtr;
int m_sampleValue;
};
void processSampleTask(void* userPtr, void* lsMemory);
void* createSampleLocalStoreMemory();
#endif //SPU_SAMPLE_TASK_H

View File

@@ -1 +1 @@
Empty placeholder for future Libspe2 SPU task
Empty placeholder for future Libspe2 SPU task

View File

@@ -1,259 +1,259 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "Win32ThreadSupport.h"
#ifdef USE_WIN32_THREADING
#include <windows.h>
#include "SpuCollisionTaskProcess.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
///The number of threads should be equal to the number of available cores
///@todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
///Setup and initialize SPU/CELL/Libspe2
Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo)
{
startThreads(threadConstructionInfo);
}
///cleanup/shutdown Libspe2
Win32ThreadSupport::~Win32ThreadSupport()
{
stopSPU();
}
#include <stdio.h>
DWORD WINAPI Thread_no_1( LPVOID lpParam )
{
Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam;
while (1)
{
WaitForSingleObject(status->m_eventStartHandle,INFINITE);
void* userPtr = status->m_userPtr;
if (userPtr)
{
btAssert(status->m_status);
status->m_userThreadFunc(userPtr,status->m_lsMemory);
status->m_status = 2;
SetEvent(status->m_eventCompletetHandle);
} else
{
//exit Thread
status->m_status = 3;
SetEvent(status->m_eventCompletetHandle);
printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle);
break;
}
}
printf("Thread TERMINATED\n");
return 0;
}
///send messages to SPUs
void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
{
/// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc);
///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
switch (uiCommand)
{
case CMD_GATHER_AND_PROCESS_PAIRLIST:
{
//#define SINGLE_THREADED 1
#ifdef SINGLE_THREADED
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr=(void*)uiArgument0;
spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
HANDLE handle =0;
#else
btSpuStatus& spuStatus = m_activeSpuStatus[taskId];
btAssert(taskId>=0);
btAssert(taskId<m_activeSpuStatus.size());
spuStatus.m_commandId = uiCommand;
spuStatus.m_status = 1;
spuStatus.m_userPtr = (void*)uiArgument0;
///fire event to start new task
SetEvent(spuStatus.m_eventStartHandle);
#endif //CollisionTask_LocalStoreMemory
break;
}
default:
{
///not implemented
btAssert(0);
}
};
}
///check for messages from SPUs
void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
{
///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
btAssert(m_activeSpuStatus.size());
int last = -1;
#ifndef SINGLE_THREADED
DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
btAssert(res != WAIT_FAILED);
last = res - WAIT_OBJECT_0;
btSpuStatus& spuStatus = m_activeSpuStatus[last];
btAssert(spuStatus.m_threadHandle);
btAssert(spuStatus.m_eventCompletetHandle);
//WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
btAssert(spuStatus.m_status > 1);
spuStatus.m_status = 0;
///need to find an active spu
btAssert(last>=0);
#else
last=0;
btSpuStatus& spuStatus = m_activeSpuStatus[last];
#endif //SINGLE_THREADED
*puiArgument0 = spuStatus.m_taskId;
*puiArgument1 = spuStatus.m_status;
}
void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo)
{
m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
m_completeHandles.resize(threadConstructionInfo.m_numThreads);
for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
{
printf("starting thread %d\n",i);
btSpuStatus& spuStatus = m_activeSpuStatus[i];
LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
LPVOID lpParameter=&spuStatus;
DWORD dwCreationFlags=0;
LPDWORD lpThreadId=0;
spuStatus.m_userPtr=0;
sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
spuStatus.m_eventStartHandle = CreateEvent(0,false,false,spuStatus.m_eventStartHandleName);
sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
spuStatus.m_eventCompletetHandle = CreateEvent(0,false,false,spuStatus.m_eventCompletetHandleName);
m_completeHandles[i] = spuStatus.m_eventCompletetHandle;
HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId);
SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
//SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL);
SetThreadAffinityMask(handle, 1<<i);
spuStatus.m_taskId = i;
spuStatus.m_commandId = 0;
spuStatus.m_status = 0;
spuStatus.m_threadHandle = handle;
spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
printf("started thread %d with threadHandle %p\n",i,handle);
}
}
void Win32ThreadSupport::startSPU()
{
}
///tell the task scheduler we are done with the SPU tasks
void Win32ThreadSupport::stopSPU()
{
int i;
for (i=0;i<m_activeSpuStatus.size();i++)
{
btSpuStatus& spuStatus = m_activeSpuStatus[i];
if (spuStatus.m_status>0)
{
WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
}
spuStatus.m_userPtr = 0;
SetEvent(spuStatus.m_eventStartHandle);
WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
CloseHandle(spuStatus.m_eventCompletetHandle);
CloseHandle(spuStatus.m_eventStartHandle);
CloseHandle(spuStatus.m_threadHandle);
}
m_activeSpuStatus.clear();
m_completeHandles.clear();
}
#endif //USE_WIN32_THREADING
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "Win32ThreadSupport.h"
#ifdef USE_WIN32_THREADING
#include <windows.h>
#include "SpuCollisionTaskProcess.h"
#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
///The number of threads should be equal to the number of available cores
///@todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
///Setup and initialize SPU/CELL/Libspe2
Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo)
{
startThreads(threadConstructionInfo);
}
///cleanup/shutdown Libspe2
Win32ThreadSupport::~Win32ThreadSupport()
{
stopSPU();
}
#include <stdio.h>
DWORD WINAPI Thread_no_1( LPVOID lpParam )
{
Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam;
while (1)
{
WaitForSingleObject(status->m_eventStartHandle,INFINITE);
void* userPtr = status->m_userPtr;
if (userPtr)
{
btAssert(status->m_status);
status->m_userThreadFunc(userPtr,status->m_lsMemory);
status->m_status = 2;
SetEvent(status->m_eventCompletetHandle);
} else
{
//exit Thread
status->m_status = 3;
SetEvent(status->m_eventCompletetHandle);
printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle);
break;
}
}
printf("Thread TERMINATED\n");
return 0;
}
///send messages to SPUs
void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
{
/// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (ppu_address_t) &taskDesc);
///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
switch (uiCommand)
{
case CMD_GATHER_AND_PROCESS_PAIRLIST:
{
//#define SINGLE_THREADED 1
#ifdef SINGLE_THREADED
btSpuStatus& spuStatus = m_activeSpuStatus[0];
spuStatus.m_userPtr=(void*)uiArgument0;
spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
HANDLE handle =0;
#else
btSpuStatus& spuStatus = m_activeSpuStatus[taskId];
btAssert(taskId>=0);
btAssert(taskId<m_activeSpuStatus.size());
spuStatus.m_commandId = uiCommand;
spuStatus.m_status = 1;
spuStatus.m_userPtr = (void*)uiArgument0;
///fire event to start new task
SetEvent(spuStatus.m_eventStartHandle);
#endif //CollisionTask_LocalStoreMemory
break;
}
default:
{
///not implemented
btAssert(0);
}
};
}
///check for messages from SPUs
void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
{
///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
btAssert(m_activeSpuStatus.size());
int last = -1;
#ifndef SINGLE_THREADED
DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
btAssert(res != WAIT_FAILED);
last = res - WAIT_OBJECT_0;
btSpuStatus& spuStatus = m_activeSpuStatus[last];
btAssert(spuStatus.m_threadHandle);
btAssert(spuStatus.m_eventCompletetHandle);
//WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
btAssert(spuStatus.m_status > 1);
spuStatus.m_status = 0;
///need to find an active spu
btAssert(last>=0);
#else
last=0;
btSpuStatus& spuStatus = m_activeSpuStatus[last];
#endif //SINGLE_THREADED
*puiArgument0 = spuStatus.m_taskId;
*puiArgument1 = spuStatus.m_status;
}
void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo)
{
m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
m_completeHandles.resize(threadConstructionInfo.m_numThreads);
for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
{
printf("starting thread %d\n",i);
btSpuStatus& spuStatus = m_activeSpuStatus[i];
LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
LPVOID lpParameter=&spuStatus;
DWORD dwCreationFlags=0;
LPDWORD lpThreadId=0;
spuStatus.m_userPtr=0;
sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
spuStatus.m_eventStartHandle = CreateEvent(0,false,false,spuStatus.m_eventStartHandleName);
sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
spuStatus.m_eventCompletetHandle = CreateEvent(0,false,false,spuStatus.m_eventCompletetHandleName);
m_completeHandles[i] = spuStatus.m_eventCompletetHandle;
HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId);
SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
//SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL);
SetThreadAffinityMask(handle, 1<<i);
spuStatus.m_taskId = i;
spuStatus.m_commandId = 0;
spuStatus.m_status = 0;
spuStatus.m_threadHandle = handle;
spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
printf("started thread %d with threadHandle %p\n",i,handle);
}
}
void Win32ThreadSupport::startSPU()
{
}
///tell the task scheduler we are done with the SPU tasks
void Win32ThreadSupport::stopSPU()
{
int i;
for (i=0;i<m_activeSpuStatus.size();i++)
{
btSpuStatus& spuStatus = m_activeSpuStatus[i];
if (spuStatus.m_status>0)
{
WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
}
spuStatus.m_userPtr = 0;
SetEvent(spuStatus.m_eventStartHandle);
WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
CloseHandle(spuStatus.m_eventCompletetHandle);
CloseHandle(spuStatus.m_eventStartHandle);
CloseHandle(spuStatus.m_threadHandle);
}
m_activeSpuStatus.clear();
m_completeHandles.clear();
}
#endif //USE_WIN32_THREADING

View File

@@ -1,125 +1,125 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h
#ifndef WIN32_THREAD_SUPPORT_H
#define WIN32_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*Win32lsMemorySetupFunc)();
///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class Win32ThreadSupport : public btThreadSupportInterface
{
public:
///placeholder, until libspe2 support is there
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
Win32ThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc
void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
void* m_eventStartHandle;
char m_eventStartHandleName[32];
void* m_eventCompletetHandle;
char m_eventCompletetHandleName[32];
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
public:
///Setup and initialize SPU/CELL/Libspe2
struct Win32ThreadConstructionInfo
{
Win32ThreadConstructionInfo(char* uniqueName,
Win32ThreadFunc userThreadFunc,
Win32lsMemorySetupFunc lsMemoryFunc,
int numThreads=1,
int threadStackSize=65535
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc),
m_numThreads(numThreads),
m_threadStackSize(threadStackSize)
{
}
char* m_uniqueName;
Win32ThreadFunc m_userThreadFunc;
Win32lsMemorySetupFunc m_lsMemoryFunc;
int m_numThreads;
int m_threadStackSize;
};
Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo);
///cleanup/shutdown Libspe2
virtual ~Win32ThreadSupport();
void startThreads(const Win32ThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks)
{
}
};
#endif //WIN32_THREAD_SUPPORT_H
#endif //USE_WIN32_THREADING
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
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 "LinearMath/btScalar.h"
#include "PlatformDefinitions.h"
#ifdef USE_WIN32_THREADING //platform specific defines are defined in PlatformDefinitions.h
#ifndef WIN32_THREAD_SUPPORT_H
#define WIN32_THREAD_SUPPORT_H
#include "LinearMath/btAlignedObjectArray.h"
#include "btThreadSupportInterface.h"
typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory);
typedef void* (*Win32lsMemorySetupFunc)();
///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class Win32ThreadSupport : public btThreadSupportInterface
{
public:
///placeholder, until libspe2 support is there
struct btSpuStatus
{
uint32_t m_taskId;
uint32_t m_commandId;
uint32_t m_status;
Win32ThreadFunc m_userThreadFunc;
void* m_userPtr; //for taskDesc etc
void* m_lsMemory; //initialized using Win32LocalStoreMemorySetupFunc
void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
void* m_eventStartHandle;
char m_eventStartHandleName[32];
void* m_eventCompletetHandle;
char m_eventCompletetHandleName[32];
};
private:
btAlignedObjectArray<btSpuStatus> m_activeSpuStatus;
btAlignedObjectArray<void*> m_completeHandles;
public:
///Setup and initialize SPU/CELL/Libspe2
struct Win32ThreadConstructionInfo
{
Win32ThreadConstructionInfo(char* uniqueName,
Win32ThreadFunc userThreadFunc,
Win32lsMemorySetupFunc lsMemoryFunc,
int numThreads=1,
int threadStackSize=65535
)
:m_uniqueName(uniqueName),
m_userThreadFunc(userThreadFunc),
m_lsMemoryFunc(lsMemoryFunc),
m_numThreads(numThreads),
m_threadStackSize(threadStackSize)
{
}
char* m_uniqueName;
Win32ThreadFunc m_userThreadFunc;
Win32lsMemorySetupFunc m_lsMemoryFunc;
int m_numThreads;
int m_threadStackSize;
};
Win32ThreadSupport(const Win32ThreadConstructionInfo& threadConstructionInfo);
///cleanup/shutdown Libspe2
virtual ~Win32ThreadSupport();
void startThreads(const Win32ThreadConstructionInfo& threadInfo);
///send messages to SPUs
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1);
///check for messages from SPUs
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
///start the spus (can be called at the beginning of each frame, to make sure that the right SPU program is loaded)
virtual void startSPU();
///tell the task scheduler we are done with the SPU tasks
virtual void stopSPU();
virtual void setNumTasks(int numTasks)
{
}
};
#endif //WIN32_THREAD_SUPPORT_H
#endif //USE_WIN32_THREADING

View File

@@ -1,73 +1,73 @@
/*
Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
All rights reserved.
Redistribution and use in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Sony Computer Entertainment Inc nor the names
of its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AOS_VECTORMATH_BULLET_CONVERT_H
#define AOS_VECTORMATH_BULLET_CONVERT_H
#include <vectormath_aos.h>
#include "LinearMath/btVector3.h"
#include "LinearMath/btQuaternion.h"
#include "LinearMath/btMatrix3x3.h"
inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec)
{
return Vectormath::Aos::Vector3(bulletVec.getX(),bulletVec.getY(),bulletVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat)
{
Vectormath::Aos::Quat vmQuat(bulletQuat.getX(),bulletQuat.getY(),bulletQuat.getZ(),bulletQuat.getW());
return vmQuat;
}
inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat)
{
return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW());
}
inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat)
{
Vectormath::Aos::Matrix3 mat(
getVmVector3(btMat.getColumn(0)),
getVmVector3(btMat.getColumn(1)),
getVmVector3(btMat.getColumn(2)));
return mat;
}
#endif //AOS_VECTORMATH_BULLET_CONVERT_H
/*
Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
All rights reserved.
Redistribution and use in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Sony Computer Entertainment Inc nor the names
of its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AOS_VECTORMATH_BULLET_CONVERT_H
#define AOS_VECTORMATH_BULLET_CONVERT_H
#include <vectormath_aos.h>
#include "LinearMath/btVector3.h"
#include "LinearMath/btQuaternion.h"
#include "LinearMath/btMatrix3x3.h"
inline Vectormath::Aos::Vector3 getVmVector3(const btVector3& bulletVec)
{
return Vectormath::Aos::Vector3(bulletVec.getX(),bulletVec.getY(),bulletVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Vector3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline btVector3 getBtVector3(const Vectormath::Aos::Point3& vmVec)
{
return btVector3(vmVec.getX(),vmVec.getY(),vmVec.getZ());
}
inline Vectormath::Aos::Quat getVmQuat(const btQuaternion& bulletQuat)
{
Vectormath::Aos::Quat vmQuat(bulletQuat.getX(),bulletQuat.getY(),bulletQuat.getZ(),bulletQuat.getW());
return vmQuat;
}
inline btQuaternion getBtQuat(const Vectormath::Aos::Quat& vmQuat)
{
return btQuaternion (vmQuat.getX(),vmQuat.getY(),vmQuat.getZ(),vmQuat.getW());
}
inline Vectormath::Aos::Matrix3 getVmMatrix3(const btMatrix3x3& btMat)
{
Vectormath::Aos::Matrix3 mat(
getVmVector3(btMat.getColumn(0)),
getVmVector3(btMat.getColumn(1)),
getVmVector3(btMat.getColumn(2)));
return mat;
}
#endif //AOS_VECTORMATH_BULLET_CONVERT_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,369 +1,369 @@
/*
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 "btSoftBodyConcaveCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletSoftBody/btSoftBody.h"
#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
: btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
{
}
btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
{
}
btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
m_softBody = (btSoftBody*) (isSwapped? body1:body0);
m_triBody = isSwapped? body0:body1;
//
// create the manifold from the dispatcher 'manifold pool'
//
// m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
clearCache();
}
btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
{
clearCache();
// m_dispatcher->releaseManifold( m_manifoldPtr );
}
void btSoftBodyTriangleCallback::clearCache()
{
for (int i=0;i<m_shapeCache.size();i++)
{
btTriIndex* tmp = m_shapeCache.getAtIndex(i);
btAssert(tmp);
btAssert(tmp->m_childShape);
m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary?
delete tmp->m_childShape;
}
m_shapeCache.clear();
}
void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
///debug drawing of the overlapping triangles
if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0)
{
btVector3 color(255,255,0);
btTransform& tr = ob->getWorldTransform();
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
}
btTriIndex triIndex(partId,triangleIndex,0);
btHashKey<btTriIndex> triKey(triIndex.getUid());
btTriIndex* shapeIndex = m_shapeCache[triKey];
if (shapeIndex)
{
btCollisionShape* tm = shapeIndex->m_childShape;
btAssert(tm);
//copy over user pointers to temporary shape
tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
btCollisionShape* tmpShape = ob->getCollisionShape();
ob->internalSetTemporaryCollisionShape( tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape);
return;
}
//aabb filter is already applied!
//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
// if (m_softBody->getCollisionShape()->getShapeType()==
{
// btVector3 other;
btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
normal.normalize();
normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
// other+=normal*22.f;
btVector3 pts[6] = {triangle[0]+normal,
triangle[1]+normal,
triangle[2]+normal,
triangle[0]-normal,
triangle[1]-normal,
triangle[2]-normal};
btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
//btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
// tm.setMargin(m_collisionMarginTriangle);
//copy over user pointers to temporary shape
tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
btCollisionShape* tmpShape = ob->getCollisionShape();
ob->internalSetTemporaryCollisionShape( tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
///this should use the btDispatcher, so the actual registered algorithm is used
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
//m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape );
triIndex.m_childShape = tm;
m_shapeCache.insert(triKey,triIndex);
}
}
void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
m_dispatchInfoPtr = &dispatchInfo;
m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
m_resultOut = resultOut;
btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
btTransform softTransform;
softTransform.setIdentity();
softTransform.setOrigin(softBodyCenter);
btTransform convexInTriangleSpace;
convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
}
void btSoftBodyConcaveCollisionAlgorithm::clearCache()
{
m_btSoftBodyTriangleCallback.clearCache();
}
void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
if (triBody->getCollisionShape()->isConcave())
{
btCollisionObject* triOb = triBody;
btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
// if (convexBody->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
//m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
// resultOut->refreshContactPoints();
}
}
}
btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
{
return btScalar(1.);
}
//const btVector3& from = convexbody->m_worldTransform.getOrigin();
//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
//todo: only do if the motion exceeds the 'radius'
btTransform triInv = triBody->getWorldTransform().inverse();
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
btTransform m_meshTransform;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
:m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
(void)partId;
(void)triangleIndex;
//do a swept sphere for now
btTransform ident;
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
ident,ident,castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
}
};
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
rayAabbMin.setMin(convexToLocal.getOrigin());
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
convexbody->getCcdSweptSphereRadius(),curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
if (triangleMesh)
{
triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
}
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
convexbody->setHitFraction( raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
}
/*
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 "btSoftBodyConcaveCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletSoftBody/btSoftBody.h"
#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
: btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
{
}
btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
{
}
btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
m_softBody = (btSoftBody*) (isSwapped? body1:body0);
m_triBody = isSwapped? body0:body1;
//
// create the manifold from the dispatcher 'manifold pool'
//
// m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
clearCache();
}
btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
{
clearCache();
// m_dispatcher->releaseManifold( m_manifoldPtr );
}
void btSoftBodyTriangleCallback::clearCache()
{
for (int i=0;i<m_shapeCache.size();i++)
{
btTriIndex* tmp = m_shapeCache.getAtIndex(i);
btAssert(tmp);
btAssert(tmp->m_childShape);
m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary?
delete tmp->m_childShape;
}
m_shapeCache.clear();
}
void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
///debug drawing of the overlapping triangles
if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0)
{
btVector3 color(255,255,0);
btTransform& tr = ob->getWorldTransform();
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
}
btTriIndex triIndex(partId,triangleIndex,0);
btHashKey<btTriIndex> triKey(triIndex.getUid());
btTriIndex* shapeIndex = m_shapeCache[triKey];
if (shapeIndex)
{
btCollisionShape* tm = shapeIndex->m_childShape;
btAssert(tm);
//copy over user pointers to temporary shape
tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
btCollisionShape* tmpShape = ob->getCollisionShape();
ob->internalSetTemporaryCollisionShape( tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape);
return;
}
//aabb filter is already applied!
//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
// if (m_softBody->getCollisionShape()->getShapeType()==
{
// btVector3 other;
btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
normal.normalize();
normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
// other+=normal*22.f;
btVector3 pts[6] = {triangle[0]+normal,
triangle[1]+normal,
triangle[2]+normal,
triangle[0]-normal,
triangle[1]-normal,
triangle[2]-normal};
btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
//btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
// tm.setMargin(m_collisionMarginTriangle);
//copy over user pointers to temporary shape
tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
btCollisionShape* tmpShape = ob->getCollisionShape();
ob->internalSetTemporaryCollisionShape( tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
///this should use the btDispatcher, so the actual registered algorithm is used
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
//m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape );
triIndex.m_childShape = tm;
m_shapeCache.insert(triKey,triIndex);
}
}
void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
m_dispatchInfoPtr = &dispatchInfo;
m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
m_resultOut = resultOut;
btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
btTransform softTransform;
softTransform.setIdentity();
softTransform.setOrigin(softBodyCenter);
btTransform convexInTriangleSpace;
convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
}
void btSoftBodyConcaveCollisionAlgorithm::clearCache()
{
m_btSoftBodyTriangleCallback.clearCache();
}
void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
if (triBody->getCollisionShape()->isConcave())
{
btCollisionObject* triOb = triBody;
btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
// if (convexBody->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
//m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
// resultOut->refreshContactPoints();
}
}
}
btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
{
return btScalar(1.);
}
//const btVector3& from = convexbody->m_worldTransform.getOrigin();
//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
//todo: only do if the motion exceeds the 'radius'
btTransform triInv = triBody->getWorldTransform().inverse();
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
btTransform m_meshTransform;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
:m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
(void)partId;
(void)triangleIndex;
//do a swept sphere for now
btTransform ident;
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
ident,ident,castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
}
};
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
rayAabbMin.setMin(convexToLocal.getOrigin());
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
convexbody->getCcdSweptSphereRadius(),curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
if (triangleMesh)
{
triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
}
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
convexbody->setHitFraction( raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
}

View File

@@ -1,153 +1,153 @@
/*
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 SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_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 "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btSoftBody;
class btCollisionShape;
#include "LinearMath/btHashMap.h"
#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
struct btTriIndex
{
int m_PartIdTriangleIndex;
class btCollisionShape* m_childShape;
btTriIndex(int partId,int triangleIndex,btCollisionShape* shape)
{
m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_childShape = shape;
}
int getTriangleIndex() const
{
// Get only the lower bits where the triangle index is stored
return (m_PartIdTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
}
int getPartId() const
{
// Get only the highest bits where the part index is stored
return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
int getUid() const
{
return m_PartIdTriangleIndex;
}
};
///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
class btSoftBodyTriangleCallback : public btTriangleCallback
{
btSoftBody* m_softBody;
btCollisionObject* m_triBody;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
btManifoldResult* m_resultOut;
btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
btHashMap<btHashKey<btTriIndex>,btTriIndex> m_shapeCache;
public:
int m_triangleCount;
// btPersistentManifold* m_manifoldPtr;
btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual ~btSoftBodyTriangleCallback();
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
{
return m_aabbMin;
}
SIMD_FORCE_INLINE const btVector3& getAabbMax() const
{
return m_aabbMax;
}
};
/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_isSwapped;
btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
public:
btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
virtual ~btSoftBodyConcaveCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
//we don't add any manifolds
}
void clearCache();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false);
}
};
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true);
}
};
};
#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_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.
*/
#ifndef SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_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 "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btSoftBody;
class btCollisionShape;
#include "LinearMath/btHashMap.h"
#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
struct btTriIndex
{
int m_PartIdTriangleIndex;
class btCollisionShape* m_childShape;
btTriIndex(int partId,int triangleIndex,btCollisionShape* shape)
{
m_PartIdTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_childShape = shape;
}
int getTriangleIndex() const
{
// Get only the lower bits where the triangle index is stored
return (m_PartIdTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
}
int getPartId() const
{
// Get only the highest bits where the part index is stored
return (m_PartIdTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
int getUid() const
{
return m_PartIdTriangleIndex;
}
};
///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
class btSoftBodyTriangleCallback : public btTriangleCallback
{
btSoftBody* m_softBody;
btCollisionObject* m_triBody;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
btManifoldResult* m_resultOut;
btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
btHashMap<btHashKey<btTriIndex>,btTriIndex> m_shapeCache;
public:
int m_triangleCount;
// btPersistentManifold* m_manifoldPtr;
btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual ~btSoftBodyTriangleCallback();
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
{
return m_aabbMin;
}
SIMD_FORCE_INLINE const btVector3& getAabbMax() const
{
return m_aabbMax;
}
};
/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_isSwapped;
btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
public:
btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
virtual ~btSoftBodyConcaveCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
//we don't add any manifolds
}
void clearCache();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false);
}
};
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true);
}
};
};
#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More