How Ammo.js clearForces Works Internally

This article explains the internal mechanics of calling clearForces() on the main physics world in ammo.js, the Emscripten-compiled JavaScript port of the Bullet Physics SDK. We will explore how this method propagates from the JavaScript wrapper down to the C++ WebAssembly layer, how it resets accumulated linear forces and angular torques on individual rigid bodies, and its significance within the physics simulation loop.

The WebAssembly and Emscripten Wrapper Layer

When you execute clearForces() on an instance of btDiscreteDynamicsWorld (the class representing the main physics world in Ammo.js), the call first passes through the Emscripten binding layer. Because Ammo.js is a direct port of the C++ Bullet Physics library, this JavaScript invocation immediately triggers the compiled C++ method btDiscreteDynamicsWorld::clearForces() inside the WebAssembly module.

Iteration Through Non-Static Rigid Bodies

Once the execution reaches the C++ layer of Bullet Physics, the physics world executes a loop over its internal collection of active rigid bodies. Specifically, the world targets its list of non-static (dynamic and kinematic) rigid bodies. Static bodies are excluded from this process because they do not react to forces.

For every active rigid body (btRigidBody) registered in the simulation world, the engine calls the individual body’s local clearForces() method.

Resetting Accumulated Vectors

At the individual rigid body level, the internal C++ implementation of btRigidBody::clearForces() is highly efficient. A rigid body in Bullet tracks cumulative external influences using two main vector variables: * m_totalForce: A btVector3 storing the sum of all linear forces applied during the current frame (via methods like applyForce). * m_totalTorque: A btVector3 storing the sum of all rotational forces applied during the current frame (via methods like applyTorque).

When clearForces() is called on a body, both m_totalForce and m_totalTorque are reset to zero vectors (0.0, 0.0, 0.0). This wipes the slate clean, discarding any forces that were applied in the interval since the last simulation step or clearing operation.

Impact on the Physics Pipeline

In a standard simulation step (stepSimulation), Bullet automatically calls clearForces() internally at the very end of the step. This is because forces in Bullet are instantaneous accumulators; they do not automatically persist from frame to frame.

If you manually call clearForces() on the main world before calling stepSimulation(), you override and erase any user-applied forces (such as those added via applyForce or applyTorque earlier in your application frame) before the physics engine has a chance to integrate them into the bodies’ velocities. Consequently, those applied forces will have zero effect on the movement of the objects in the next physics tick.