Today I’m covering simple methods used to move dynamic objects. I am also introducing servo-controllers.

To study the effect of forces on an object’s velocity and position, it is good to know how to step the simulation correctly. Before reading this tutorial, you may wish to have a look on the bullet wiki and read stepping the world.

Additionally, you may want to check the btRigid body class reference on the Bullet site. btRigidBody provides other methods that can be used to apply torques and forces.

Forces

You can apply forces using:

btRigidBody::applyCentralForce(btVector3 F)

If you call this method, a force equal to F*t will be applied at the next frame, where:

  • F is expressed in Newtons per second.
  • t is the duration of the next ‘physics frame’.

When using applyCentralForce, the total force applied depends on the duration of the next frame.

Example 1:

float duration = 0.5f; // frame duration (seconds)
float maxSubsteps = 5; // max number of substeps to update
float tick = 0.1f;  // max duration of a substep (seconds)

body->applyCentralForce(btVector3(1,0,0));
world->step(duration,maxSubsteps,tick); // total force applied: 0.5N

Example 2:

float duration = 0.2f;
float maxSubsteps = 5;
float tick = 0.1f;

body->applyCentralForce(btVector3(1,0,0));
world->step(duration,maxSubsteps,tick); // total force applied: 0.2N

Impulses

If you want to give a one-off ‘impulse’ irrespective of frame duration, you can use:

btRigidBody::applyCentralImpulse(btVector3 F)

In this case the total force applied at the next frame is F, irrespective of frame duration.

Continuous forces

If you want to apply continuous forces (e.g, traction generated by an engine), you should call applyCentralForce at every frame. This is because forces are reset after the next frame:

body->applyCentralForce(btVector3(1,0,0));
world->step(0.1f,10,0.02f); // applied 0.1 N

world->step(0.1f,10,0.02f); // applied 0.0 N

High-school memory: Just because forces are reset doesn’t mean the object will stop moving right away! If there is no air resistance or friction, the body will continue moving forever.

How do I control the object’s velocity?

When dealing with forces, you can adjust forces using a servo-controller (aka servo-mechanism or servo). A servo uses negative feedback to adjust it’s input in order to regulate it’s output.

Why can’t I just set the velocity directly?

If you want a dynamic object that collides, falls under the effect of gravity and rests on the ground automagically, setting velocity directly isn’t a good idea (you’ll end up canceling the effect of all these forces). Instead you want to set the target velocity and let a servo generate forces to adjust your object’s velocity.

OK, how do I write a servo? Is it hard?

A basic servo works like this:

  1. Assume a target velocity v0
  2. Read the current velocity v
  3. Evaluate the error: e = v – v0
  4. Evaluate a correction factor: c = – e = v0 – v
  5. Apply the correction factor multiplied by an arbitrary scale factor k:
    F = k . ( v0 – v )

Use btRigidBody:getLinearVelocity() to read a body’s current velocity.

The tricky part is getting the scale factor right. As a rule of the thumb if you try with a 1kg sphere, a factor between 10 and 50 works fine. A smart servo adjusts the scale factor automatically.

I will provide sample code for servos another time. We have enough on our hands learning Bullet.