A ball never gets stopped....

benny.mo.777
Posts: 5
Joined: Tue Jan 04, 2011 12:49 pm

A ball never gets stopped....

Post by benny.mo.777 »

Hi people,

I'm new to bullet.

I modified a BasicDemo bundled with bullet 2.77 to drop a ball ( sphere shape ) over a board, rotated 22.5 degrees around z-axis.
The ball bounces off the board, finally hit the ground and roll on the ground but never gets stopped... it ends up with falling down from the ground.
I expected the ball rolls on the ground and finally stopped.

Plz take a look at the attached animation gif.

How can I make the ball stopped ?

Here is the full source.
--------------------------------------------------------------------------------------------------------------------------
/*
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.
*/

//#define TEST_SERIALIZATION 1

///create 125 (5x5x5) dynamic object
/****************
* Only one dynamic object (sphere shape)
***************/
#define ARRAY_SIZE_X 1
#define ARRAY_SIZE_Y 1
#define ARRAY_SIZE_Z 1

//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 "BasicDemo.h"
#include "GlutStuff.h"
///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
#include "btBulletDynamicsCommon.h"
#ifdef TEST_SERIALIZATION
#include "LinearMath/btSerializer.h"
#endif //TEST_SERIALIZATION

#include <stdio.h> //printf debugging
#include <math.h> /* for cos(), sin(), and sqrt() */

void BasicDemo::clientMoveAndDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//simple dynamics world doesn't handle fixed-time-stepping
float ms = getDeltaTimeMicroseconds();

///step the simulation
if (m_dynamicsWorld)
{
m_dynamicsWorld->stepSimulation(ms / 60.f);
//optional but useful: debug drawing
m_dynamicsWorld->debugDrawWorld();
}

renderme();

glFlush();

swapBuffers();

}



void BasicDemo::displayCallback(void) {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

renderme();

//optional but useful: debug drawing to detect problems
if (m_dynamicsWorld)
m_dynamicsWorld->debugDrawWorld();

glFlush();
swapBuffers();
}





void BasicDemo::initPhysics()
{
setTexturing(true);
setShadows(true);

setCameraDistance(btScalar(SCALING*50.));

///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->setGravity(btVector3(0,-10,0));

/********************
* ground
********************/
{
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(30.),btScalar(50.)));
// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);

m_collisionShapes.push_back(groundShape);

btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-30,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->setRestitution(0.9f);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}

/********************
* a board, rotated 22.5 degrees around Z-axis
********************/
{
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(5.),btScalar(0.5),btScalar(5.)));
// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);

m_collisionShapes.push_back(groundShape);

btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(-6,6,0));

/***************
* rotate
**************/
btQuaternion quat(0,0, sin(((btScalar)3.14/8)/2), cos(((btScalar)3.14/8)/2));
groundTransform.setRotation(quat);
//body->setCenterOfMassTransform(trans);

//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->setRestitution(0.9f);

//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}


/********************
* a ball (shpere shape)
********************/
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance

// btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1));
btCollisionShape* colShape = new btSphereShape(SCALING*1);
//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
m_collisionShapes.push_back(colShape);

/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();

btScalar mass(10.f);

//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)
colShape->calculateLocalInertia(mass,localInertia);

float start_x = START_POS_X - ARRAY_SIZE_X/2;
float start_y = START_POS_Y;
float start_z = START_POS_Z - ARRAY_SIZE_Z/2;

for (int k=0;k<ARRAY_SIZE_Y;k++)
{
for (int i=0;i<ARRAY_SIZE_X;i++)
{
for(int j = 0;j<ARRAY_SIZE_Z;j++)
{
startTransform.setOrigin(SCALING*btVector3(
btScalar(2.0*i + start_x),
btScalar(20+2.0*k + start_y),
btScalar(2.0*j + start_z)));


//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->setRestitution(0.9f);

body->setActivationState(ISLAND_SLEEPING);

m_dynamicsWorld->addRigidBody(body);
body->setActivationState(ISLAND_SLEEPING);
}
}
}
}


clientResetScene();


#ifdef TEST_SERIALIZATION
//test serializing this

int maxSerializeBufferSize = 1024*1024*5;

btDefaultSerializer* serializer = new btDefaultSerializer(maxSerializeBufferSize);
m_dynamicsWorld->serialize(serializer);

FILE* f2 = fopen("testFile.bullet","wb");
fwrite(serializer->m_buffer,serializer->m_currentSize,1,f2);
fclose(f2);
#endif

#if 0
bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile("testFile.bullet");
bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
bool verboseDumpAllTypes = true;
if (ok)
bulletFile2->parse(verboseDumpAllTypes);

if (verboseDumpAllTypes)
{
bulletFile2->dumpChunks(bulletFile2->getFileDNA());
}
#endif //TEST_SERIALIZATION

}


void BasicDemo::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();
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<m_collisionShapes.size();j++)
{
btCollisionShape* shape = m_collisionShapes[j];
delete shape;
}

delete m_dynamicsWorld;

delete m_solver;

delete m_broadphase;

delete m_dispatcher;

delete m_collisionConfiguration;


}
----------------------------------------------------------------------------------------------------------------
You do not have the required permissions to view the files attached to this post.
lulzfish
Posts: 43
Joined: Mon Jan 03, 2011 4:26 pm

Re: A ball never gets stopped....

Post by lulzfish »

This is because the ball and floor are perfectly rigid, so there's no rolling resistance. In the ideal world simulated by a physics engine, balls or cylinders do roll forever.

Edit: In the real world, either the rolling object (like a tire) or the surface (like a wood floor or carpeting) will be slightly soft, and will deform slightly during the rolling, and this deformation converts some of the kinetic energy to heat. Of course, that is not simulated unless you're doing really intense soft-body, which is unnecessary.

So you need a way to dampen it. You could get its angular velocity after each step, then apply a small torque opposite to that, so that it gradually slows down. I don't know if Bullet provides a way to do this automatically, you might check the forums / documentation for "angular damping" or something.
Last edited by lulzfish on Tue Jan 04, 2011 5:21 pm, edited 1 time in total.
benny.mo.777
Posts: 5
Joined: Tue Jan 04, 2011 12:49 pm

Re: A ball never gets stopped....

Post by benny.mo.777 »

Hi, lulzfish.

Thanks for ur quick res !

I'll check it out.

-benny
winspear
Posts: 77
Joined: Thu Nov 26, 2009 6:32 pm

Re: A ball never gets stopped....

Post by winspear »

You can also set friction or restitution using

body->setRestitution( restitution );
body->setFriction(0.25);
apanloco
Posts: 7
Joined: Wed Dec 29, 2010 12:08 am

Re: A ball never gets stopped....

Post by apanloco »

And on top of that, you can also set the damping on the body:
body->setDamping(linearDamping, angularDamping); // (0.0 -> 1.0)