setWorldTransform vs setCenterOfMassTransform in Ammo.js

In Ammo.js (the Emscripten port of the Bullet Physics engine), positioning and moving rigid bodies requires a clear understanding of how the engine tracks spatial coordinates. While both setWorldTransform and setCenterOfMassTransform are used to define an object’s position and rotation in 3D space, they target different components of a physics body. Choosing the wrong method can lead to unexpected physics behavior, visual jitter, or broken collision detection.

The Core Difference

The fundamental difference lies in which coordinate system you are manipulating and how the physics solver processes the change:


Under the Hood: How Bullet Physics Sees It

To understand why this distinction matters, it helps to look at the relationship between rigid bodies, collision shapes, and the center of mass.

1. The Role of the Center of Mass

In Ammo.js, all dynamic physics calculations (such as torque, angular velocity, and gravity) are calculated relative to the rigid body’s center of mass.

If you have a symmetrical shape (like a box or a sphere centered at [0, 0, 0]), the local origin of the shape and the center of mass are identical. However, for compound shapes or asymmetrical meshes, the center of mass may be offset from the shape’s local origin.

2. State Interpolation and Jitter

Ammo.js uses interpolation to smooth out the visual representation of objects between physics simulation ticks.

When you call setCenterOfMassTransform, Ammo.js updates both the current transform and the interpolation transform. When you call setWorldTransform on an active dynamic rigid body, the interpolation transform is left unchanged. This mismatch often causes the object to “jitter” or snap back to its previous position during the next physics frame.


When to Use Each Method

To ensure stable physics and smooth rendering, follow these usage guidelines:

Use setCenterOfMassTransform when:

Note: After calling setCenterOfMassTransform on an active body, you should also clear its forces and linear/angular velocities using clearForces(), setLinearVelocity(), and setAngularVelocity() to prevent leftover momentum from carrying over to the new position.

Use setWorldTransform when: