Read Stress and Tension in Ammo.js Soft Bodies
This article explains how to measure and retrieve localized tension and stress values across an Ammo.js soft body. By analyzing the deformation of the underlying spring-like links that connect the soft body nodes, you can calculate real-time structural strain for visualization, gameplay mechanics, or destruction systems.
In Ammo.js (the Emscripten port of the Bullet Physics engine), soft
bodies are represented by btSoftBody, which consists of
nodes (vertices) and links (edges/springs connecting the nodes). Ammo.js
does not provide a direct, pre-calculated “stress” variable for each
vertex. Instead, localized tension must be calculated manually by
measuring the deformation of individual links relative to their original
rest length.
To read these tension values, you must iterate through the soft body’s links array. Each link connects two nodes and stores its original structural “rest length.” By comparing the current distance between the two connected nodes against the rest length, you can determine the strain (tension or compression) at that specific location.
Here is the step-by-step process and JavaScript code to calculate these values using the Ammo.js API:
// Assuming 'softBody' is an instance of Ammo.btSoftBody
const links = softBody.m_links;
const linkCount = links.size();
for (let i = 0; i < linkCount; i++) {
const link = links.at(i);
// Retrieve the two nodes connected by this link
const nodeA = link.get_m_n(0);
const nodeB = link.get_m_n(1);
// Get current 3D positions of both nodes
const posA = nodeA.m_x;
const posB = nodeB.m_x;
// Calculate the current distance between the nodes
const dx = posA.x() - posB.x();
const dy = posA.y() - posB.y();
const dz = posA.z() - posB.z();
const currentLength = Math.sqrt(dx * dx + dy * dy + dz * dz);
// Retrieve the rest length of the link
const restLength = link.m_rl;
// Calculate tension (strain).
// Positive values indicate tension (stretching), negative indicates compression.
const tension = (currentLength - restLength) / restLength;
// 'tension' can now be mapped to vertex colors or used for structural damage logic
}If you need to visualize this stress across a 3D mesh (such as a Three.js buffer geometry), you should map the calculated link tension back to the corresponding vertices. Because multiple links share the same node, you can average the tension values of all connected links at each node. This average value can then be written directly to a custom shader vertex attribute, allowing you to dynamically color the soft body—shifting from blue (low stress) to red (high stress) in real time.