diff --git a/Demos/AllBulletDemos/CMakeLists.txt b/Demos/AllBulletDemos/CMakeLists.txt index 3d09c4de1..1ecc73216 100644 --- a/Demos/AllBulletDemos/CMakeLists.txt +++ b/Demos/AllBulletDemos/CMakeLists.txt @@ -8,7 +8,9 @@ # You shouldn't have to modify anything below this line ######################################################## - +LINK_DIRECTORIES( +"C:/MinGW/lib" +) INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/Extras/BulletColladaConverter ${BULLET_PHYSICS_SOURCE_DIR}/Extras ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include/1.4 ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL } @@ -24,23 +26,23 @@ ADD_EXECUTABLE(AllBulletDemos Main.cpp DemoEntries.cpp ../CcdPhysicsDemo/CcdPhysicsDemo.cpp - ../BasicDemo/BasicDemo.cpp + ../BasicDemo/BasicDemo.cpp ../Benchmarks/BenchmarkDemo.cpp - ../BspDemo/BspDemo.cpp - ../BspDemo/BspConverter.cpp - ../BspDemo/BspLoader.cpp - ../DynamicControlDemo/MotorDemo.cpp - ../ConcaveDemo/ConcavePhysicsDemo.cpp - ../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp - ../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp - ../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp - ../SliderConstraintDemo/SliderConstraintDemo.cpp + ../BspDemo/BspDemo.cpp + ../BspDemo/BspConverter.cpp + ../BspDemo/BspLoader.cpp + ../DynamicControlDemo/MotorDemo.cpp + ../ConcaveDemo/ConcavePhysicsDemo.cpp + ../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp + ../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp + ../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp + ../SliderConstraintDemo/SliderConstraintDemo.cpp ../RagdollDemo/RagdollDemo.cpp - ../GimpactTestDemo/GimpactTestDemo.cpp - ../Raytracer/Raytracer.cpp - ../GjkConvexCastDemo/LinearConvexCastDemo.cpp - ../VehicleDemo/VehicleDemo.cpp - ../SoftDemo/SoftDemo.cpp - ../ConstraintDemo/ConstraintDemo.cpp + ../GimpactTestDemo/GimpactTestDemo.cpp + ../Raytracer/Raytracer.cpp + ../GjkConvexCastDemo/LinearConvexCastDemo.cpp + ../VehicleDemo/VehicleDemo.cpp + ../SoftDemo/SoftDemo.cpp + ../ConstraintDemo/ConstraintDemo.cpp ) diff --git a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp index 79f08a3a5..13f221c48 100644 --- a/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp +++ b/Demos/CcdPhysicsDemo/CcdPhysicsDemo.cpp @@ -4,8 +4,8 @@ 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, +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. @@ -124,13 +124,13 @@ void CcdPhysicsDemo::createStack( btCollisionShape* boxShape, float halfCubeSize -rowSize * halfCubeSize + halfCubeSize + j * 2.0f * halfCubeSize, halfCubeSize + i * halfCubeSize * 2.0f, zPos); - + trans.setOrigin(pos); btScalar mass = 1.f; btRigidBody* body = 0; body = localCreateRigidBody(mass,trans,boxShape); -#ifdef USER_DEFINED_FRICTION_MODEL +#ifdef USER_DEFINED_FRICTION_MODEL ///Advanced use: override the friction solver body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1; #endif //USER_DEFINED_FRICTION_MODEL @@ -145,7 +145,7 @@ void CcdPhysicsDemo::createStack( btCollisionShape* boxShape, float halfCubeSize //by default, Bullet will use its own nearcallback, but you can override it using dispatcher->setNearCallback() -void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; @@ -161,7 +161,7 @@ void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& if (collisionPair.m_algorithm) { btManifoldResult contactPointResult(colObj0,colObj1); - + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) { //discrete collision detection query @@ -196,7 +196,7 @@ extern int gTotalContactPoints; void CcdPhysicsDemo::clientMoveAndDisplay() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #ifdef USE_KINEMATIC_GROUND @@ -220,16 +220,16 @@ void CcdPhysicsDemo::clientMoveAndDisplay() float dt = getDeltaTimeMicroseconds() * 0.000001f; - + // printf("dt = %f: ",dt); - + if (m_dynamicsWorld) { //#define FIXED_STEP 1 #ifdef FIXED_STEP m_dynamicsWorld->stepSimulation(1.0f/60.f,0); - + #else //during idle mode, just run 1 simulation step maximum int maxSimSubSteps = m_idle ? 1 : 1; @@ -238,10 +238,10 @@ void CcdPhysicsDemo::clientMoveAndDisplay() int numSimSteps = 0; numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); - + //optional but useful: debug drawing m_dynamicsWorld->debugDrawWorld(); - + #ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT if (!numSimSteps) printf("Interpolated transforms\n"); @@ -260,12 +260,12 @@ void CcdPhysicsDemo::clientMoveAndDisplay() #endif } - -#ifdef USE_QUICKPROF - btProfiler::beginBlock("render"); -#endif //USE_QUICKPROF - - renderme(); + +#ifdef USE_QUICKPROF + btProfiler::beginBlock("render"); +#endif //USE_QUICKPROF + + renderme(); //render the graphics objects, with center of mass shift @@ -274,9 +274,9 @@ void CcdPhysicsDemo::clientMoveAndDisplay() -#ifdef USE_QUICKPROF - btProfiler::endBlock("render"); -#endif +#ifdef USE_QUICKPROF + btProfiler::endBlock("render"); +#endif glFlush(); //some additional debugging info #ifdef PRINT_CONTACT_STATISTICS @@ -294,7 +294,7 @@ void CcdPhysicsDemo::clientMoveAndDisplay() void CcdPhysicsDemo::displayCallback(void) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); renderme(); @@ -342,7 +342,7 @@ void CcdPhysicsDemo::initPhysics() // m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); #endif - + #ifdef DO_BENCHMARK_PYRAMIDS @@ -355,7 +355,7 @@ void CcdPhysicsDemo::initPhysics() m_dispatcher=0; m_collisionConfiguration = new btDefaultCollisionConfiguration(); - + #ifdef USE_PARALLEL_DISPATCHER int maxNumOutstandingTasks = 4; @@ -397,7 +397,7 @@ int maxNumOutstandingTasks = 4; m_dispatcher = new SpuGatheringCollisionDispatcher(m_threadSupportCollision,maxNumOutstandingTasks,m_collisionConfiguration); // m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #else - + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #endif //USE_PARALLEL_DISPATCHER @@ -414,14 +414,14 @@ int maxNumOutstandingTasks = 4; // m_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); /// When trying to debug broadphase issues, try to use the btSimpleBroadphase // m_broadphase = new btSimpleBroadphase; - + //box-box is in Extras/AlternativeCollisionAlgorithms:it requires inclusion of those files #ifdef COMPARE_WITH_QUICKSTEP m_solver = new btOdeQuickstepConstraintSolver(); #else - + #ifdef USE_PARALLEL_SOLVER m_threadSupportSolver = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( @@ -435,11 +435,11 @@ int maxNumOutstandingTasks = 4; btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); m_solver = solver;//new btOdeQuickstepConstraintSolver(); - + #endif //USE_PARALLEL_SOLVER #endif - + btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); @@ -459,7 +459,7 @@ int maxNumOutstandingTasks = 4; m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; m_dynamicsWorld->setGravity(btVector3(0,-10,0)); - + #ifdef USER_DEFINED_FRICTION_MODEL { @@ -478,7 +478,7 @@ int maxNumOutstandingTasks = 4; btTransform tr; tr.setIdentity(); - + for (i=0;i0) @@ -520,7 +520,7 @@ int maxNumOutstandingTasks = 4; btTransform trans; trans.setIdentity(); - + if (i>0) { //stack them @@ -549,7 +549,7 @@ int maxNumOutstandingTasks = 4; if (!isDyna) mass = 0.f; - + btRigidBody* body = localCreateRigidBody(mass,trans,shape); #ifdef USE_KINEMATIC_GROUND if (mass == 0.f) @@ -558,15 +558,15 @@ int maxNumOutstandingTasks = 4; body->setActivationState(DISABLE_DEACTIVATION); } #endif //USE_KINEMATIC_GROUND - - + + // Only do CCD if motion in one timestep (1.f/60.f) exceeds CUBE_HALF_EXTENTS body->setCcdSquareMotionThreshold( CUBE_HALF_EXTENTS ); - + //Experimental: better estimation of CCD Time of Impact: body->setCcdSweptSphereRadius( 0.2*CUBE_HALF_EXTENTS ); -#ifdef USER_DEFINED_FRICTION_MODEL +#ifdef USER_DEFINED_FRICTION_MODEL ///Advanced use: override the friction solver body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1; #endif //USER_DEFINED_FRICTION_MODEL @@ -578,7 +578,7 @@ int maxNumOutstandingTasks = 4; #ifdef DO_BENCHMARK_PYRAMIDS btTransform trans; trans.setIdentity(); - + btScalar halfExtents = CUBE_HALF_EXTENTS; trans.setOrigin(btVector3(0,-halfExtents,0)); @@ -609,13 +609,13 @@ int maxNumOutstandingTasks = 4; m_collisionShapes.push_back(ball); btRigidBody* ballBody = localCreateRigidBody(10000.f,sphereTrans,ball); ballBody->setLinearVelocity(btVector3(0,0,-10)); -#endif +#endif #endif //DO_BENCHMARK_PYRAMIDS // clientResetScene(); } - + @@ -680,7 +680,7 @@ void CcdPhysicsDemo::exitPhysics() delete m_collisionConfiguration; - + } diff --git a/Demos/CharacterDemo/CharacterControllerInterface.h b/Demos/CharacterDemo/CharacterControllerInterface.h index 5c5ac8bab..e481ef3d9 100644 --- a/Demos/CharacterDemo/CharacterControllerInterface.h +++ b/Demos/CharacterDemo/CharacterControllerInterface.h @@ -12,16 +12,16 @@ class CharacterControllerInterface public: CharacterControllerInterface () {}; virtual ~CharacterControllerInterface () {}; - virtual void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0; - virtual void destroy (btDynamicsWorld* dynamicsWorld) = 0; + virtual void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0; + virtual void destroy () = 0; virtual btCollisionObject* getCollisionObject () = 0; virtual void reset () = 0; virtual void warp (const btVector3& origin) = 0; - - virtual void preStep (btDynamicsWorld* dynamicsWorld) = 0; - virtual void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt, + virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)=0; + virtual void preStep (const btDynamicsWorld* dynamicsWorld) = 0; + virtual void playerStep (const btDynamicsWorld* dynamicsWorld, btScalar dt, int forward, int backward, int left, diff --git a/Demos/CharacterDemo/CharacterDemo.cpp b/Demos/CharacterDemo/CharacterDemo.cpp index b0b36c839..f7ea37a2c 100644 --- a/Demos/CharacterDemo/CharacterDemo.cpp +++ b/Demos/CharacterDemo/CharacterDemo.cpp @@ -43,14 +43,25 @@ static int gLeft = 0; static int gRight = 0; static int gJump = 0; -#define QUAKE_BSP_IMPORTING 1 +///playerStepCallback is the main function that is updating the character. +///Register this callback using: m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character); +///This function will be called at the end of each internal simulation time step +void playerStepCallback(const btDynamicsWorld* dynamicsWorld, btScalar timeStep) +{ + CharacterControllerInterface* characterInterface= (CharacterControllerInterface*) dynamicsWorld->getWorldUserInfo(); + characterInterface->preStep (dynamicsWorld); + characterInterface->playerStep (dynamicsWorld, timeStep, gForward, gBackward, gLeft, gRight, gJump); +} + +#define QUAKE_BSP_IMPORTING 1 #ifdef QUAKE_BSP_IMPORTING #include "../BspDemo/BspLoader.h" #include "../BspDemo/BspConverter.h" + class BspToBulletConverter : public BspConverter { CharacterDemo* m_demoApp; @@ -108,7 +119,10 @@ CharacterDemo::~CharacterDemo() { //cleanup in the reverse order of creation/initialization if (m_character) - m_character->destroy (m_dynamicsWorld); + { + m_dynamicsWorld->removeCollisionObject(m_character->getCollisionObject()); + m_character->destroy (); + } //remove the rigidbodies from the dynamics world and delete them @@ -163,8 +177,10 @@ class MyCustomOverlappingPairCallback : public btOverlappingPairCallback { bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const { - // we already know that the character proxy is either proxy0 or proxy1 - return true; + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } } myCustomOverlapFilterCallback; @@ -237,12 +253,12 @@ void CharacterDemo::initPhysics() m_constraintSolver = new btSequentialImpulseConstraintSolver(); m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); btTransform tr; tr.setIdentity(); -#define USE_BSP_STAGE -#ifdef USE_BSP_STAGE + #ifdef QUAKE_BSP_IMPORTING char* bspfilename = "BspDemo.bsp"; void* memoryBuffer = 0; @@ -286,7 +302,6 @@ void CharacterDemo::initPhysics() fclose(file); } -#endif #else #define USE_TRIMESH_GROUND 1 #ifdef USE_TRIMESH_GROUND @@ -477,12 +492,19 @@ const float TRIANGLE_SIZE=20.f; #else m_character = new KinematicCharacterController (); #endif - m_character->setup (m_dynamicsWorld); + m_character->setup (); + + m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character); //some custom callback sample m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getCollisionObject()); sweepBP->setOverlappingPairUserCallback(m_customPairCallback); - m_character->registerPairCache (m_customPairCallback->getOverlappingPairCache()); + m_character->registerPairCacheAndDispatcher (m_customPairCallback->getOverlappingPairCache(), m_dispatcher); + + m_dynamicsWorld->addCollisionObject(m_character->getCollisionObject(),btBroadphaseProxy::DebrisFilter, btBroadphaseProxy::StaticFilter);//AllFilter); + + + clientResetScene(); setCameraDistance(26.f); @@ -498,22 +520,11 @@ void CharacterDemo::renderme() DemoApplication::renderme(); } -void CharacterDemo::clientMoveAndDisplay() + + +void CharacterDemo::debugDrawContacts() { - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - float dt = getDeltaTimeMicroseconds() * 0.000001f; - - /* Character stuff &*/ - if (m_character) - { - m_character->preStep (m_dynamicsWorld); - m_character->playerStep (m_dynamicsWorld, dt, gForward, gBackward, gLeft, gRight, gJump); - } - -#if 0 - printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size()); +// printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size()); { btManifoldArray manifoldArray; for (int i=0;igetOverlappingPairArray().size();i++) @@ -541,8 +552,23 @@ void CharacterDemo::clientMoveAndDisplay() } } } -#endif +} + +void CharacterDemo::clientMoveAndDisplay() +{ + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + float dt = getDeltaTimeMicroseconds() * 0.000001f; + + /* Character stuff &*/ + if (m_character) + { + + } + + debugDrawContacts(); if (m_dynamicsWorld) @@ -612,6 +638,7 @@ void CharacterDemo::displayCallback(void) if (m_dynamicsWorld) m_dynamicsWorld->debugDrawWorld(); + debugDrawContacts(); glFlush(); glutSwapBuffers(); @@ -622,7 +649,8 @@ void CharacterDemo::clientResetScene() m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getCollisionObject()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); m_character->reset (); - m_character->warp (btVector3(0.0, 1.75, 0.0)); + ///WTF + m_character->warp (btVector3(0, -2.0, 0.)); } void CharacterDemo::specialKeyboardUp(int key, int x, int y) diff --git a/Demos/CharacterDemo/CharacterDemo.h b/Demos/CharacterDemo/CharacterDemo.h index c18a8857f..418533891 100644 --- a/Demos/CharacterDemo/CharacterDemo.h +++ b/Demos/CharacterDemo/CharacterDemo.h @@ -15,7 +15,12 @@ subject to the following restrictions: #ifndef CHARACTER_DEMO_H #define CHARACTER_DEMO_H -class CharacterController; + +///DYNAMIC_CHARACTER_CONTROLLER is not supported/obsolete at the moment +//#define DYNAMIC_CHARACTER_CONTROLLER 1 + +class CharacterControllerInterface; +class DynamicCharacterController; class KinematicCharacterController; class btCollisionShape; @@ -29,7 +34,7 @@ class CharacterDemo : public DemoApplication public: #ifdef DYNAMIC_CHARACTER_CONTROLLER - CharacterController* m_character; + CharacterControllerInterface* m_character; #else KinematicCharacterController* m_character; #endif @@ -50,6 +55,7 @@ class CharacterDemo : public DemoApplication btVector3* m_vertices; + void debugDrawContacts(); float m_cameraHeight; @@ -67,7 +73,7 @@ class CharacterDemo : public DemoApplication virtual void displayCallback(); - ///a very basic camera following the vehicle + ///a very basic camera following the character virtual void updateCamera(); virtual void specialKeyboard(int key, int x, int y); diff --git a/Demos/CharacterDemo/DynamicCharacterController.cpp b/Demos/CharacterDemo/DynamicCharacterController.cpp index ad00e8232..73980ac0b 100644 --- a/Demos/CharacterDemo/DynamicCharacterController.cpp +++ b/Demos/CharacterDemo/DynamicCharacterController.cpp @@ -21,7 +21,7 @@ DynamicCharacterController::~DynamicCharacterController () { } -void DynamicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar height, btScalar width, btScalar stepHeight) +void DynamicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight) { btVector3 spherePositions[2]; btScalar sphereRadii[2]; @@ -45,10 +45,10 @@ void DynamicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar //m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); m_rigidBody->setSleepingThresholds (0.0, 0.0); m_rigidBody->setAngularFactor (0.0); - dynamicsWorld->addRigidBody (m_rigidBody); + } -void DynamicCharacterController::destroy (btDynamicsWorld* dynamicsWorld) +void DynamicCharacterController::destroy () { if (m_shape) { @@ -57,8 +57,8 @@ void DynamicCharacterController::destroy (btDynamicsWorld* dynamicsWorld) if (m_rigidBody) { - dynamicsWorld->removeRigidBody (m_rigidBody); delete m_rigidBody; + m_rigidBody = 0; } } @@ -67,7 +67,7 @@ btCollisionObject* DynamicCharacterController::getCollisionObject () return m_rigidBody; } -void DynamicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) +void DynamicCharacterController::preStep (const btDynamicsWorld* dynamicsWorld) { btTransform xform; m_rigidBody->getMotionState()->getWorldTransform (xform); @@ -118,7 +118,7 @@ void DynamicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) } } -void DynamicCharacterController::playerStep (btScalar dt, +void DynamicCharacterController::playerStep (const btDynamicsWorld* dynaWorld,btScalar dt, int forward, int backward, int left, @@ -190,3 +190,15 @@ bool DynamicCharacterController::onGround () const { return m_rayLambda[0] < btScalar(1.0); } + +void DynamicCharacterController::reset () +{ +} +void DynamicCharacterController::warp (const btVector3& origin) +{ +} +void DynamicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher) +{ + +} + diff --git a/Demos/CharacterDemo/DynamicCharacterController.h b/Demos/CharacterDemo/DynamicCharacterController.h index bdca1032d..b8992fd78 100644 --- a/Demos/CharacterDemo/DynamicCharacterController.h +++ b/Demos/CharacterDemo/DynamicCharacterController.h @@ -9,6 +9,7 @@ class btCollisionShape; class btRigidBody; class btDynamicsWorld; +///DynamicCharacterController is obsolete/unsupported at the moment class DynamicCharacterController : public CharacterControllerInterface { protected: @@ -29,13 +30,17 @@ protected: public: DynamicCharacterController (); ~DynamicCharacterController (); - void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25); - void destroy (btDynamicsWorld* dynamicsWorld); + void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25); + void destroy (); + + virtual void reset (); + virtual void warp (const btVector3& origin); + virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher); btCollisionObject* getCollisionObject (); - void preStep (btDynamicsWorld* dynamicsWorld); - void playerStep (btScalar dt, + void preStep (const btDynamicsWorld* dynamicsWorld); + void playerStep (const btDynamicsWorld* dynaWorld,btScalar dt, int forward, int backward, int left, diff --git a/Demos/CharacterDemo/KinematicCharacterController.cpp b/Demos/CharacterDemo/KinematicCharacterController.cpp index 4216db61d..6d491a1bd 100644 --- a/Demos/CharacterDemo/KinematicCharacterController.cpp +++ b/Demos/CharacterDemo/KinematicCharacterController.cpp @@ -87,7 +87,7 @@ btVector3 perpindicularComponent (const btVector3& direction, const btVector3& n KinematicCharacterController::KinematicCharacterController () { m_turnAngle = btScalar(0.0); - m_walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s + m_walkVelocity = btScalar(1.1) * 14.0; // 4 km/h -> 1.1 m/s m_shape = NULL; m_pairCache = NULL; m_collisionObject = NULL; @@ -97,15 +97,15 @@ KinematicCharacterController::~KinematicCharacterController () { } -void KinematicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar height, btScalar width, btScalar stepHeight) +void KinematicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight) { btVector3 spherePositions[2]; btScalar sphereRadii[2]; sphereRadii[0] = width; sphereRadii[1] = width; - spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) - width), 0.0); - spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0) + width), 0.0); + spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) ), 0.0); + spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0)), 0.0); m_halfHeight = height/btScalar(2.0); @@ -116,19 +116,20 @@ void KinematicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScal btTransform startTransform; startTransform.setIdentity (); startTransform.setOrigin (btVector3(0.0, 4.0, 0.0)); - btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape); + //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + //btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape); m_collisionObject = new btCollisionObject (); + + m_collisionObject->setWorldTransform(startTransform); m_collisionObject->setCollisionShape (m_shape); - m_collisionObject->setCollisionFlags (btCollisionObject::CF_KINEMATIC_OBJECT); - dynamicsWorld->addCollisionObject (m_collisionObject); + m_collisionObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE); + } -void KinematicCharacterController::destroy (btDynamicsWorld* dynamicsWorld) +void KinematicCharacterController::destroy () { if (m_collisionObject) { - dynamicsWorld->removeCollisionObject (m_collisionObject); delete m_collisionObject; } @@ -143,29 +144,33 @@ btCollisionObject* KinematicCharacterController::getCollisionObject () return m_collisionObject; } -bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dynamicsWorld) +bool KinematicCharacterController::recoverFromPenetration (const btDynamicsWorld* dynamicsWorld) { + if (m_pairCache == NULL) return false; bool penetration = false; - dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), dynamicsWorld->getDispatcher()); + + m_dispatcher->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), m_dispatcher); - btManifoldArray manifoldArray; + m_currentPosition = m_collisionObject->getWorldTransform().getOrigin(); + btScalar maxPen = btScalar(0.0); for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++) { - manifoldArray.clear(); + m_manifoldArray.resize(0); btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i]; if (collisionPair->m_algorithm) - collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray); - for (int j=0;jgetBody0() == m_collisionObject ? btScalar(-1.0) : btScalar(1.0); for (int p=0;pgetNumContacts();p++) { @@ -176,7 +181,8 @@ bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dyna if (pt.getDistance() < maxPen) { maxPen = pt.getDistance(); - m_touchingNormal = pt.m_normalWorldOnB * directionSign; + m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? + } m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2); penetration = true; @@ -184,13 +190,18 @@ bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dyna //printf("touching %f\n", pt.getDistance()); } } - manifold->clearManifold(); + + //manifold->clearManifold(); } } + btTransform newTrans = m_collisionObject->getWorldTransform(); + newTrans.setOrigin(m_currentPosition); + m_collisionObject->setWorldTransform(newTrans); +// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); return penetration; } -void KinematicCharacterController::stepUp (btDynamicsWorld* dynamicsWorld) +void KinematicCharacterController::stepUp (const btDynamicsWorld* dynamicsWorld) { // phase 1: up btTransform start, end; @@ -222,31 +233,47 @@ void KinematicCharacterController::updateTargetPositionBasedOnCollision (const b { btVector3 movementDirection = m_targetPosition - m_currentPosition; btScalar movementLength = movementDirection.length(); - 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 (tangentMag != 0.0) + if (movementLength>SIMD_EPSILON) { - m_targetPosition += parallelDir * btScalar (tangentMag*movementLength); - } + movementDirection.normalize(); - if (normalMag != 0.0) + 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 { - m_targetPosition += perpindicularDir * btScalar (normalMag*movementLength); +// printf("movementLength don't normalize a zero vector\n"); } } -void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove) +void KinematicCharacterController::stepForwardAndStrafe (const btDynamicsWorld* dynamicsWorld, 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; @@ -255,6 +282,7 @@ void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynami btScalar fraction = 1.0; btScalar distance2 = (m_currentPosition-m_targetPosition).length2(); +// printf("distance2=%f\n",distance2); if (m_touchingContact) { @@ -262,44 +290,67 @@ void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynami updateTargetPositionBasedOnCollision (m_touchingNormal); } - while (fraction > btScalar(0.01)) + int maxIter = 10; + + while (fraction > btScalar(0.01) && maxIter-- > 0) { start.setOrigin (m_currentPosition); end.setOrigin (m_targetPosition); ClosestNotMeConvexResultCallback callback (m_collisionObject); - dynamicsWorld->convexSweepTest (m_shape, start, end, callback); + //btScalar margin = m_shape->getMargin(); + //m_shape->setMargin(margin - 0.06f); + dynamicsWorld->convexSweepTest (m_shape, start, end, callback); + //m_shape->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 > 0.05) { +// 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(); - currentDir.normalize(); - /* Ageia's C.C. took this test from Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */ - if (currentDir.dot(originalDir) <= btScalar(0.0)) + 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 KinematicCharacterController::stepDown (btDynamicsWorld* dynamicsWorld, btScalar dt) +void KinematicCharacterController::stepDown (const btDynamicsWorld* dynamicsWorld, btScalar dt) { btTransform start, end; @@ -341,13 +392,15 @@ void KinematicCharacterController::warp (const btVector3& origin) m_collisionObject->setWorldTransform (xform); } -void KinematicCharacterController::registerPairCache (btOverlappingPairCache* pairCache) +void KinematicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher) { m_pairCache = pairCache; + m_dispatcher = dispatcher; } -void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) +void KinematicCharacterController::preStep (const btDynamicsWorld* dynamicsWorld) { + int numPenetrationLoops = 0; m_touchingContact = false; while (recoverFromPenetration (dynamicsWorld)) @@ -356,7 +409,7 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) m_touchingContact = true; if (numPenetrationLoops > 4) { - printf("character could not recover from penetration = %d\n", numPenetrationLoops); +// printf("character could not recover from penetration = %d\n", numPenetrationLoops); break; } } @@ -364,6 +417,7 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) xform = m_collisionObject->getWorldTransform (); btVector3 forwardDir = xform.getBasis()[2]; +// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]); btVector3 upDir = xform.getBasis()[1]; btVector3 strafeDir = xform.getBasis()[0]; forwardDir.normalize (); @@ -376,11 +430,12 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) m_currentPosition = xform.getOrigin(); m_targetPosition = m_currentPosition; +// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); } -void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld, +void KinematicCharacterController::playerStep (const btDynamicsWorld* dynamicsWorld, btScalar dt, int forward, int backward, @@ -406,6 +461,9 @@ void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld, btTransform xform; xform = m_collisionObject->getWorldTransform (); +// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]); +// printf("walkSpeed=%f\n",walkSpeed); + stepUp (dynamicsWorld); stepForwardAndStrafe (dynamicsWorld, walkDirection * walkSpeed); stepDown (dynamicsWorld, dt); diff --git a/Demos/CharacterDemo/KinematicCharacterController.h b/Demos/CharacterDemo/KinematicCharacterController.h index bebf2ac49..aa4c734a6 100644 --- a/Demos/CharacterDemo/KinematicCharacterController.h +++ b/Demos/CharacterDemo/KinematicCharacterController.h @@ -8,7 +8,12 @@ class btCollisionShape; class btRigidBody; class btDynamicsWorld; +class btCollisionDispatcher; + +///KinematicCharacterController is a collision object with support for sliding motion in a world. +///It uses the convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. +///Interaction between KinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. class KinematicCharacterController : public CharacterControllerInterface { protected: @@ -16,6 +21,7 @@ protected: btConvexShape* m_shape; btCollisionObject* m_collisionObject; btOverlappingPairCache* m_pairCache; + btCollisionDispatcher* m_dispatcher; btScalar m_fallSpeed; btScalar m_jumpSpeed; @@ -36,28 +42,30 @@ protected: btScalar m_currentStepOffset; btVector3 m_targetPosition; + btManifoldArray m_manifoldArray; + bool m_touchingContact; btVector3 m_touchingNormal; - bool recoverFromPenetration (btDynamicsWorld* dynamicsWorld); - void stepUp (btDynamicsWorld* dynamicsWorld); - void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(1.0), btScalar normalMag = btScalar(0.0)); - void stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove); - void stepDown (btDynamicsWorld* dynamicsWorld, btScalar dt); + bool recoverFromPenetration (const btDynamicsWorld* dynamicsWorld); + void stepUp (const btDynamicsWorld* dynamicsWorld); + void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0)); + void stepForwardAndStrafe (const btDynamicsWorld* dynamicsWorld, const btVector3& walkMove); + void stepDown (const btDynamicsWorld* dynamicsWorld, btScalar dt); public: KinematicCharacterController (); ~KinematicCharacterController (); - void setup (btDynamicsWorld* dynamicsWorld, btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35)); - void destroy (btDynamicsWorld* dynamicsWorld); + void setup (btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35)); + void destroy (); btCollisionObject* getCollisionObject (); void reset (); void warp (const btVector3& origin); - void registerPairCache (btOverlappingPairCache* pairCache); - void preStep (btDynamicsWorld* dynamicsWorld); - void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt, + virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher); + void preStep (const btDynamicsWorld* dynamicsWorld); + void playerStep (const btDynamicsWorld* dynamicsWorld, btScalar dt, int forward, int backward, int left, diff --git a/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp b/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp index 842383d24..d42545422 100644 --- a/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp +++ b/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.cpp @@ -82,12 +82,12 @@ SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher() ///this is useful for the collision dispatcher. class btSpuCollisionPairCallback : public btOverlapCallback { - btDispatcherInfo& m_dispatchInfo; + const btDispatcherInfo& m_dispatchInfo; SpuGatheringCollisionDispatcher* m_dispatcher; public: - btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher) + btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher) :m_dispatchInfo(dispatchInfo), m_dispatcher(dispatcher) { @@ -141,7 +141,7 @@ public: } }; -void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) +void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) { if (dispatchInfo.m_enableSPU) diff --git a/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h b/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h index 497773b61..9f7fb9e8d 100644 --- a/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h +++ b/Extras/BulletMultiThreaded/SpuGatheringCollisionDispatcher.h @@ -55,7 +55,7 @@ public: bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; }; diff --git a/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/src/BulletCollision/BroadphaseCollision/btDispatcher.h index b4f582542..451265504 100644 --- a/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -44,6 +44,8 @@ struct btDispatcherInfo m_debugDraw(0), m_enableSatConvex(false), m_enableSPU(true), + m_useEpa(true), + m_allowedCcdPenetration(btScalar(0.04)), m_stackAllocator(0) { @@ -51,12 +53,13 @@ struct btDispatcherInfo btScalar m_timeStep; int m_stepCount; int m_dispatchFunc; - btScalar m_timeOfImpact; + mutable btScalar m_timeOfImpact; bool m_useContinuous; class btIDebugDraw* m_debugDraw; bool m_enableSatConvex; bool m_enableSPU; bool m_useEpa; + btScalar m_allowedCcdPenetration; btStackAlloc* m_stackAllocator; }; @@ -82,7 +85,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; virtual int getNumManifolds() const = 0; @@ -90,7 +93,7 @@ public: virtual btPersistentManifold** getInternalManifoldPointer() = 0; - virtual void* allocateCollisionAlgorithm(int size) = 0; + virtual void* allocateCollisionAlgorithm(int size) = 0; virtual void freeCollisionAlgorithm(void* ptr) = 0; diff --git a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index 46726ce26..be69a54f1 100644 --- a/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -399,7 +399,7 @@ public: { } - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) + virtual void processAllOverlappingPairs(btOverlapCallback*,const btDispatcher* /*dispatcher*/) { } diff --git a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index 53b5e6456..7c6829295 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -191,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO ///this is useful for the collision dispatcher. class btCollisionPairCallback : public btOverlapCallback { - btDispatcherInfo& m_dispatchInfo; + const btDispatcherInfo& m_dispatchInfo; btCollisionDispatcher* m_dispatcher; public: - btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) :m_dispatchInfo(dispatchInfo), m_dispatcher(dispatcher) { } - btCollisionPairCallback& operator=(btCollisionPairCallback& other) + /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) { m_dispatchInfo = other.m_dispatchInfo; m_dispatcher = other.m_dispatcher; return *this; } + */ + virtual ~btCollisionPairCallback() {} @@ -221,7 +223,8 @@ public: }; -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) { //m_blockedForChanges = true; @@ -237,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa //by default, Bullet will use this near callback -void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; diff --git a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index b6b57e8ce..a9c9cd414 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -35,7 +35,7 @@ class btCollisionConfiguration; class btCollisionDispatcher; ///user can override this nearcallback for collision filtering and more finegrained control over collision detection -typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. @@ -107,7 +107,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; void setNearCallback(btNearCallback nearCallback) { @@ -120,7 +120,7 @@ public: } //by default, Bullet will use this near callback - static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); virtual void* allocateCollisionAlgorithm(int size); diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 086c71c71..6c15475bc 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -4,8 +4,8 @@ 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, +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. @@ -57,7 +57,7 @@ btCollisionWorld::~btCollisionWorld() for (i=0;igetBroadphaseHandle(); if (bp) { @@ -107,7 +107,7 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho m_dispatcher1,0 )) ; - + @@ -116,12 +116,12 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho void btCollisionWorld::updateAabbs() { BT_PROFILE("updateAabbs"); - + btTransform predictedTrans; for ( int i=0;iisActive()) { @@ -138,7 +138,7 @@ void btCollisionWorld::updateAabbs() //something went wrong, investigate //this assert is unwanted in 3D modelers (danger of loosing work) colObj->setActivationState(DISABLE_SIMULATION); - + static bool reportMe = true; if (reportMe && m_debugDrawer) { @@ -151,7 +151,7 @@ void btCollisionWorld::updateAabbs() } } } - + } @@ -183,12 +183,12 @@ void btCollisionWorld::performDiscreteCollisionDetection() void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) { - - + + //bool removeFromBroadphase = false; - + { - + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); if (bp) { @@ -233,12 +233,12 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); #endif //#USE_SUBSIMPLEX_CONVEX_CAST - + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { //add hit if (castResult.m_normal.length2() > btScalar(0.0001)) - { + { if (castResult.m_fraction < resultCallback.m_closestHitFraction) { #ifdef USE_SUBSIMPLEX_CONVEX_CAST @@ -249,7 +249,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra castResult.m_normal.normalize(); btCollisionWorld::LocalRayResult localRayResult ( - collisionObject, + collisionObject, 0, castResult.m_normal, castResult.m_fraction @@ -273,7 +273,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); //ConvexCast::CastResult - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback { btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; @@ -294,13 +294,13 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btCollisionWorld::LocalShapeInfo shapeInfo; shapeInfo.m_shapePart = partId; shapeInfo.m_triangleIndex = triangleIndex; - + btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, + (m_collisionObject, &shapeInfo, hitNormalLocal, hitFraction); - + bool normalInWorldSpace = false; return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); } @@ -313,7 +313,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra } else { btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; - + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); @@ -321,7 +321,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra //ConvexCast::CastResult - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback { btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; @@ -342,17 +342,17 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btCollisionWorld::LocalShapeInfo shapeInfo; shapeInfo.m_shapePart = partId; shapeInfo.m_triangleIndex = triangleIndex; - + btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, + (m_collisionObject, &shapeInfo, hitNormalLocal, hitFraction); - + bool normalInWorldSpace = false; return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); - - + + } }; @@ -395,29 +395,39 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback,short int collisionFilterMask) + ConvexResultCallback& resultCallback, btScalar allowedPenetration,short int collisionFilterMask) { if (collisionShape->isConvex()) { btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; castResult.m_fraction = btScalar(1.);//?? btConvexShape* convexShape = (btConvexShape*) collisionShape; btVoronoiSimplexSolver simplexSolver; btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; - btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + + bool result = false; - if (convexCaster.calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); + //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); + + btConvexCast* castPtr = &convexCaster1; + + + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { //add hit if (castResult.m_normal.length2() > btScalar(0.0001)) - { + { if (castResult.m_fraction < resultCallback.m_closestHitFraction) { castResult.m_normal.normalize(); btCollisionWorld::LocalConvexResult localConvexResult ( - collisionObject, + collisionObject, 0, castResult.m_normal, castResult.m_hitPoint, @@ -443,7 +453,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); //ConvexCast::CastResult - struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback { btCollisionWorld::ConvexResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; @@ -468,15 +478,15 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt { btCollisionWorld::LocalConvexResult convexResult - (m_collisionObject, + (m_collisionObject, &shapeInfo, hitNormalLocal, hitPointLocal, hitFraction); - + bool normalInWorldSpace = true; - + return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace); } return hitFraction; @@ -499,7 +509,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); //ConvexCast::CastResult - struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback { btCollisionWorld::ConvexResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; @@ -524,12 +534,12 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt { btCollisionWorld::LocalConvexResult convexResult - (m_collisionObject, + (m_collisionObject, &shapeInfo, hitNormalLocal, hitPointLocal, hitFraction); - + bool normalInWorldSpace = false; return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace); @@ -543,7 +553,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt tccb.m_hitFraction = resultCallback.m_closestHitFraction; btVector3 boxMinLocal, boxMaxLocal; castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); - + btVector3 rayAabbMinLocal = convexFromLocal; rayAabbMinLocal.setMin(convexToLocal); btVector3 rayAabbMaxLocal = convexFromLocal; @@ -567,26 +577,26 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt collisionObject, childCollisionShape, childWorldTrans, - resultCallback, collisionFilterMask); + resultCallback, allowedPenetration,collisionFilterMask); } } } } } -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) const { - + btTransform rayFromTrans,rayToTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(rayFromWorld); rayToTrans.setIdentity(); - + rayToTrans.setOrigin(rayToWorld); /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) - + int i; for (i=0;igetBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { + if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); btVector3 collisionObjectAabbMin,collisionObjectAabbMax; collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); @@ -610,14 +620,14 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), resultCallback); - } + } } - + } } -void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback,short int collisionFilterMask) +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback,short int collisionFilterMask) const { btTransform convexFromTrans,convexToTrans; convexFromTrans = convexFromWorld; @@ -640,7 +650,7 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT { btCollisionObject* collisionObject= m_collisionObjects[i]; //only perform raycast if filterMask matches - if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { + if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); btVector3 collisionObjectAabbMin,collisionObjectAabbMax; collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); @@ -653,8 +663,10 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT collisionObject, collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), - resultCallback); - } + resultCallback, + getDispatchInfo().m_allowedCcdPenetration, + collisionFilterMask); + } } } diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 5dc9b514f..10565e5ca 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -123,6 +123,11 @@ public: return m_dispatcher1; } + const btDispatcher* getDispatcher() const + { + return m_dispatcher1; + } + virtual void updateAabbs(); virtual void setDebugDrawer(btIDebugDraw* debugDrawer) @@ -309,11 +314,11 @@ public: /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1) const; // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. - void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, short int collisionFilterMask=-1); + void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, short int collisionFilterMask=-1) const; /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. @@ -330,7 +335,7 @@ public: btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback, short int collisionFilterMask=-1); + ConvexResultCallback& resultCallback, btScalar allowedPenetration, short int collisionFilterMask=-1); void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); @@ -354,6 +359,11 @@ public: return m_dispatchInfo; } + const btDispatcherInfo& getDispatchInfo() const + { + return m_dispatchInfo; + } + }; diff --git a/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 0d27eef40..6551cfb92 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -51,10 +51,18 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + + btScalar relLinVelocLength = (linVelB-linVelA).length(); + + if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) + return false; + btScalar radius = btScalar(0.001); @@ -108,8 +116,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact( dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; - - + btScalar projectedLinearVelocity = relLinVel.dot(n); + //not close enough while (dist > radius) { @@ -120,7 +128,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( } btScalar dLambda = btScalar(0.); - btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); + projectedLinearVelocity = relLinVel.dot(n); //calculate safe moving fraction from distance / (linear+rotational velocity) @@ -130,6 +138,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact( dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + lambda = lambda + dLambda; if (lambda > btScalar(1.)) @@ -187,6 +197,10 @@ bool btContinuousConvexCollision::calcTimeOfImpact( } + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) + return false; + result.m_fraction = lambda; result.m_normal = n; result.m_hitPoint = c; diff --git a/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index ae35d5236..0edf4dcd4 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -42,20 +42,21 @@ public: CastResult() :m_fraction(btScalar(1e30)), - m_debugDrawer(0) + m_debugDrawer(0), + m_allowedPenetration(btScalar(0)) { } virtual ~CastResult() {}; - btVector3 m_normal; - btVector3 m_hitPoint; - btScalar m_fraction; btTransform m_hitTransformA; btTransform m_hitTransformB; - + btVector3 m_normal; + btVector3 m_hitPoint; + btScalar m_fraction; //input and output btIDebugDraw* m_debugDrawer; + btScalar m_allowedPenetration; }; diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp index 450b59560..bef697a0a 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -158,6 +158,11 @@ bool btGjkConvexCast::calcTimeOfImpact( } + //is n normalized? + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (n.dot(r)>=-result.m_allowedPenetration) + return false; + result.m_fraction = lambda; result.m_normal = n; result.m_hitPoint = c; diff --git a/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp index 9bedb5a5b..5c7056509 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -119,6 +119,8 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( { dist2 = v.length2(); hasResult = true; + //todo: check this normal for validity + n=v; //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); //printf("DIST2=%f\n",dist2); //printf("numverts = %i\n",m_simplexSolver->numVertices()); @@ -130,8 +132,17 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( //int numiter = MAX_ITERATIONS - maxIter; // printf("number of iterations: %d", numiter); + + //don't report a time of impact when moving 'away' from the hitnormal + + result.m_fraction = lambda; result.m_normal = n.normalized(); + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (result.m_normal.dot(r)>=-result.m_allowedPenetration) + return false; + btVector3 hitA,hitB; m_simplexSolver->compute_points(hitA,hitB); result.m_hitPoint=hitB; diff --git a/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 2c42ea4a1..801d0cc98 100644 --- a/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -39,15 +39,16 @@ class btDynamicsWorld : public btCollisionWorld { protected: - btInternalTickCallback m_internalTickCallback; + btInternalTickCallback m_internalTickCallback; + void* m_worldUserInfo; - btContactSolverInfo m_solverInfo; + btContactSolverInfo m_solverInfo; public: btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) - :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0) { } @@ -95,8 +96,17 @@ public: virtual void clearForces() = 0; - /// Set the callback for when an internal tick (simulation substep) happens - void setInternalTickCallback(btInternalTickCallback cb) { m_internalTickCallback = cb; } + /// 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* getWorldUserInfo() const + { + return m_worldUserInfo; + } btContactSolverInfo& getSolverInfo() { diff --git a/src/LinearMath/btScalar.h b/src/LinearMath/btScalar.h index 890a3c906..671e373c5 100644 --- a/src/LinearMath/btScalar.h +++ b/src/LinearMath/btScalar.h @@ -23,7 +23,7 @@ subject to the following restrictions: #include #include -#define BT_BULLET_VERSION 269 +#define BT_BULLET_VERSION 270 inline int btGetVersion() {