Multiple instances of btDefaultMotionState, all ignored, but one

481 views Asked by At

To summarize the problem(s):

I have two bodies in my world so far, one being the ground, the other one being a falling box called "fallingStar".

1) I do not understand why my bullet world is not aligned with my drawn world unless I set an offset of btVector3(2,2,2) to the (btDefault)MotionState. There is no fancy magic going on anywhere in the code that would explain the offset. Or at least I could not find any reason, not in the shaders, not anywhere.

2) I expected to be able to use multiple instances of btDefaultMotionState, to be precise, I wanted to use one instance for the falling entity and place it somewhere above the ground and then create another instance for the ground that should simply be aligned with my graphics-ground, ever unmoving.

What I am experiencing in regards to 2) is that for whatever reason the btDefaultMotionState instance for the falling entity is always also influencing the one for the ground, without any reference.

Now to the code:

Creation of the fallingBox:

btCollisionShape *fallingBoxShape = new btBoxShape(btVector3(1,1,1));
btScalar fallingBoxMass = 1;
btVector3 fallingBoxInertia(0,0,0);
fallingBoxShape->calculateLocalInertia(fallingBoxMass, fallingBoxInertia);

// TODO this state somehow defines where exactly _ALL_ of the physicsWorld is...
btDefaultMotionState *fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(2,2,2)));
//btDefaultMotionState *fallMotionState = new btDefaultMotionState();
btRigidBody::btRigidBodyConstructionInfo fallingBoxBodyCI(fallingBoxMass, fallMotionState, fallingBoxShape, fallingBoxInertia);
/*btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));*/
this->fallingBoxBody = new btRigidBody(fallingBoxBodyCI);
/*fallMotionState->setWorldTransform(initialTransform);
this->fallingBoxBody->setWorldTransform(initialTransform);*/
this->physicsWorld->addBody(*fallingBoxBody);

Now the interesting parts to me are the necessary offset of btVector3(2,2,2) to align it with my drawn world and this:

btTransform initialTransform;
initialTransform.setOrigin(btVector3(0,5,0));
this->fallingStarBody = new btRigidBody(fallingStarBodyCI);
fallMotionState->setWorldTransform(initialTransform);

If I reenable this part of the code ALL the bodies again show an offset, but NOT just 5 up, which I could somehow comprehend if for whatever reason the worldTransform would effect every entity, but about 2,2,2 off... which I cannot grasp at all.

I guess that this line is useless:

fallMotionState->setWorldTransform(initialTransform); as it does not change anything whether it's there or not.

Now to the code of the ground creation:

btCompoundShape *shape = new btCompoundShape();

... just some logic, nothing to do with bullet

btTransform transform;
transform.setIdentity();

transform.setOrigin(btVector3(x + (this->x * Ground::width),
                          y + (this->y * Ground::height),
                          z + (this->z * Ground::depth)));

btBoxShape *boxShape = new btBoxShape(btVector3(1,0,1)); // flat surface, no box

shape->addChildShape(transform, boxShape);

(this portion just creates a compoundshape for each surface tile :)

btRigidBody::btRigidBodyConstructionInfo info(0, nullptr, shape);
return new btRigidBody(info); 

Here I purposely set the motionstate to nullptr, but this doesn't change anything.

Now I really am curious... I thought maybe the implementation of btDefaultMotionState is a singleton, but it doesn't look so, so... why the hell is setting the motionState of one body affecting the whole world?

offset without btVector3(2,2,2) for btDefaultMotionState

offset with btVector3(2,2,2) for btDefaultMotionState

The position of my box and it's body, also an offset

3

There are 3 answers

0
AudioBubble On

What you are describing is not normal bullet behavior. Your understanding of the library is correct.

What you are most likely dealing with is either a buffer overrun or a dangling pointer. The code you have posted does not have an obvious one of either, so it would be coming from somewhere else in your codebase. You might be able to track that down using a well-placed memory breakpoint.

You "might" be dealing with a header/binary version inconsistency issue, but that's less likely as you would probably be seeing other major issues.

5
javaLover On

Bullet is a good library but only few dedicate time to write good documentation.

To set position of a btRigidBody, try this :-

btTransform transform = body -> getCenterOfMassTransform();
transform.setOrigin(aNewPosition); //<- set orientation / position that you like
body -> setCenterOfMassTransform(transform);  

If your code is wrong only at the set transformation part (that is what I guess from skimming your code), it should be solved.

Note that this snippet works only for dynamic body, not static body.

About CompoundBody:-

If it is a compound body, e.g. shape B contains shape C.
Setting transformation of B would work (set body of B), but not work for C.
(because C is just a shape, transformation support only body.)

If I want to change relative transformation of C to B, I would create a whole new compound shape and a new rigid body. Don't forget to remove old body & shape.

That is a library limitation.

P.S.

I can't answer some of your doubt/questions, these information are what I gathered after stalking in Bullet forum for a while, and tested by myself.

(I am also coding game + game library from scratch, using Bullet and other open sources.)

Edit: (about the new problem)

it just slowly falls down (along with the ground itself, which should not move as I gave it a mass of 0)

I would try to solve it in this order.

Idea A

  • Set to the compound mass = 0 instead, because setting a child shape's mass has no meaning.

Idea B

  • First check -> getCenterOfMassTransform() every time-step , is it really falling?
  • If it is actually falling, to be sure, try dynamicsWorld->setGravity(btVector3(0,0,0));.
  • If still not work, try with very simple world (1 simple object, no compound) and see.

Idea C (now I start to be desperate)

  • Ensure your camera position is constant.
  • If the problem is still alive, I think you now can create a simple test-case and post it in Bullet forum without too much effort.
  • Lower amounts of lines of code = better feedback
0
LastBlow On

Just had the exact same type of behavior with the DebugDrawer suspended on top of the world. Solved it by passing to Bullet Physics the projectionview matrix alone, without the model matrix that he has and multiplies with already:

glUseProgram(shaderID);

m_MVP = m_camera->getProjectionViewMatrix();
glUniformMatrix4fv(shaderIDMVP, 1, GL_FALSE, &m_MVP[0][0]);
if (m_dynamicWorld) m_dynamicWorld->debugDrawWorld();