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.