How to change gravity for all bodies mid-simulation[Solved]

bwelch
Posts: 48
Joined: Thu Dec 12, 2013 4:04 pm

How to change gravity for all bodies mid-simulation[Solved]

Post by bwelch »

Hello. This is my first post on this forum, and only my second week working with Bullet, so I hope you'll forgive any forum faux pas or questions of ignorance. :)

I am working on learning Bullet, and made a little bowling simulation to test placing rigid bodies, applying forces, and detecting collision. Of course, there's only so much boring bowling one can do when they are in absolute control of physics, so I've added some portals and boost pads and a gravity switch to my bowling example to spice things up.

I'm having a problem with my gravity switch, though. When the ball rolls over the switch, I can detect the collision, change the color of the switch, and toggle gravity, but it seems that only the ball is affected by the change in gravity. I'd like everything in the simulation to respond to the change, including the pins.

Here's the snippet of my code:

Code: Select all

bool btCallback(btManifoldPoint& cp,const btCollisionObjectWrapper* obj1,int id1,int index1,const btCollisionObjectWrapper* obj2,int id2,int index2)
{

	if(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->btid == 1){	//if obj1 is a booster, speed up obj2
		btVector3 boostdir;
		boostdir.setX(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getX());
		boostdir.setY(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getY());
		boostdir.setZ(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getZ());
		((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(boostdir.x()*10,boostdir.y()*10,boostdir.z()*10));
		//((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(100,0,0));
		WriteLine(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->getCenterOfMassTransform().getOrigin().getX());
		//WriteLine("BOOST!");
	}

	else if(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->btid == 1){	//if obj2 is a booster, speed up obj1
		btVector3 boostdir;
		boostdir.setX(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getX());
		boostdir.setY(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getY());
		boostdir.setZ(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->getLinearVelocity().getZ());
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->applyForce(btVector3(100,0,0),boostdir);
		//((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(100,0,0));
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(boostdir.x()*10,boostdir.y()*10,boostdir.z()*10));
		//WriteLine("BOOST!");
	}

	else if(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->btid == 2){	//if obj 1 is a portal, tranlate obj2
		double radius = ((bulletObject*)obj2->getCollisionObject()->getUserPointer())->model->MaxRadius();	//happens to work because it's a sphere
		((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->translate(btVector3(-230+(2*radius),-15,0));	//translate in Bullet coordinates
		WriteLine("FWOOSH! ", radius);
	}

	else if(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->btid == 2){	//if obj 2 is a portal, tranlate obj1
		double radius = ((bulletObject*)obj1->getCollisionObject()->getUserPointer())->model->MaxRadius();
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->translate(btVector3(-230+(2*radius),-15,0));
		WriteLine("FWOOSH! ", radius);
	}

	else if(((bulletObject*)obj1->getCollisionObject()->getUserPointer())->btid == 3){	//if obj 1 is a gravity switch, toggle gravity
		GravityVector = GravityVector*-1;
		world->setGravity(GravityVector);
		WriteLine("FLOOP! ", Now());
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->btid = 4;		//deactivate gravity switch
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->model->ChangeColor(black);
	}

	else if(((bulletObject*)obj2->getCollisionObject()->getUserPointer())->btid == 3){	//if obj 2 is a gravity switch, toggle gravity
		GravityVector = GravityVector*-1;
		world->setGravity(GravityVector);
		WriteLine("FLOOP! ", Now());
		((bulletObject*)obj2->getCollisionObject()->getUserPointer())->btid = 4;		//deactivate gravity switch
		((bulletObject*)obj2->getCollisionObject()->getUserPointer())->model->ChangeColor(black);
	}

	else if(obj1->getCollisionObject()->isStaticObject() || obj2->getCollisionObject()->isStaticObject()) return false;	//don't do anything for collisions with normal static bodies

	else {
		//WriteLine("Collision!");
		((bulletObject*)obj1->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(0,20,0));	//apply a vertical force on any colliding objects for now
		((bulletObject*)obj2->getCollisionObject()->getUserPointer())->body->applyCentralForce(btVector3(0,20,0));	//apply a vertical force on any colliding objects for now
	}

	return false;
}
I assumed that changing the gravity for the world would affect everything, but it doesn't appear to. What am I doing wrong?

Thanks,
BW
Last edited by bwelch on Mon Dec 16, 2013 2:47 pm, edited 1 time in total.
papaonn
Posts: 41
Joined: Wed Nov 20, 2013 4:14 pm

Re: How to change gravity for all bodies mid-simulation

Post by papaonn »

Hi just few guess :

the bowling is affected by the gravity because the bowling objet is still in "activate" state.

bullet will deactivate the state when it is no longer moving / require no additional collision check (perhaps).

so it is important to activate all other objects (including pins) if they are in deactivate state.

btCollisionShape::activate() (if no wrong)

OR

btRigidBody::activate() (this works because i worked more on rigid body)
bwelch
Posts: 48
Joined: Thu Dec 12, 2013 4:04 pm

Re: How to change gravity for all bodies mid-simulation

Post by bwelch »

papaonn wrote:Hi just few guess :

the bowling is affected by the gravity because the bowling objet is still in "activate" state.

btCollisionShape::activate() (if no wrong)
Yep, that seemed to do it. I added this into my rendering function so that any dynamic body is activated:

Code: Select all

bodies[i]->body->activate();	//force activation for the pins
And it works like a charm. Thanks for your help! It would have taken me forever to try that.
papaonn
Posts: 41
Joined: Wed Nov 20, 2013 4:14 pm

Re: How to change gravity for all bodies mid-simulation[Solv

Post by papaonn »

no worries ;)
have fun =)