Help needed. No collision response

Ohlenburg
Posts: 2
Joined: Mon Aug 06, 2007 1:16 pm

Help needed. No collision response

Post by Ohlenburg »

Hi everybody,
I am new to the Bullet SDK and I am already stuck at the first try to integrate Bullet into an existing 3D engine.

For my for test I looked at the tutorial BasicDemo. Could you please tell me what I am missing?

First, this is how I init Bullet:

Code: Select all

	dispatcher = new btCollisionDispatcher(true);

	btCollisionAlgorithmCreateFunc * sphereSphereCF = new btSphereSphereCollisionAlgorithm::CreateFunc;
	dispatcher->registerCollisionCreateFunc(SPHERE_SHAPE_PROXYTYPE, SPHERE_SHAPE_PROXYTYPE, sphereSphereCF);

	broadphase = new btSimpleBroadphase;
	solver = new btSequentialImpulseConstraintSolver;

	dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver);
	dynamicsWorld->setGravity(btVector3(0.0, -10.0 , 0.0));
Then I create a static ground sphere. Please not, that I use my own Sphere class. It is located at the origin of the coordinate system and has a radius of 7 m.

Code: Select all

	RSG::ObjectRef groundSphere = RSG::Object::newObject<Sphere>();
	groundSphere->setField(RSG::Sphere::RADIUS_FIELD_ID, 7.0);
	createObject(groundSphere);
Here is the method createObject:

Code: Select all

void BulletTest::createObject(RSG::ObjectRef node, double mass = 0.0)
{
	if (node->getClassId() == RSG::Sphere::getStaticClassId())
	{ 
		double radius = node->getField<double>(RSG::Sphere::RADIUS_FIELD_ID);
		HomogenousMatrixD4 transform = node->getField<HomogenousMatrixD4>(RSG::Sphere::TRANSFORMATION_FIELD_ID);
		btCollisionShape* shape = new btSphereShape(btScalar(radius));
		btVector3 localInertia(0, 0, 0)
		if (mass > 0.0)
			shape->calculateLocalInertia(mass, localInertia);
		TestMotionState * motionState = new TestMotionState(node, transform);
		btRigidBody* body = new btRigidBody(0.0, motionState, shape, localInertia);
		dynamicsWorld->addRigidBody(body);

		body->setWorldTransform( motionState->transform );
		body->activate();
		if (mass > 0.0)
		{
			body->setLinearVelocity(btVector3(0,0,0));
			body->setAngularVelocity(btVector3(0,0,0));
		}
	}
	sceneref->addChildNode(node);
}
Afterwards I create 50 spheres above my ground sphere with a mass of 1:

Code: Select all

	for (unsigned int i = 0; i < 50; ++i)
	{
		int colsize = 2;
		int row = (int)((i*0.6*2)/(colsize*2*0.6));
		int row2 = row;
		int col = (i)%(colsize)-colsize/2;

		HomogenousMatrixD4 matrix(VectorD3(col*2*0.6 + (row2%2)*0.6, row*2*0.6+0.6 + 20.0, 0));
		RSG::ObjectRef sphere = RSG::Object::newObject<Sphere>();
		sphere->setField(RSG::Sphere::TRANSFORMATION_FIELD_ID, matrix);
		sphere->setField(RSG::Sphere::RADIUS_FIELD_ID, 0.6);
		createObject(sphere, 1.0);
	}
I have derived the class TestMotionState from btMotionState in order to get the transformation updates of the ridig bodies and map them onto the corresponding objects in my engine. The HomogenousMatrixD4 is a 4x4 matrix in row major format. Here is the class TestMotionState:

Code: Select all

class TestMotionState : public btMotionState
{
	friend class BulletTest;
	public:
		TestMotionState(RSG::ObjectRef obj, const HomogenousMatrixD4& matrix)
		: node(obj)
		{
			transform.setOrigin(btVector3(btScalar(matrix.get(0, 3)), btScalar(matrix.get(1, 3)), 
				btScalar(matrix.get(2, 3))));
			transform.setBasis(btMatrix3x3(btScalar(matrix.get(0, 0)), btScalar(matrix.get(0, 1)), btScalar(matrix.get(0, 2)), 
				btScalar(matrix.get(1, 0)), btScalar(matrix.get(1, 1)), btScalar(matrix.get(1, 2)), 
				btScalar(matrix.get(1, 0)), btScalar(matrix.get(1, 1)), btScalar(matrix.get(1, 2))));
		};

	/// synchronizes world transform from user to physics
	virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const 
	{
		centerOfMassWorldTrans = transform;
	}

	///synchronizes world transform from physics to user
	///Bullet only calls the update of worldtransform for active objects
	virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
	{
		transform = centerOfMassWorldTrans;
		float m[16];
		transform.getOpenGLMatrix(&m[0]);
		HomogenousMatrixD4 matrix;
		for (int i = 0; i < 16; ++i)
			matrix(i) = m[i];
		node->setField(RSG::Node::TRANSFORMATION_FIELD_ID, matrix);
	}

	private:
		RSG::SmartObjectRef<Node> node;
		btTransform transform;
		bool dirty;
};
And finally, before I call the update method of my scenegraph, I tell Bullet to do its stuff:

Code: Select all

	float ms = clock->getTimeMicroseconds();
	clock->reset();
	float minFPS = 1000000.f/60.f;
	if (ms > minFPS)
		ms = minFPS;

	dynamicsWorld->stepSimulation(1.0/420.f, 1);
The situation now is, that the dynamic sphere are correctly falling down, but when they hit the ground sphere nothing happens. I have step through the Bullet code and the collisions between the sphere are calculated, but then they get somehow rejected and no collision response is generated.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

Please also check out some other demos, for example CcdPhysicsDemo.

Code: Select all

  btRigidBody* body = new btRigidBody(0.0, motionState, shape, localInertia); 
You should pass the mass for the body, not 0.0

The basic demo is probably a bit confusing, because it doesn't register all various collision detection interactions/algorithms, only for sphere versus sphere.

Remove the 'true' argument to collision dispatcher, and don't register a special sphere-sphere.

So please the first few lines:

Code: Select all

 dispatcher = new btCollisionDispatcher(); 

   broadphase = new btSimpleBroadphase; 
   solver = new btSequentialImpulseConstraintSolver; 

   dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver); 
   dynamicsWorld->setGravity(btVector3(0.0, -10.0 , 0.0)); 

Hope this helps,
Erwin
Ohlenburg
Posts: 2
Joined: Mon Aug 06, 2007 1:16 pm

Post by Ohlenburg »

Hi Erwin,
thanks for the quick reply, but that did not help. By the way, after the stepSimulation call,

gNumManifold = 0, gOverlappingPais > 0, gTotalContactPoints = 0

throughout the simulation.
You should pass the mass for the body, not 0.0
Sorry, this happened while pasting the code together, I already passed the mass to the ridig body.
Please also check out some other demos, for example CcdPhysicsDemo.
Yes, I also took a look at the CcdPhysicsDemo, but I don't find that demo less confusing.

Just to clarify things:

Are these the things you have to do at least for a physics simulation? Or is there something else?

In order for the btDiscreteDynamicsWorld to perform collision detection and physics simulation, you need a CollisionDispatcher, a Broadphase and a ConstraintSolver and you have to set the gravity.

For each ridig body you have to set the shape, e.g. btSphereShape, the mass, the localInertia, the motion state, and the world transform. Then add it to the DynamicsWorld and activate it.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Post by Erwin Coumans »

Please compare your setup with available Bullet demos. And read the user manual.

If the Bullet demos don't work, please let us know.

Thanks,
Erwin