diff --git a/Demos/AllBulletDemos/DemoEntries.cpp b/Demos/AllBulletDemos/DemoEntries.cpp index d6e6e51c7..5d70898ef 100644 --- a/Demos/AllBulletDemos/DemoEntries.cpp +++ b/Demos/AllBulletDemos/DemoEntries.cpp @@ -99,15 +99,17 @@ btDemoEntry g_demoEntries[] = { {"DynamicControlDemo",MotorDemo::Create}, {"RagdollDemo",RagdollDemo::Create}, + {"BasicDemo", BasicDemo::Create}, {"CcdPhysicsDemo", CcdPhysicsDemo::Create}, {"ConcaveDemo",ConcaveDemo::Create}, {"ConcaveRaycastDemo",ConcaveRaycastDemo::Create}, {"ConcaveConvexcastDemo",ConcaveConvexcastDemo::Create}, {"ConvexDecomposition",ConvexDecompositionDemo::Create}, - {"BasicDemo", BasicDemo::Create}, {"BspDemo", BspDemo::Create}, {"Gimpact Test", GimpactConcaveDemo::Create}, +#ifndef BT_USE_DOUBLE_PRECISION {"MultiThreaded", MultiThreadedDemo::Create}, +#endif //BT_USE_DOUBLE_PRECISION {"Raytracer Test",Raytracer::Create}, {"GjkConvexCast",LinearConvexCastDemo::Create}, {"VehicleDemo",VehicleDemo::Create}, diff --git a/Demos/BasicDemo/BasicDemo.cpp b/Demos/BasicDemo/BasicDemo.cpp index eb857f186..14531729d 100644 --- a/Demos/BasicDemo/BasicDemo.cpp +++ b/Demos/BasicDemo/BasicDemo.cpp @@ -125,7 +125,8 @@ void BasicDemo::initPhysics() //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,groundShape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); @@ -171,7 +172,8 @@ void BasicDemo::initPhysics() //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,colShape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); m_dynamicsWorld->addRigidBody(body); } diff --git a/Demos/ColladaDemo/ColladaDemo.cpp b/Demos/ColladaDemo/ColladaDemo.cpp index 8d5437e33..d6e49c03c 100644 --- a/Demos/ColladaDemo/ColladaDemo.cpp +++ b/Demos/ColladaDemo/ColladaDemo.cpp @@ -62,7 +62,8 @@ class MyColladaConverter : public ColladaConverter { if (!bodyOther) { - bodyOther = new btRigidBody(0,0,0); + btRigidBody::btRigidBodyConstructionInfo cinfo(0,0,0); + bodyOther = new btRigidBody(cinfo); bodyOther->setWorldTransform(bodyRef->getWorldTransform()); localAttachmentOther = localAttachmentFrameRef; diff --git a/Demos/ConstraintDemo/ConstraintDemo.cpp b/Demos/ConstraintDemo/ConstraintDemo.cpp index 3aed5fe38..2c88e7239 100644 --- a/Demos/ConstraintDemo/ConstraintDemo.cpp +++ b/Demos/ConstraintDemo/ConstraintDemo.cpp @@ -114,7 +114,6 @@ void ConstraintDemo::initPhysics() } - //create a slider, using the generic D6 constraint { mass = 1.f; @@ -130,6 +129,7 @@ void ConstraintDemo::initPhysics() d6body0 = localCreateRigidBody( mass,trans,shape); d6body0->setActivationState(DISABLE_DEACTIVATION); btRigidBody* fixedBody1 = localCreateRigidBody(0,trans,0); + m_dynamicsWorld->addRigidBody(fixedBody1); btTransform frameInA, frameInB; frameInA = btTransform::getIdentity(); @@ -154,8 +154,17 @@ ConstraintDemo::~ConstraintDemo() { //cleanup in the reverse order of creation/initialization - //remove the rigidbodies from the dynamics world and delete them int i; + + //removed/delete constraints + for (i=m_dynamicsWorld->getNumConstraints()-1; i>=0 ;i--) + { + btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); + m_dynamicsWorld->removeConstraint(constraint); + delete constraint; + } + + //remove the rigidbodies from the dynamics world and delete them for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) { btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; @@ -168,6 +177,9 @@ ConstraintDemo::~ConstraintDemo() delete obj; } + + + //delete collision shapes for (int j=0;jcalculateLocalInertia(mass,localInertia); btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,shape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); m_ownerWorld->addRigidBody(body); diff --git a/Demos/GenericJointDemo/Ragdoll.cpp b/Demos/GenericJointDemo/Ragdoll.cpp index c0528e4c9..c470de5f7 100644 --- a/Demos/GenericJointDemo/Ragdoll.cpp +++ b/Demos/GenericJointDemo/Ragdoll.cpp @@ -363,7 +363,9 @@ btRigidBody* RagDoll::localCreateRigidBody (btScalar mass, const btTransform& st shape->calculateLocalInertia(mass,localInertia); btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,shape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + rbInfo.m_additionalDamping = true; + btRigidBody* body = new btRigidBody(rbInfo); m_ownerWorld->addRigidBody(body); diff --git a/Demos/HelloWorld/HelloWorld.cpp b/Demos/HelloWorld/HelloWorld.cpp index b852a3c28..82cc5a2a2 100644 --- a/Demos/HelloWorld/HelloWorld.cpp +++ b/Demos/HelloWorld/HelloWorld.cpp @@ -69,7 +69,8 @@ int main(int argc, char** argv) //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,groundShape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); //add the body to the dynamics world dynamicsWorld->addRigidBody(body); @@ -100,7 +101,8 @@ int main(int argc, char** argv) //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,colShape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); dynamicsWorld->addRigidBody(body); } diff --git a/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp b/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp index b54ba0b7e..e2ebccec8 100644 --- a/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp +++ b/Demos/MultiThreadedDemo/MultiThreadedDemo.cpp @@ -13,32 +13,11 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -//enable just one, DO_BENCHMARK_PYRAMIDS or DO_WALL -#define DO_BENCHMARK_PYRAMIDS 1 -//#define DO_WALL 1 - -//Note: some of those settings need 'DO_WALL' demo -//#define USE_KINEMATIC_GROUND 1 -//#define PRINT_CONTACT_STATISTICS 1 -//#define REGISTER_BOX_BOX 1 //needs to be used in combination with REGISTER_CUSTOM_COLLISION_ALGORITHM -//#define USER_DEFINED_FRICTION_MODEL 1 -//#define USE_CUSTOM_NEAR_CALLBACK 1 -//#define CENTER_OF_MASS_SHIFT 1 -//#define VERBOSE_TIMESTEPPING_CONSOLEOUTPUT 1 - //#define USE_PARALLEL_SOLVER 1 //experimental parallel solver #define USE_PARALLEL_DISPATCHER 1 -//following define allows to compare/replace Bullet's constraint solver with ODE quickstep -//this define requires to either add the libquickstep library (win32, see msvc/8/libquickstep.vcproj) or manually add the files from Extras/quickstep -//#define COMPARE_WITH_QUICKSTEP 1 - - #include "btBulletDynamicsCommon.h" #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#ifdef REGISTER_BOX_BOX -#include "../Extras/AlternativeCollisionAlgorithms/BoxBoxCollisionAlgorithm.h" -#endif //REGISTER_BOX_BOX #include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" #ifdef USE_PARALLEL_DISPATCHER @@ -65,9 +44,6 @@ subject to the following restrictions: #endif//USE_PARALLEL_DISPATCHER -#ifdef COMPARE_WITH_QUICKSTEP -#include "../Extras/quickstep/OdeConstraintSolver.h" -#endif //COMPARE_WITH_QUICKSTEP #include "LinearMath/btQuickprof.h" #include "LinearMath/btIDebugDraw.h" @@ -133,10 +109,6 @@ void MultiThreadedDemo::createStack( btCollisionShape* boxShape, float halfCubeS btRigidBody* body = 0; body = localCreateRigidBody(mass,trans,boxShape); -#ifdef USER_DEFINED_FRICTION_MODEL - ///Advanced use: override the friction solver - body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1; -#endif //USER_DEFINED_FRICTION_MODEL } } @@ -164,25 +136,6 @@ void MultiThreadedDemo::clientMoveAndDisplay() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#ifdef USE_KINEMATIC_GROUND - //btQuaternion kinRotation(btVector3(0,0,1),0.); - btVector3 kinTranslation(-0.01,0,0); - //kinematic object - btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[0]; - //is this a rigidbody with a motionstate? then use the motionstate to update positions! - if (btRigidBody::upcast(colObj) && btRigidBody::upcast(colObj)->getMotionState()) - { - btTransform newTrans; - btRigidBody::upcast(colObj)->getMotionState()->getWorldTransform(newTrans); - newTrans.getOrigin()+=kinTranslation; - btRigidBody::upcast(colObj)->getMotionState()->setWorldTransform(newTrans); - } else - { - m_dynamicsWorld->getCollisionObjectArray()[0]->getWorldTransform().getOrigin() += kinTranslation; - } - -#endif //USE_KINEMATIC_GROUND - float dt = m_clock.getTimeMicroseconds() * 0.000001f; m_clock.reset(); @@ -243,12 +196,6 @@ void MultiThreadedDemo::clientMoveAndDisplay() btProfiler::endBlock("render"); #endif glFlush(); - //some additional debugging info -#ifdef PRINT_CONTACT_STATISTICS - printf("num manifolds: %i\n",gNumManifold); - printf("num gOverlappingPairs: %i\n",gOverlappingPairs); - printf("num gTotalContactPoints : %i\n",gTotalContactPoints ); -#endif //PRINT_CONTACT_STATISTICS gTotalContactPoints = 0; glutSwapBuffers(); @@ -291,21 +238,13 @@ void MultiThreadedDemo::initPhysics() m_collisionShapes.push_back(new btBoxShape (btVector3(200,CUBE_HALF_EXTENTS,200))); #endif -#ifdef DO_BENCHMARK_PYRAMIDS m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); -#else - m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); -#endif -#ifdef DO_BENCHMARK_PYRAMIDS setCameraDistance(32.5f); -#endif -#ifdef DO_BENCHMARK_PYRAMIDS m_azi = 90.f; -#endif //DO_BENCHMARK_PYRAMIDS m_dispatcher=0; m_collisionConfiguration = new btDefaultCollisionConfiguration(); @@ -360,28 +299,12 @@ int maxNumOutstandingTasks = 4; m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); #endif //USE_PARALLEL_DISPATCHER -#ifdef USE_CUSTOM_NEAR_CALLBACK - //this is optional - m_dispatcher->setNearCallback(customNearCallback); -#endif btVector3 worldAabbMin(-1000,-1000,-1000); btVector3 worldAabbMax(1000,1000,1000); m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); -/// For large worlds or over 16384 objects, use the bt32BitAxisSweep3 broadphase -// 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 REGISTER_BOX_BOX - m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new BoxBoxCollisionAlgorithm::CreateFunc); -#endif //REGISTER_BOX_BOX -#ifdef COMPARE_WITH_QUICKSTEP - m_solver = new OdeConstraintSolver(); -#else #ifdef USE_PARALLEL_SOLVER @@ -411,9 +334,6 @@ int maxNumOutstandingTasks = 4; #endif //USE_PARALLEL_SOLVER -#endif - - btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = world; @@ -441,7 +361,6 @@ int maxNumOutstandingTasks = 4; } -#ifdef DO_BENCHMARK_PYRAMIDS btTransform trans; trans.setIdentity(); @@ -463,9 +382,6 @@ int maxNumOutstandingTasks = 4; float zPos = (i-numWalls/2) * wallDistance; createStack(m_collisionShapes[shapeIndex[1]],halfExtents,wallHeight,zPos); } -// createStack(m_collisionShapes[shapeIndex[1]],halfExtends,20,10); - -// createStack(m_collisionShapes[shapeIndex[1]],halfExtends,20,20); #define DESTROYER_BALL 1 #ifdef DESTROYER_BALL btTransform sphereTrans; @@ -476,7 +392,6 @@ int maxNumOutstandingTasks = 4; btRigidBody* ballBody = localCreateRigidBody(10000.f,sphereTrans,ball); ballBody->setLinearVelocity(btVector3(0,0,-10)); #endif -#endif //DO_BENCHMARK_PYRAMIDS // clientResetScene(); diff --git a/Demos/OpenGL/DemoApplication.cpp b/Demos/OpenGL/DemoApplication.cpp index 0b9efbc1f..ed25cd04a 100644 --- a/Demos/OpenGL/DemoApplication.cpp +++ b/Demos/OpenGL/DemoApplication.cpp @@ -489,7 +489,7 @@ void DemoApplication::shootBox(const btVector3& destination) if (m_dynamicsWorld) { - float mass = 100.f; + float mass = 10.f; btTransform startTransform; startTransform.setIdentity(); btVector3 camPos = getCameraPosition(); @@ -502,7 +502,7 @@ void DemoApplication::shootBox(const btVector3& destination) btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f)); m_shootBoxShape = new btUniformScalingShape(childShape,0.5f); #else - m_shootBoxShape = new btBoxShape(btVector3(0.5f,0.5f,0.5f)); + m_shootBoxShape = new btBoxShape(btVector3(1.f,1.f,1.f)); #endif// } @@ -736,7 +736,7 @@ btRigidBody* DemoApplication::localCreateRigidBody(float mass, const btTransform #define USE_MOTIONSTATE 1 #ifdef USE_MOTIONSTATE btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(mass,myMotionState,shape,localInertia)); #else btRigidBody* body = new btRigidBody(mass,0,shape,localInertia); diff --git a/Demos/RagdollDemo/RagdollDemo.cpp b/Demos/RagdollDemo/RagdollDemo.cpp index cb32a3ade..d11799bf5 100644 --- a/Demos/RagdollDemo/RagdollDemo.cpp +++ b/Demos/RagdollDemo/RagdollDemo.cpp @@ -98,7 +98,9 @@ class RagDoll shape->calculateLocalInertia(mass,localInertia); btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); - btRigidBody* body = new btRigidBody(mass,myMotionState,shape,localInertia); + + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); m_ownerWorld->addRigidBody(body); diff --git a/Demos/Raytracer/Raytracer.cpp b/Demos/Raytracer/Raytracer.cpp index 41e66f9a1..9b06f639a 100644 --- a/Demos/Raytracer/Raytracer.cpp +++ b/Demos/Raytracer/Raytracer.cpp @@ -133,6 +133,28 @@ void Raytracer::initPhysics() Raytracer::~Raytracer() { + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_collisionWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_collisionWorld->getCollisionObjectArray()[i]; + m_collisionWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision world + delete m_collisionWorld; + + //delete broadphase + delete m_overlappingPairCache; + + //delete dispatcher + delete m_dispatcher; + + delete m_collisionConfiguration; + delete raytracePicture; raytracePicture=0; } diff --git a/Demos/VehicleDemo/VehicleDemo.cpp b/Demos/VehicleDemo/VehicleDemo.cpp index 522ec939f..811c2c248 100644 --- a/Demos/VehicleDemo/VehicleDemo.cpp +++ b/Demos/VehicleDemo/VehicleDemo.cpp @@ -147,9 +147,6 @@ VehicleDemo::~VehicleDemo() void VehicleDemo::initPhysics() { - - extern btScalar gJitterVelocityDampingFactor; - gJitterVelocityDampingFactor = 1.f; #ifdef FORCE_ZAXIS_UP m_cameraUp = btVector3(0,0,1); diff --git a/Extras/BulletMultiThreaded/SpuParallelSolver.cpp b/Extras/BulletMultiThreaded/SpuParallelSolver.cpp index 913eb3b7b..4406f09e0 100644 --- a/Extras/BulletMultiThreaded/SpuParallelSolver.cpp +++ b/Extras/BulletMultiThreaded/SpuParallelSolver.cpp @@ -109,7 +109,7 @@ void btParallelSequentialImpulseSolver::prepareSolve(int numBodies, int numManif btScalar btParallelSequentialImpulseSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) { - PROFILE("parallel_solveGroup"); + BT_PROFILE("parallel_solveGroup"); if (!numManifolds && !numConstraints) return 0; @@ -262,7 +262,7 @@ btAlignedObjectArray solverConstraintPool_persist; void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) { - PROFILE("parallel_allSolved"); + BT_PROFILE("parallel_allSolved"); if (!m_numberOfContacts && !m_sortedConstraints.size()) { @@ -353,7 +353,7 @@ void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& in // Setup all the moving rigid bodies { - PROFILE("setup moving rigidbodies"); + BT_PROFILE("setup moving rigidbodies"); int bodiesPerTask = PARALLEL_SOLVER_BODIES_PER_TASK; int bodiesToSchedule = numBodies; @@ -417,7 +417,7 @@ void btParallelSequentialImpulseSolver::allSolved (const btContactSolverInfo& in } { - PROFILE("parallel_solve_iterations"); + BT_PROFILE("parallel_solve_iterations"); btSpinlock::SpinVariable* spinVar = (btSpinlock::SpinVariable*)btAlignedAlloc(sizeof(btSpinlock::SpinVariable), 128); for (int iter = 0; iter < info.m_numIterations; ++iter) diff --git a/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp b/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp index 6307053e5..fff0e66d2 100644 --- a/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp +++ b/Extras/BulletMultiThreaded/SpuSolverTask/SpuParallellSolverTask.cpp @@ -809,7 +809,7 @@ static int getConstraintSize (btTypedConstraintType type) //-- MAIN METHOD void processSolverTask(void* userPtr, void* lsMemory) { -// PROFILE("processSolverTask"); +// BT_PROFILE("processSolverTask"); SolverTask_LocalStoreMemory* localMemory = (SolverTask_LocalStoreMemory*)lsMemory; diff --git a/Extras/quickstep/OdeConstraintSolver.cpp b/Extras/quickstep/OdeConstraintSolver.cpp index 93ba1e95e..d62c63402 100644 --- a/Extras/quickstep/OdeConstraintSolver.cpp +++ b/Extras/quickstep/OdeConstraintSolver.cpp @@ -69,7 +69,6 @@ OdeConstraintSolver::OdeConstraintSolver(): //iterative lcp and penalty method btScalar OdeConstraintSolver::solveGroup(btCollisionObject** bodies,int numBulletBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* dispatcher) { - BEGIN_PROFILE("prepareConstraints"); m_CurBody = 0; m_CurJoint = 0; @@ -126,9 +125,7 @@ btScalar OdeConstraintSolver::solveGroup(btCollisionObject** bodies,int numBulle // printf(" numJoints > numManifolds * 4 + numConstraints"); - END_PROFILE("prepareConstraints"); - BEGIN_PROFILE("solveConstraints"); - m_SorLcpSolver.SolveInternal1(m_cfm,m_erp,m_odeBodies,numBodies,m_joints,numJoints,infoGlobal,stackAlloc); ///do + m_SorLcpSolver.SolveInternal1(m_cfm,m_erp,m_odeBodies,numBodies,m_joints,numJoints,infoGlobal,stackAlloc); ///do //write back resulting velocities for (int i=0;im_originalBody->setAngularVelocity(m_odeBodies[i]->m_angularVelocity); } } - END_PROFILE("solveConstraints"); - + /// Remotion, just free all this here m_odeBodies.clear(); diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index ac810f492..5e5249d8f 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -115,7 +115,7 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho void btCollisionWorld::updateAabbs() { - PROFILE("updateAabbs"); + BT_PROFILE("updateAabbs"); btTransform predictedTrans; for ( int i=0;icalculateOverlappingPairs(m_dispatcher1); } - END_PROFILE("perform Broadphase Collision Detection"); - - BEGIN_PROFILE("performDiscreteCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); { - PROFILE("dispatchAllCollisionPairs"); + BT_PROFILE("dispatchAllCollisionPairs"); if (dispatcher) dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); } - END_PROFILE("performDiscreteCollisionDetection"); } diff --git a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index 0cc3ac599..d8239127e 100644 --- a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -138,7 +138,7 @@ class btPersistentManifoldSortPredicate void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) { - BEGIN_PROFILE("islandUnionFindAndHeapSort"); + BT_PROFILE("islandUnionFindAndHeapSort"); //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 @@ -295,8 +295,6 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, //int islandId; - END_PROFILE("islandUnionFindAndHeapSort"); - // printf("Start Islands\n"); diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 7619a31dc..91b252527 100644 --- a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -36,9 +36,6 @@ subject to the following restrictions: #include "LinearMath/btAlignedObjectArray.h" -#ifdef USE_PROFILE -#include "LinearMath/btQuickprof.h" -#endif //USE_PROFILE int totalCpd = 0; @@ -434,7 +431,7 @@ void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { - PROFILE("solveGroupCacheFriendlySetup"); + BT_PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; @@ -473,7 +470,6 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol btVector3 color(0,1,0); - BEGIN_PROFILE("gatherSolverData"); //int sizeofSB = sizeof(btSolverBody); //int sizeofSC = sizeof(btSolverConstraint); @@ -706,10 +702,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol } } } - END_PROFILE("gatherSolverData"); - - BEGIN_PROFILE("prepareConstraints"); - + btContactSolverInfo info = infoGlobal; { @@ -743,16 +736,13 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol - - END_PROFILE("prepareConstraints"); return 0.f; } btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { - PROFILE("solveGroupCacheFriendlyIterations"); - BEGIN_PROFILE("solveConstraintsIterations"); + BT_PROFILE("solveGroupCacheFriendlyIterations"); int numConstraintPool = m_tmpSolverConstraintPool.size(); int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); @@ -784,7 +774,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations( for (j=0;jcalculateLocalInertia(mass,localInertia); } void* mem = btAlignedAlloc(sizeof(btRigidBody),16); - btRigidBody* body = new (mem)btRigidBody(mass, 0,shape,localInertia); + btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); + btRigidBody* body = new (mem)btRigidBody(rbci); body->setWorldTransform(trans); body->setUserPointer(user_data); return (plRigidBodyHandle) body; diff --git a/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp index c6c254807..451ec1f54 100644 --- a/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp +++ b/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp @@ -116,14 +116,11 @@ void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) ///calculate time of impact for overlapping pairs - BEGIN_PROFILE("performContinuousCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); if (dispatcher) dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - END_PROFILE("performContinuousCollisionDetection"); - toi = dispatchInfo.m_timeOfImpact; dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; @@ -132,7 +129,6 @@ void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) { - BEGIN_PROFILE("perform Temporal Broadphase Collision Detection"); btVector3 temporalAabbMin,temporalAabbMax; @@ -187,7 +183,6 @@ void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - END_PROFILE("perform Temporal Broadphase Collision Detection"); } diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index ed9a9b4ab..ba89e8c23 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -211,6 +211,24 @@ void btDiscreteDynamicsWorld::clearForces() } } +///apply gravity, call this once per timestep +void btDiscreteDynamicsWorld::applyGravity() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iisActive()) + { + body->applyGravity(); + } + } +} + + + void btDiscreteDynamicsWorld::synchronizeMotionStates() { { @@ -255,7 +273,7 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, { startProfiling(timeStep); - PROFILE("stepSimulation"); + BT_PROFILE("stepSimulation"); int numSimulationSubSteps = 0; @@ -294,6 +312,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, saveKinematicState(fixedTimeStep); + applyGravity(); + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; @@ -317,7 +337,7 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) { - PROFILE("internalSingleStepSimulation"); + BT_PROFILE("internalSingleStepSimulation"); ///apply gravity, predict motion predictUnconstraintMotion(timeStep); @@ -407,21 +427,18 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) { - PROFILE("updateVehicles"); - BEGIN_PROFILE("updateVehicles"); - + BT_PROFILE("updateVehicles"); + for ( int i=0;iupdateVehicle( timeStep); } - END_PROFILE("updateVehicles"); } void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) { - PROFILE("updateActivationState"); - BEGIN_PROFILE("updateActivationState"); + BT_PROFILE("updateActivationState"); for ( int i=0;iupdateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); @@ -647,16 +662,14 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() //Store the island id in each body getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); - END_PROFILE("calculateSimulationIslands"); - + } void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { - PROFILE("integrateTransforms"); - BEGIN_PROFILE("integrateTransforms"); + BT_PROFILE("integrateTransforms"); btTransform predictedTrans; for ( int i=0;iisActive()) { - body->applyForces( timeStep); body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } } } - END_PROFILE("predictUnconstraintMotion"); } diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 878b97497..9d21c756a 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -59,7 +59,7 @@ protected: int m_profileTimings; - void predictUnconstraintMotion(btScalar timeStep); + virtual void predictUnconstraintMotion(btScalar timeStep); void integrateTransforms(btScalar timeStep); @@ -148,10 +148,13 @@ public: { 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(); + }; diff --git a/src/BulletDynamics/Dynamics/btRigidBody.cpp b/src/BulletDynamics/Dynamics/btRigidBody.cpp index 8022a8bfa..690662366 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -20,38 +20,51 @@ subject to the following restrictions: #include "LinearMath/btMotionState.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -btScalar gLinearAirDamping = btScalar(1.); //'temporarily' global variables btScalar gDeactivationTime = btScalar(2.); bool gDisableDeactivation = false; - -btScalar gLinearSleepingThreshold = btScalar(0.8); -btScalar gAngularSleepingThreshold = btScalar(1.0); static int uniqueId = 0; -btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_angularFactor(btScalar(1.)), - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_linearSleepingThreshold(gLinearSleepingThreshold), - m_angularSleepingThreshold(gAngularSleepingThreshold), - m_optionalMotionState(motionState), - m_contactSolverType(0), - m_frictionSolverType(0) + +btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + setupRigidBody(constructionInfo); +} + +btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) +{ + btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); + setupRigidBody(cinfo); +} + +void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) { - if (motionState) + m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + m_angularFactor = btScalar(1.); + m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearDamping = btScalar(0.); + m_angularDamping = btScalar(0.5); + m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; + m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; + m_optionalMotionState = constructionInfo.m_motionState; + m_contactSolverType = 0; + m_frictionSolverType = 0; + m_additionalDamping = constructionInfo.m_additionalDamping; + + m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; + m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; + m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; + + if (m_optionalMotionState) { - motionState->getWorldTransform(m_worldTransform); + m_optionalMotionState->getWorldTransform(m_worldTransform); } else { - m_worldTransform = btTransform::getIdentity(); + m_worldTransform = constructionInfo.m_startWorldTransform; } m_interpolationWorldTransform = m_worldTransform; @@ -59,93 +72,24 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS m_interpolationAngularVelocity.setValue(0,0,0); //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; + m_friction = constructionInfo.m_friction; + m_restitution = constructionInfo.m_restitution; - m_collisionShape = collisionShape; + m_collisionShape = constructionInfo.m_collisionShape; m_debugBodyId = uniqueId++; //m_internalOwner is to allow upcasting from collision object to rigid body m_internalOwner = this; - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); + setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); + setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); updateInertiaTensor(); } -#ifdef OBSOLETE_MOTIONSTATE_LESS -btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_linearSleepingThreshold(gLinearSleepingThreshold), - m_angularSleepingThreshold(gAngularSleepingThreshold), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(0), - m_contactSolverType(0), - m_frictionSolverType(0) - -{ - - m_worldTransform = worldTransform; - m_interpolationWorldTransform = m_worldTransform; - m_interpolationLinearVelocity.setValue(0,0,0); - m_interpolationAngularVelocity.setValue(0,0,0); - - //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; - - m_collisionShape = collisionShape; - m_debugBodyId = uniqueId++; - - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); - updateInertiaTensor(); - -} - -#endif //OBSOLETE_MOTIONSTATE_LESS - - - - -#define EXPERIMENTAL_JITTER_REMOVAL 1 -#ifdef EXPERIMENTAL_JITTER_REMOVAL -//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate -//doesn't work very well yet (value 0 disabled this damping) -//note there this influences deactivation thresholds! -btScalar gClippedAngvelThresholdSqr = btScalar(0.01); -btScalar gClippedLinearThresholdSqr = btScalar(0.01); -#endif //EXPERIMENTAL_JITTER_REMOVAL - -btScalar gJitterVelocityDampingFactor = btScalar(0.7); void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) { - -#ifdef EXPERIMENTAL_JITTER_REMOVAL - //if (wantsSleeping()) - { - //clip to avoid jitter - if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && - (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) - { - m_angularVelocity *= gJitterVelocityDampingFactor; - m_linearVelocity *= gJitterVelocityDampingFactor; - } - } - -#endif //EXPERIMENTAL_JITTER_REMOVAL - btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); } @@ -196,50 +140,63 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) -#include + +///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping +void btRigidBody::applyDamping(btScalar timeStep) +{ + m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + + if (m_additionalDamping) + { + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && + (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) + { + m_angularVelocity *= m_additionalDampingFactor; + m_linearVelocity *= m_additionalDampingFactor; + } + + + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + } +} -void btRigidBody::applyForces(btScalar step) +void btRigidBody::applyGravity() { if (isStaticOrKinematicObject()) return; applyCentralForce(m_gravity); - - m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); -#define FORCE_VELOCITY_DAMPING 1 -#ifdef FORCE_VELOCITY_DAMPING - btScalar speed = m_linearVelocity.length(); - if (speed < m_linearDamping) - { - btScalar dampVel = btScalar(0.005); - if (speed > dampVel) - { - btVector3 dir = m_linearVelocity.normalized(); - m_linearVelocity -= dir * dampVel; - } else - { - m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - - btScalar angSpeed = m_angularVelocity.length(); - if (angSpeed < m_angularDamping) - { - btScalar angDampVel = btScalar(0.005); - if (angSpeed > angDampVel) - { - btVector3 dir = m_angularVelocity.normalized(); - m_angularVelocity -= dir * angDampVel; - } else - { - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } -#endif //FORCE_VELOCITY_DAMPING - } void btRigidBody::proceedToTransform(const btTransform& newTrans) diff --git a/src/BulletDynamics/Dynamics/btRigidBody.h b/src/BulletDynamics/Dynamics/btRigidBody.h index b11f9f76d..c9badae9f 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/src/BulletDynamics/Dynamics/btRigidBody.h @@ -27,16 +27,18 @@ class btMotionState; class btTypedConstraint; -extern btScalar gLinearAirDamping; - extern btScalar gDeactivationTime; extern bool gDisableDeactivation; -extern btScalar gLinearSleepingThreshold; -extern btScalar gAngularSleepingThreshold; -/// btRigidBody class for btRigidBody Dynamics -/// +///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. +///There are 3 types of rigid bodies: +///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. +///- B) Fixed objects with zero mass. They are not moving (basically collision objects) +///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. +///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. +///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) class btRigidBody : public btCollisionObject { @@ -54,9 +56,15 @@ class btRigidBody : public btCollisionObject btScalar m_linearDamping; btScalar m_angularDamping; + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + btScalar m_linearSleepingThreshold; btScalar m_angularSleepingThreshold; - //m_optionalMotionState allows to automatic synchronize the world transform for active objects btMotionState* m_optionalMotionState; @@ -66,20 +74,85 @@ class btRigidBody : public btCollisionObject public: -#ifdef OBSOLETE_MOTIONSTATE_LESS - //not supported, please use btMotionState - btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); -#endif //OBSOLETE_MOTIONSTATE_LESS - btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); + ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) + ///You can use the motion state to synchronize the world transform between physics and graphics objects. + ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, + ///m_startWorldTransform is only used when you don't provide a motion state. + struct btRigidBodyConstructionInfo + { + btScalar m_mass; - virtual ~btRigidBody() + ///When a motionState is provided, the rigid body will initialize its world transform from the motion state + ///In this case, m_startWorldTransform is ignored. + btMotionState* m_motionState; + btTransform m_startWorldTransform; + + btCollisionShape* m_collisionShape; + btVector3 m_localInertia; + btScalar m_linearDamping; + btScalar m_angularDamping; + + ///best simulation results when friction is non-zero + btScalar m_friction; + ///best simulation results using zero restitution. + btScalar m_restitution; + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): + m_mass(mass), + m_motionState(motionState), + m_collisionShape(collisionShape), + m_localInertia(localInertia), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), + m_linearSleepingThreshold(btScalar(0.8)), + m_angularSleepingThreshold(btScalar(1.f)), + m_additionalDamping(false), + m_additionalDampingFactor(btScalar(0.005)), + m_additionalLinearDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingFactor(btScalar(0.01)) + { + m_startWorldTransform.setIdentity(); + } + }; + + ///btRigidBody constructor using construction info + btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); + + + virtual ~btRigidBody() { //No constraints should point to this rigidbody //Remove constraints from the dynamics world before you delete the related rigidbodies. btAssert(m_constraintRefs.size()==0); } +protected: + + ///setupRigidBody is only used internally by the constructor + void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); + +public: void proceedToTransform(const btTransform& newTrans); @@ -99,8 +172,7 @@ public: void saveKinematicState(btScalar step); - - void applyForces(btScalar step); + void applyGravity(); void setGravity(const btVector3& acceleration); @@ -110,7 +182,9 @@ public: } void setDamping(btScalar lin_damping, btScalar ang_damping); - + + void applyDamping(btScalar timeStep); + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } diff --git a/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 54925d480..13c0548ed 100644 --- a/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -188,8 +188,9 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { if (body->isActive()) { - body->applyForces( timeStep); + body->applyGravity(); body->integrateVelocities( timeStep); + body->applyDamping(timeStep); body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } diff --git a/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index 3b0c31b1e..ee5ad54e5 100644 --- a/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -23,8 +23,6 @@ #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" - - static btRigidBody s_fixedObject( 0,0,0); btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) diff --git a/src/LinearMath/btQuickprof.cpp b/src/LinearMath/btQuickprof.cpp index cc69888f8..364b5a575 100644 --- a/src/LinearMath/btQuickprof.cpp +++ b/src/LinearMath/btQuickprof.cpp @@ -1,42 +1,4 @@ /* -Copyright (c) 2006 Tyler Streeter - -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. - -*/ - - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. - -// Credits: The Clock class was inspired by the Timer classes in -// Ogre (www.ogre3d.org). - -#include "LinearMath/btQuickprof.h" - -#ifdef USE_QUICKPROF - -// Note: We must declare these private static variables again here to -// avoid link errors. -bool btProfiler::mEnabled = false; -btClock btProfiler::mClock; -unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; -unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; -std::map btProfiler::mProfileBlocks; -std::ofstream btProfiler::mOutputFile; -bool btProfiler::mFirstFileOutput = true; -btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; -unsigned long int btProfiler::mCycleNumber = 0; -#endif //USE_QUICKPROF - /*************************************************************************************************** ** @@ -48,6 +10,11 @@ unsigned long int btProfiler::mCycleNumber = 0; ** ***************************************************************************************************/ +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + +#include "LinearMath/btQuickprof.h" + static btClock gProfileClock; inline void Profile_Get_Ticks(unsigned long int * ticks) diff --git a/src/LinearMath/btQuickprof.h b/src/LinearMath/btQuickprof.h index 1476c4777..35a87cece 100644 --- a/src/LinearMath/btQuickprof.h +++ b/src/LinearMath/btQuickprof.h @@ -1,20 +1,11 @@ -/* -Copyright (c) 2006 Tyler Streeter - -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. - -*/ -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. +/*************************************************************************************************** +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). @@ -24,8 +15,8 @@ subject to the following restrictions: #include "btScalar.h" -//#define USE_QUICKPROF 1 -//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 //if you don't need btClock, you can comment next line @@ -235,489 +226,8 @@ class btClock #endif //USE_BT_CLOCK -#ifdef USE_QUICKPROF -#include -#include -#include -#include - - - - -namespace hidden -{ - /// A simple data structure representing a single timed block - /// of code. - struct ProfileBlock - { - ProfileBlock() - { - currentBlockStartMicroseconds = 0; - currentCycleTotalMicroseconds = 0; - lastCycleTotalMicroseconds = 0; - totalMicroseconds = 0; - } - - /// The starting time (in us) of the current block update. - unsigned long int currentBlockStartMicroseconds; - - /// The accumulated time (in us) spent in this block during the - /// current profiling cycle. - unsigned long int currentCycleTotalMicroseconds; - - /// The accumulated time (in us) spent in this block during the - /// past profiling cycle. - unsigned long int lastCycleTotalMicroseconds; - - /// The total accumulated time (in us) spent in this block. - unsigned long int totalMicroseconds; - }; - -}; - -/// A static class that manages timing for a set of profiling blocks. -class btProfiler -{ -public: - /// A set of ways to retrieve block timing data. - enum BlockTimingMethod - { - /// The total time spent in the block (in seconds) since the - /// profiler was initialized. - BLOCK_TOTAL_SECONDS, - - /// The total time spent in the block (in ms) since the - /// profiler was initialized. - BLOCK_TOTAL_MILLISECONDS, - - /// The total time spent in the block (in us) since the - /// profiler was initialized. - BLOCK_TOTAL_MICROSECONDS, - - /// The total time spent in the block, as a % of the total - /// elapsed time since the profiler was initialized. - BLOCK_TOTAL_PERCENT, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle. - BLOCK_CYCLE_SECONDS, - - /// The time spent in the block (in ms) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MILLISECONDS, - - /// The time spent in the block (in us) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MICROSECONDS, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle, as a % of the total cycle time. - BLOCK_CYCLE_PERCENT - }; - - /// Initializes the profiler. This must be called first. If this is - /// never called, the profiler is effectively disabled; all other - /// functions will return immediately. The first parameter - /// is the name of an output data file; if this string is not empty, - /// data will be saved on every profiling cycle; if this string is - /// empty, no data will be saved to a file. The second parameter - /// determines which timing method is used when printing data to the - /// output file. - inline static void init(const std::string outputFilename="", - BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); - - /// Cleans up allocated memory. - inline static void destroy(); - - /// Begins timing the named block of code. - inline static void beginBlock(const std::string& name); - - /// Updates the accumulated time spent in the named block by adding - /// the elapsed time since the last call to startBlock for this block - /// name. - inline static void endBlock(const std::string& name); - - /// Returns the time spent in the named block according to the - /// given timing method. See comments on BlockTimingMethod for details. - inline static double getBlockTime(const std::string& name, - BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); - - /// Defines the end of a profiling cycle. Use this regularly if you - /// want to generate detailed timing information. This must not be - /// called within a timing block. - inline static void endProfilingCycle(); - - /// A helper function that creates a string of statistics for - /// each timing block. This is mainly for printing an overall - /// summary to the command line. - inline static std::string createStatsString( - BlockTimingMethod method=BLOCK_TOTAL_PERCENT); - -//private: - inline btProfiler(); - - inline ~btProfiler(); - - /// Prints an error message to standard output. - inline static void printError(const std::string& msg) - { - //btAssert(0); - std::cout << "[QuickProf error] " << msg << std::endl; - } - - /// Determines whether the profiler is enabled. - static bool mEnabled; - - /// The clock used to time profile blocks. - static btClock mClock; - - /// The starting time (in us) of the current profiling cycle. - static unsigned long int mCurrentCycleStartMicroseconds; - - /// The duration (in us) of the most recent profiling cycle. - static unsigned long int mLastCycleDurationMicroseconds; - - /// Internal map of named profile blocks. - static std::map mProfileBlocks; - - /// The data file used if this feature is enabled in 'init.' - static std::ofstream mOutputFile; - - /// Tracks whether we have begun print data to the output file. - static bool mFirstFileOutput; - - /// The method used when printing timing data to an output file. - static BlockTimingMethod mFileOutputMethod; - - /// The number of the current profiling cycle. - static unsigned long int mCycleNumber; -}; - - -btProfiler::btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -btProfiler::~btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -void btProfiler::init(const std::string outputFilename, - BlockTimingMethod outputMethod) -{ - mEnabled = true; - - if (!outputFilename.empty()) - { - mOutputFile.open(outputFilename.c_str()); - } - - mFileOutputMethod = outputMethod; - - mClock.reset(); - - // Set the start time for the first cycle. - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::destroy() -{ - if (!mEnabled) - { - return; - } - - if (mOutputFile.is_open()) - { - mOutputFile.close(); - } - - // Destroy all ProfileBlocks. - while (!mProfileBlocks.empty()) - { - delete (*mProfileBlocks.begin()).second; - mProfileBlocks.erase(mProfileBlocks.begin()); - } -} - -void btProfiler::beginBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - if (name.empty()) - { - printError("Cannot allow unnamed profile blocks."); - return; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // Create a new ProfileBlock. - mProfileBlocks[name] = new hidden::ProfileBlock(); - block = mProfileBlocks[name]; - } - - // We do this at the end to get more accurate results. - block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::endBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - // We do this at the beginning to get more accurate results. - unsigned long int endTick = mClock.getTimeMicroseconds(); - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return; - } - - unsigned long int blockDuration = endTick - - block->currentBlockStartMicroseconds; - block->currentCycleTotalMicroseconds += blockDuration; - block->totalMicroseconds += blockDuration; -} - -double btProfiler::getBlockTime(const std::string& name, - BlockTimingMethod method) -{ - if (!mEnabled) - { - return 0; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return 0; - } - - double result = 0; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - result = (double)block->totalMicroseconds * (double)0.000001; - break; - case BLOCK_TOTAL_MILLISECONDS: - result = (double)block->totalMicroseconds * (double)0.001; - break; - case BLOCK_TOTAL_MICROSECONDS: - result = (double)block->totalMicroseconds; - break; - case BLOCK_TOTAL_PERCENT: - { - double timeSinceInit = (double)mClock.getTimeMicroseconds(); - if (timeSinceInit <= 0) - { - result = 0; - } - else - { - result = 100.0 * (double)block->totalMicroseconds / - timeSinceInit; - } - break; - } - case BLOCK_CYCLE_SECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.000001; - break; - case BLOCK_CYCLE_MILLISECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.001; - break; - case BLOCK_CYCLE_MICROSECONDS: - result = (double)block->lastCycleTotalMicroseconds; - break; - case BLOCK_CYCLE_PERCENT: - { - if (0 == mLastCycleDurationMicroseconds) - { - // We have not yet finished a cycle, so just return zero - // percent to avoid a divide by zero error. - result = 0; - } - else - { - result = 100.0 * (double)block->lastCycleTotalMicroseconds / - mLastCycleDurationMicroseconds; - } - break; - } - default: - break; - } - - return result; -} - -void btProfiler::endProfilingCycle() -{ - if (!mEnabled) - { - return; - } - - // Store the duration of the cycle that just finished. - mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - - mCurrentCycleStartMicroseconds; - - // For each block, update data for the cycle that just finished. - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - hidden::ProfileBlock* block = (*iter).second; - block->lastCycleTotalMicroseconds = - block->currentCycleTotalMicroseconds; - block->currentCycleTotalMicroseconds = 0; - } - - if (mOutputFile.is_open()) - { - // Print data to the output file. - if (mFirstFileOutput) - { - // On the first iteration, print a header line that shows the - // names of each profiling block. - mOutputFile << "#cycle, "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << (*iter).first << ", "; - } - - mOutputFile << std::endl; - mFirstFileOutput = false; - } - - mOutputFile << mCycleNumber << ", "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) - << ", "; - } - - mOutputFile << std::endl; - } - - ++mCycleNumber; - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -std::string btProfiler::createStatsString(BlockTimingMethod method) -{ - if (!mEnabled) - { - return ""; - } - - std::string s; - std::string suffix; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - suffix = "s"; - break; - case BLOCK_TOTAL_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_TOTAL_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_TOTAL_PERCENT: - { - suffix = "%"; - break; - } - case BLOCK_CYCLE_SECONDS: - suffix = "s"; - break; - case BLOCK_CYCLE_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_CYCLE_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_CYCLE_PERCENT: - { - suffix = "%"; - break; - } - default: - break; - } - - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - if (iter != mProfileBlocks.begin()) - { - s += "\n"; - } - - char blockTime[64]; - sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); - - s += (*iter).first; - s += ": "; - s += blockTime; - s += " "; - s += suffix; - } - - return s; -} - - -#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) -#define END_PROFILE(a) btProfiler::endBlock(a) - -#else //USE_QUICKPROF -#define BEGIN_PROFILE(a) -#define END_PROFILE(a) - -#endif //USE_QUICKPROF - - -/*************************************************************************************************** -** -** profile.h -** -** Real-Time Hierarchical Profiling for Game Programming Gems 3 -** -** by Greg Hjelstrom & Byon Garrabrant -** -***************************************************************************************************/ - /* ** A node in the Profile Hierarchy Tree */ @@ -816,7 +326,7 @@ private: /* ** ProfileSampleClass is a simple way to profile a function's scope -** Use the PROFILE macro at the start of scope to time +** Use the BT_PROFILE macro at the start of scope to time */ class CProfileSample { public: @@ -831,10 +341,10 @@ public: } }; -#if !defined(NO_PROFILE) -#define PROFILE( name ) CProfileSample __profile( name ) +#if !defined(BT_NO_PROFILE) +#define BT_PROFILE( name ) CProfileSample __profile( name ) #else -#define PROFILE( name ) +#define BT_PROFILE( name ) #endif