Page 1 of 1

Getting the direction an object would move

Posted: Fri Feb 01, 2019 9:52 pm
by candybear
I'm a Bullet newbie so I hope this question makes sense. I have a bunch of cubes in a scene, and when they collide with scene geometry they move consistently with respect to how one would expect them to move. However, I also have rigid bodies that have angular and linear factors set to 0 so that they do not move according to rigid body simulation. Is there any way I could retrieve the direction the objects with 0 linear and angular factors would move (as if they had non zero linear / angular factors)? These objects are controlled by the user, and I don't always want them to move according to the physics simulation; I would simply want information as to how they would've moved if they were actually being moved by the physics simulation.
For example, say I had a cube with a 0 angular and linear factors and it moved into some other object, would there be any way for me to find out which direction the cube would naturally move as if it had non-zero angular and linear factors.

Thanks in advance!

Re: Getting the direction an object would move

Posted: Sat Feb 02, 2019 3:51 pm
by drleviathan
Here is method might work for you. It does have a theoretical side-effect on the "pushing" objects : they will lose momentum as if they really did move the "non-movable" objects. Also, it would require your non-movable objects to be "active" in the simulation, which will "activate" other objects that touch them, so it won't work well when the non-movable objects like the floor or walls: everything in the World would "wake up".

I would summarize it like so: "Make your non-movable objects DYNAMIC but effectively KINEMATIC using a CustomMotionState which measures their real velocities after collisions then slams their transforms and velocities back to their original values."

(1) Don't zero the linear and angular factors on your locked objects. Instead, give them a CustomMotionState that will move them back to their locked positions every substep.

(2) Derive CustomMotionState from btMotionState and implement its setWorldTransform() like so:

Code: Select all

void CustomMotionState::setWorldTransform(const btTransform& worldTrans) const {
    // harvest the velocities
    btVector3 linearVelocity = m_body->getLinearVelocity();
    btVector3 angularVelocity = m_body->getAngularVelocity();
    // actually use harvested velocities here, or save for later

   // move the body back to its "locked" transform
    if (m_body) {
        m_body->setLinearVelocity(btVector(0.0f, 0.0f, 0.0f));
        m_body->setAngularVelocity(btVector(0.0f, 0,0f, 0.0f));

        // maybe flag body for deactivation so that it settles down faster, dunno if this would be helpful or not
        m_body->setDeactivationTime(2.1f); // assuming default gDeactivationTime of 2.0 seconds
Of course I've implied some obvious details: you would need to also implement the other pure virtual method in the btMotionState interface and make your CustomMotionState keep the m_body back pointer and a few other data members.

Another other bit of advice: since your locked objects aren't actually locked, you might want to give them artificially large masses (larger than the masses of the pushers). This would make them less "responsive" to the "pushing" objects and would attenuate the measured velocity response, but it would also attenuate the amount of momentum lost by the pushers on collision and would reduce that artifact. In other words: if you just want to get an idea of the general direction of the locked objects' velocities but not their magnitudes, make the masses of your "locked" objects high.

You're new to Bullet so you might be wondering: "What is a MotionState?" I will offer this overview about how I think of it: the MotionState is a bridge object hook that Bullet provides to make it easy for the physics Body to interact with your GameObject and visa-versa. The interface contract is as follows:

For Body's that have a MotionState...

(A) Bullet will call MotionState::setWorldTransform() once per substrp on every active+DYNAMIC Body. This is where you would harvest the DYNAMIC Body's new transform so you can tell the GameObject about it.

(B) Bullet will call MotionState::getWorldTransform() in two instances:

(B1) When the Body is first added to the World AND it has a MotionState

(B2) Once every substep if the Body is active+KINEMATIC. This is an opportunity for you to harvest the (scripted) transform from your GameObject and apply it to the KINEMATIC Body.