diff --git a/examples/Benchmarks/BenchmarkDemo.cpp b/examples/Benchmarks/BenchmarkDemo.cpp index f5e6b88b8..ca9f75786 100644 --- a/examples/Benchmarks/BenchmarkDemo.cpp +++ b/examples/Benchmarks/BenchmarkDemo.cpp @@ -391,6 +391,7 @@ void BenchmarkDemo::initPhysics() m_dynamicsWorld->getSolverInfo().m_solverMode |=SOLVER_ENABLE_FRICTION_DIRECTION_CACHING; //don't recalculate friction values each frame dynamicsWorld->getSolverInfo().m_numIterations = 5; //few solver iterations //m_defaultContactProcessingThreshold = 0.f;//used when creating bodies: body->setContactProcessingThreshold(...); + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->setGravity(btVector3(0,-10,0)); diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index de711d0aa..0542891c1 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -23,6 +23,8 @@ SET(App_ExampleBrowser_SRCS ../GyroscopicDemo/GyroscopicSetup.h ../Planar2D/Planar2D.cpp ../Planar2D/Planar2D.h + ../RollingFrictionDemo/RollingFrictionDemo.cpp + ../RollingFrictionDemo/RollingFrictionDemo.h ../FractureDemo/FractureDemo.cpp ../FractureDemo/btFractureBody.cpp ../FractureDemo/btFractureDynamicsWorld.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 135a7b64a..2b2b745e9 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -30,7 +30,7 @@ #include "../Raycast/RaytestDemo.h" #include "../FractureDemo/FractureDemo.h" #include "../DynamicControlDemo/MotorDemo.h" - +#include "../RollingFrictionDemo/RollingFrictionDemo.h" #ifdef B3_USE_CLEW #include "../OpenCL/broadphase/PairBench.h" @@ -65,8 +65,10 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(0,"API"), - ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. ", BasicExampleCreateFunc), + ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. Press D to toggle auto-deactivation of the simulation. ", BasicExampleCreateFunc), + ExampleEntry(1,"Rolling Friction", "Damping is often not good enough to keep rounded objects from rolling down a sloped surface. Instead, you can set the rolling friction of a rigid body. Generally it is best to leave the rolling friction to zero, to avoid artifacts.", RollingFrictionCreateFunc), + ExampleEntry(1,"Constraints","Show the use of the various constraints in Bullet. Press the L key to visualize the constraint limits. Press the C key to visualize the constraint frames.", AllConstraintCreateFunc), diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index 769ef9042..de359e4ff 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -54,6 +54,7 @@ "../RenderingExamples/*", "../VoronoiFracture/*", "../SoftDemo/*", + "../RollingFrictionDemo/*", "../FractureDemo/*", "../DynamicControlDemo/*", "../Constraints/*", diff --git a/examples/RollingFrictionDemo/RollingFrictionDemo.cpp b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp new file mode 100644 index 000000000..bfa264535 --- /dev/null +++ b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp @@ -0,0 +1,278 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +///create 125 (5x5x5) dynamic object +#define ARRAY_SIZE_X 5 +#define ARRAY_SIZE_Y 5 +#define ARRAY_SIZE_Z 5 + +//maximum number of objects (and allow user to shoot additional boxes) +#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024) + +///scaling of the objects (0.1 = 20 centimeter boxes ) +#define SCALING 1. +#define START_POS_X -5 +#define START_POS_Y -5 +#define START_POS_Z -3 + +#include "RollingFrictionDemo.h" +///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. +#include "btBulletDynamicsCommon.h" +#include //printf debugging + + +#include "../CommonInterfaces/CommonRigidBodyBase.h" + + +///The RollingFrictionDemo shows the use of rolling friction. +///Spheres will come to a rest on a sloped plane using a constraint. Damping cannot achieve the same. +///Generally it is best to leave the rolling friction coefficient zero (or close to zero). +class RollingFrictionDemo : public CommonRigidBodyBase +{ +public: + + RollingFrictionDemo(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~RollingFrictionDemo() + { + + } + void initPhysics(); + + void exitPhysics(); + + +}; + + + + + + +void RollingFrictionDemo::initPhysics() +{ + + m_guiHelper->setUpAxis(1); + + + ///collision configuration contains default setup for memory, collision setup + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); +// m_dynamicsWorld->getSolverInfo().m_singleAxisRollingFrictionThreshold = 0.f;//faster but lower quality + m_dynamicsWorld->setGravity(btVector3(0,-10,0)); + + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + + { + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(20.),btScalar(50.),btScalar(10.))); + + // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + groundTransform.setRotation(btQuaternion(btVector3(0,0,1),SIMD_PI*0.03)); + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + btScalar mass(0.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + body->setFriction(1); + body->setRollingFriction(1); + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + { + + ///create a few basic rigid bodies + btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(100.),btScalar(50.),btScalar(100.))); + + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-54,0)); + //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here: + btScalar mass(0.); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + groundShape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + body->setFriction(1); + body->setRollingFriction(1); + //add the body to the dynamics world + m_dynamicsWorld->addRigidBody(body); + } + + { + //create a few dynamic rigidbodies + // Re-using the same collision is better for memory usage and performance +#define NUM_SHAPES 10 + btCollisionShape* colShapes[NUM_SHAPES] = { + new btSphereShape(btScalar(1.)), + new btCapsuleShape(0.5,1), + new btCapsuleShapeX(0.5,1), + new btCapsuleShapeZ(0.5,1), + new btConeShape(0.5,1), + new btConeShapeX(0.5,1), + new btConeShapeZ(0.5,1), + new btCylinderShape(btVector3(0.5,1,0.5)), + new btCylinderShapeX(btVector3(1,0.5,0.5)), + new btCylinderShapeZ(btVector3(0.5,0.5,1)), + }; + for (int i=0;icalculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); + btRigidBody* body = new btRigidBody(rbInfo); + body->setFriction(1.f); + body->setRollingFriction(.3); + body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + + + m_dynamicsWorld->addRigidBody(body); + } + } + } + } + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); + +} + + + +void RollingFrictionDemo::exitPhysics() +{ + + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject( obj ); + delete obj; + } + + //delete collision shapes + for (int j=0;j