Ammo Physics `setWorldTransform()` for Kinematic and Dynamic bodies

I’m able to move physics bodies using setWorldTransform(). However, setWorldTransform() appears to behave differently for Kinematic and Dynamic bodies:

const worldTrans = new Ammo.btTransform();
worldTrans.setIdentity();
worldTrans.setOrigin(position);

// Works for Dynamic, but not for Kinematic bodies
btRigidBody.setWorldTransform(worldTrans);

// Works for Kinematic, but not for Dynamic bodies
btRigidBody.getMotionState().setWorldTransform(worldTrans);

For some reason, getMotionState() is required for Kinematic bodies and must be omitted for Dynamic bodies. I’m not blocked, as the code above can successfully move both types of bodies. I’m just curious why the methods to move Kinematic and Dynamic bodies are different

Thank you for your help :slight_smile:

I found an interesting source by Erwin Coumans, creator of Bullet Physics:

Kinematic btRigidBody example

...

#ifdef USE_MOTIONSTATE
m_groundBody->getMotionState()->setWorldTransform(predictedTrans);
#else
m_groundBody->setWorldTransform(predictedTrans);
#endif

...

Kinematic object are entities controlled/animated outside the physics engine but provide collisions and response to dynamics objects. Like an elevator platform for example.
Dynamics objects are fully controlled by the physics engine.
So, moving them outside the physics engine is a bit different.

1 Like

Found an interesting article: The Dark Art of tweaking Bullet Physics - Merc Tactics - GameDev.net

To move a kinematic object you need to directly modify both the world transform and the motionState (setting the world transform without modifying the motionState will cause interactions between kinematic and dynamic objects to behave very strangely)

btTransform& t = m_pRigidBody->getWorldTransform();
t.setOrigin(btVector3(m_x+m_xOffset, m_y+m_yOffset, m_z));
m_pRigidBody->getMotionState()->setWorldTransform(t);

Also the position change only happens after btDynamicsWorld::stepSimulation is called.

If you need the object to move without btDynamicsWorld::stepSimulation being called you can call pWorld->updateSingleAabb(m_pRigidBody);