Most 3D applications use a scenegraph that stores scene node coordinates and we need a convenient way to update these coordinates from the physical simulation. In this case the simulation contains a dynamic object which moves ‘on its own’, being subject to gravity, collisions and other forces.

Often we want to animate objects ourselves, but we still want other objects to bounce off such objects, so we create a kind of alias or reference to the object we’re animating. Such an alias or reference is made into a kinematic object. A kinematic object still has physical properties (e.g. friction) that help determine how dynamic objects interact with it.

This article is a work in progress. Please refer to the motion state tutorial on the Bullet wiki. In theory motion states and kinematic bodies are ‘pretty simple’. I often find it easier to use dynamic bodies out of the box and rely on the default motion state.

The motion state

All bodies in the simulation are setup with a motion state.

The motion state allows sharing a node’s transform between the physics engine and the renderer. btMotionState is a small interface that specifies a getter/setter pair. The bullet API calls the getter to retrieve the shared transform and calls the setter to assign it.

Kinematic objects aren’t animated by the simulation, ‘we do it ourselves’. How do we let the simulation know that these objects have moved?

  1. Create a rigid body that will ‘stand for’ the kinematic object. This will be a kind of ‘alias’ or ‘reference’ to the object we’re animating, so we need to disable dynamics for this object (so it won’t be influenced by gravity or other objects).
  2. implement getWorldTransform() so that an up to date transform is returned whenever the simulation calls that function.
  3. Implement setWorldTransform() so that you (or the engine, if interpolating) can set the transform.
  4. Make the object ‘kinematic’ (see below)

Configuration:

There are two steps to ‘make an object kinematic’.

body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);

This flag tells the engine that the object is kinematic – so it shouldn’t move under the influence of gravity or because of colliding with other objects.

body->setActivationState(DISABLE_DEACTIVATION);

This prevents the object from ‘falling asleep’. Normally objects that haven’t moved in a while aren’t processed and keep sleeping until something bumps into them, or something that they’re in contact with wakes them up. Since kinematic objects aren’t affected by forces, we need to prevent them from falling asleep.

Back to dynamic state (UNTESTED)

body->setCollisionFlags( body->getCollisionFlags() & ~(btCollisionObject::CF_KINEMATIC_OBJECT));

body->activate(true); // or try… body->forceActivationState(ACTIVE_FLAG)

Tips and Caveats

  • Avoid relying on how many times or when the motion state’s get/set methods are accessed. Even if your object is not kinematic, the motion state’s getter may be called after the initial simulation step (TESTED).
  • If you ‘teleport’ a dynamic object, set the object’s transform by calling body->getWorldTransform().setOrigin(); even if you have removed the body from the simulation, after adding this object again the transform underlying your motion state may be overridden by a call to setWorldTransform before getWorldTransform is called by the engine.
  • In my experience it would appear that kinematic objects are somewhat less reliable than dynamic objects. I often seen tunneling effects that disappear if I use a dynamic object instead. Once again testing in a sandbox can be very helpful in such cases.