How to Pin Soft Body Cloth in Ammo.js

This article provides a step-by-step guide on how to securely anchor or pin the corners of a soft body cloth to specific points in 3D space using the Ammo.js physics engine. You will learn how to identify the correct nodes of the cloth mesh and use two primary methods—setting node mass to zero for fixed global positioning, or using anchors to attach the cloth to rigid bodies—to ensure stable and realistic cloth simulation.


Understanding Cloth Nodes in Ammo.js

A soft body cloth in Ammo.js is composed of a collection of vertices, referred to as nodes. To pin a specific corner of the cloth, you must first identify the index of that node.

When you create a cloth patch using btSoftBodyHelpers.CreatePatch, the cloth is generated as a grid. If your cloth has a resolution of numColumns by numRows, the corner nodes are located at the following indices:


Method 1: Setting Node Mass to Zero (Fixed in Space)

If you want to pin a cloth corner to a static coordinate in the 3D world, the most efficient method is to set the mass of that specific node to zero. In Bullet/Ammo.js physics, an object or node with a mass of 0 becomes static and unaffected by gravity or external forces.

Step-by-Step Implementation

  1. Create the Soft Body: Generate your cloth patch and add it to your physics world.
  2. Access the Node: Use the soft body’s get_m_nodes() array to access the node configuration.
  3. Set Mass to Zero: Call the setMass method on the soft body for the specific node index.
// Assuming 'clothSoftBody' is your btSoftBody instance
// and 'numColumns' and 'numRows' define your grid resolution.

const topLeftIndex = 0;
const topRightIndex = numColumns - 1;

// Set mass of the top-left corner node to 0 (pinned)
clothSoftBody.setMass(topLeftIndex, 0);

// Set mass of the top-right corner node to 0 (pinned)
clothSoftBody.setMass(topRightIndex, 0);

This method locks the designated corners to their initial spawning coordinates. They will remain suspended in the air, allowing the rest of the cloth to dangle and react naturally to wind, gravity, and collisions.


Method 2: Anchoring to a Rigid Body (Dynamic Pinning)

If you need the cloth to be pinned to an object that moves (such as a flagpole, a character’s hand, or a moving platform), you must anchor the cloth node to a btRigidBody.

Ammo.js provides the appendAnchor method to link a soft body node to a rigid body.

Step-by-Step Implementation

  1. Create or Reference a Rigid Body: This can be a static anchor point or a dynamic moving object.
  2. Identify the Node Index: Determine which cloth node you want to attach.
  3. Append the Anchor: Call appendAnchor(nodeIndex, rigidBody, disableCollisions, influence) on your soft body.
// 1. Create a static anchor rigid body at your target coordinate
const colShape = new Ammo.btSphereShape(0.1); // Small invisible sphere
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(x, y, z)); // Pin position

const localInertia = new Ammo.btVector3(0, 0, 0);
const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, colShape, localInertia); // Mass = 0 (static)
const anchorBody = new Ammo.btRigidBody(rbInfo);

physicsWorld.addRigidBody(anchorBody);

// 2. Append the cloth corner node to the anchor rigid body
const nodeIndex = 0; // Top-left corner
const disableCollisionBetweenLinkedBodies = true;
const influence = 1.0; // Rigid attachment strength (0.0 to 1.0)

clothSoftBody.appendAnchor(
    nodeIndex, 
    anchorBody, 
    disableCollisionBetweenLinkedBodies, 
    influence
);

Best Practices for Stability