How to Apply Force to Ammo.js Soft Body Vertex

This article explains how to apply a localized physical force to a specific vertex (node) of an Ammo.js soft body. You will learn how to identify the target vertex index, create the force vector using the Ammo.js API, apply the force directly to the node, and manage memory allocation to ensure smooth performance in your 3D physics simulation.

In Ammo.js (the Emscripten port of the Bullet Physics engine), soft bodies are composed of a collection of interconnected nodes (vertices). To apply a localized force to a single point on a soft body, you must target its specific node index using the addForce method of the btSoftBody class.

Step 1: Identify the Target Vertex Index

Before applying force, you need the index of the vertex you want to manipulate. This index corresponds to the vertex’s position in the geometry array used to generate the soft body.

If you are determining the vertex dynamically (for example, via a user click or collision), you can perform a raycast to find the intersection point, loop through the soft body’s nodes, and identify the node closest to the collision point.

Step 2: Create the Force Vector

Define the direction and magnitude of the localized force using a btVector3 object.

// Define a force vector (e.g., applying 15 units of force along the Y-axis)
const forceVector = new Ammo.btVector3(0, 15, 0);

Step 3: Apply the Force to the Soft Body Node

Use the addForce method on your soft body instance. This method takes two arguments: the btVector3 force vector and the integer index of the target vertex.

const vertexIndex = 42; // The specific index of the vertex

// Apply the localized force to the vertex
softBody.addForce(forceVector, vertexIndex);

This force will be processed during the next physics step simulation (physicsWorld.stepSimulation()). Because it is a force and not an impulse, you may need to apply it continuously over multiple animation frames if you want a sustained push rather than a momentary nudge.

Step 4: Clean Up Memory

Since Ammo.js is written in C++ and compiled to WebAssembly/JavaScript, objects created with the new keyword must be manually deallocated to prevent memory leaks.

// Destroy the vector once it has been applied to the physics engine
Ammo.destroy(forceVector);

Complete Code Example

Below is a complete implementation showing how to apply a one-time localized force to a specific vertex within your render or physics update loop:

function applyLocalizedForce(softBody, vertexIndex, forceX, forceY, forceZ) {
    // 1. Create the Ammo.js vector
    const force = new Ammo.btVector3(forceX, forceY, forceZ);
    
    // 2. Apply the force to the specified node index
    softBody.addForce(force, vertexIndex);
    
    // 3. Clean up the allocated vector memory
    Ammo.destroy(force);
}

// Example usage: Apply an upward and outward force to vertex 105
applyLocalizedForce(mySoftBody, 105, 5.0, 20.0, -2.0);