problems setting up compound objects

Singular
Posts: 13
Joined: Tue Sep 13, 2011 2:20 pm
Location: ru

problems setting up compound objects

Post by Singular »

hey guys, i'm new here and new to BP, sorry in advance for probably asking for a lot of RTFM info, but i couldn't find any consistent documentation(wiki and standart pdf feels more like random fact compilation, they're not sequential and informative enough for me), so i tried to figure out stuff looking on demos source and a bit on wiki.

so desired result is: have some abstract object(like btCompoundObject), attach some primitives(preferably positioned by offset from compound object) to it, simulate physics, get resulting object transofrmation, not child geometry(unacceptable, useless in most cases), but whole object transformation, custom render.

how i try to do stuff:
init:

Code: Select all

//Bullet World
	collisionConfiguration = new btDefaultCollisionConfiguration();
	dispatcher = new btCollisionDispatcher(collisionConfiguration);
	overlappingPairCache = new btDbvtBroadphase();
	solver = new btSequentialImpulseConstraintSolver;
	dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
	dynamicsWorld->setGravity(btVector3(0, Gravity, 0));

	for(unsigned int f = 0; f < 1000; f++)
	{
		if(!physObjects[f].Enabled)
			continue;

		physObjects[f].compoundShape = new btCompoundShape();

		for(unsigned int d = 0; d < 16; d++)
		{
			if(physObjects[f].SubGeom[d].Enabled)
			{
				//Init Shape
				btCollisionShape* tShape;
				if(physObjects[f].SubGeom[d]._Type == 0)//box
					tShape = new btBoxShape(btVector3(physObjects[f].SubGeom[d].Size.x, physObjects[f].SubGeom[d].Size.y, physObjects[f].SubGeom[d].Size.z));
				else									//sphere
					tShape = new btSphereShape(physObjects[f].SubGeom[d].Size.x);

				if(!physObjects[f].Static)
					tShape->calculateLocalInertia(physObjects[f].Mass, btVector3(0,0,0));

                                             //Child geometry offset
				btTransform tTransform;
				tTransform.setIdentity();
				tTransform.setOrigin(btVector3(physObjects[f].SubGeom[d].Pos.x, physObjects[f].SubGeom[d].Pos.y, physObjects[f].SubGeom[d].Pos.z));

				if(physObjects[f].SubGeom[d]._Type == 0)
					tTransform.setRotation(physObjects[f].SubGeom[d].Rot);


				physObjects[f].compoundShape->addChildShape(tTransform, tShape);
			}
		}

		btTransform gTransform;

                      //Whole object transformation
		gTransform.setIdentity();
		gTransform.setOrigin(btVector3(physObjects[f].Pos.x, physObjects[f].Pos.y, physObjects[f].Pos.z));
		gTransform.setRotation(physObjects[f].Rot);

		btDefaultMotionState* myMotionState = new btDefaultMotionState(gTransform);
		btRigidBody::btRigidBodyConstructionInfo rbInfo(physObjects[f].Mass, myMotionState, physObjects[f].compoundShape, btVector3(0,0,0));
		physObjects[f].body = new btRigidBody(rbInfo);

                      //kinematic
		if(physObjects[f].Static)
		{
			physObjects[f].body->setCollisionFlags(physObjects[f].body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
			physObjects[f].body->setActivationState(DISABLE_DEACTIVATION);
		}

		//add the body to the dynamics world
		dynamicsWorld->addRigidBody(physObjects[f].body);
	}
 
for running simulation i use just

Code: Select all

dynamicsWorld->stepSimulation(1.f/60.f, 10);
(i'm not quite sure if i need custom simulation pipeline for my goal).

and render(removed unnecessary stuff):

Code: Select all

//in physObjects
      body->getMotionState()->getWorldTransform(bTransform);
		bTransform.getOpenGLMatrix(R);
		glMultMatrixf(R);

		for(unsigned int f = 0; f < 16; f++)
		{
			if(SubGeom[f].Enabled)
			{
				if(SubGeom[f]._Type == 0)
				{
					glPushMatrix();

					//Child shape transform
					glTranslatef(SubGeom[f].Pos.x, SubGeom[f].Pos.y, SubGeom[f].Pos.z);
					glRotatef(SubGeom[f].Rot.x, 1, 0, 0);
					glRotatef(SubGeom[f].Rot.y, 0, 1, 0);
					glRotatef(SubGeom[f].Rot.z, 0, 0, 1);
					glScalef(SubGeom[f].Size.x, SubGeom[f].Size.y, SubGeom[f].Size.z);

					//Draw Cube
					glSolidCube(1.0);
					glPopMatrix();
				}
				else
				{
					glPushMatrix();

					//Child shape transform
					glTranslatef(SubGeom[f].Pos.x, SubGeom[f].Pos.y, SubGeom[f].Pos.z);

					//Draw Sphere
					gluSphere(gluq, SubGeom[f].Size.x, 32, 32);
					glPopMatrix();
				}
			}
		}
Result: visual child geometry offset: ok. visual initial position: ok. reacts on gravity. something like collision happens earlier than it visually should(wrong internal offset/scale?), so objects collide on distance and doesnt seem to react much(just move slower\stop, but not bounce\rotate). later it looks like objects very slowly pass through kinematic box(imitating ground plane) and then fall down to infinity.

So i would be very glad if you don't mind spending your time on explaining what am i doing wrong and how it meant to work or point out actually acceptable documentation.
Last edited by Singular on Wed Sep 14, 2011 7:09 am, edited 3 times in total.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: problems setting up compound objects

Post by Mako_energy02 »

That is a lot of foreign code to take in at once, so I don't understand all of it...but there are a couple errors I see and I'll point out more if I spot them.

1) You aren't properly initializing your object's Local Inertia.

Code: Select all

if(!physObjects[f].Static)
   tShape->calculateLocalInertia(physObjects[f].Mass, btVector3(0,0,0));
This is incorrect. You have to make the btVector3 representing the local inertia prior, and pass it in...keeping it around. This is because local inertia is not a property of the shape, but of the object itself. So when the shape calculates it, it doesn't store it. Instead it changes the btVector3 you pass in, and since it's non-cost reference when the function completes you have a valid local inertia to pass into your body.

Code: Select all

btRigidBody::btRigidBodyConstructionInfo rbInfo(physObjects[f].Mass, myMotionState, physObjects[f].compoundShape, btVector3(0,0,0));
The last arguement in the rigid body construction info constructor is where it should end up going. Not having a valid local inertia (such as having it be (0,0,0)) will cause your objects to be unable to rotate and not realistically react to collisions.

2) I could be wrong, but I think your use of a kinematic body is wrong for your use-case. I haven't dabbled in kinematic objects just yet, I've only done a bunch of scattered reading while looking at and fixing other things in my simulations. But as I currently understand it, kinematic bodies ignore normal collision response, and expect you to code something in to provide that. This includes contact response in the form of having an object rest on terrain. Why in your case it's passing through slowly, I don't know. But a regular static body seems more appropriate.

Code: Select all

physObjects[f].body->setCollisionFlags(physObjects[f].body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
Try replacing the kinematic flag there with a static flag:

Code: Select all

physObjects[f].body->setCollisionFlags(physObjects[f].body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
Singular
Posts: 13
Joined: Tue Sep 13, 2011 2:20 pm
Location: ru

Re: problems setting up compound objects

Post by Singular »

thanks for your reply.
ok, i think i fixed those mistakes(i really confused inertia vector with something you just pass in as body parameter), if i've got it right, i should also remove calculateLocalInertia for shapes and only call it for compound object after adding all child shapes. so i did it like that, changed static body flag and...surprisingly no real difference. except objects started to rotate after passing through static ground but before that they still collide on distance and don't react much.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: problems setting up compound objects

Post by Mako_energy02 »

Yes, you should call it on the compound shape and not each child shape. My bad there.

There may be something with the terrain itself going wrong rather then the objects. I'm not seeing the terrain initialization code in your provided samples, can you share that?
Singular
Posts: 13
Joined: Tue Sep 13, 2011 2:20 pm
Location: ru

Re: problems setting up compound objects

Post by Singular »

umm, in my case "terrain" is just a regular object but with "static"(and\or kinematic) flag. so in my test i just create big static box and drop some non-static boxes\spheres on it. so if something wrong with "ground" it's wrong with all objects(and it visually looks like that), because they init same way as described in 1st post, but with mentioned fixes.

so after making inertia calculation for compound object instead of shapes objects started rotate, but still, overall behavior looks totally wrong. they tend to pass through each other, collide at distance, be unstable and move at weird angles(at least in my visual implementation, i don't know how it "looks" for bullet). and i have hard time visually determine whats wrong, because everything looks so.
Singular
Posts: 13
Joined: Tue Sep 13, 2011 2:20 pm
Location: ru

Re: problems setting up compound objects

Post by Singular »

ok, answer is very stupid. i should've multiply box sides by 0.5 then passing them to Bullet...that's it. there are some problems left but they look more like material tuning stuff(a bit of penetration between "ground" and objects under the pressure of gravity, and still quite questionable behavior in some cases).