Performing Cloth Simulation with Self-Collision Detection in Newton

Newton implements cloth self-collision detection through sewing springs generated by BVH-accelerated proximity queries, using the Style3D solver to simulate realistic fabric dynamics with inter-penetration prevention.

Newton's physics engine provides a comprehensive cloth simulation framework built on the Style3D solver, enabling realistic fabric dynamics with optional self-collision detection. This article explains how to perform cloth simulation with self-collision detection in Newton by leveraging sewing springs, BVH acceleration structures, and GPU kernels to prevent inter-penetration while maintaining simulation stability.

Understanding Newton's Cloth Simulation Architecture

The Style3D Solver Foundation

Newton's cloth simulation is built on top of the Style3D solver, which extends the standard Newton pipeline with custom attributes for anisotropic stretch, bending, and self-collision handling. The solver consumes specialized geometry data computed during the mesh import stage and applies PBD (Position Based Dynamics) or XPBD integration depending on the configuration.

Core Cloth Geometry Helpers

The public API for cloth creation resides in newton/_src/solvers/style3d/cloth.py. This module provides two primary entry points:

  • add_cloth_mesh – Imports arbitrary triangle meshes with custom UV parameterization
  • add_cloth_grid – Generates procedural rectangular grids with optional boundary constraints

Both helpers automatically compute rest-state data including panel-space triangles, edge cotangents for bending, and anisotropic stiffness parameters required by the Style3D solver.

Creating Cloth Geometry

Arbitrary Mesh Import with add_cloth_mesh

The add_cloth_mesh function (lines 91‑129 in newton/_src/solvers/style3d/cloth.py) constructs cloth from arbitrary vertex and index buffers. It performs the following operations:

  1. Transforms vertices to world space using the provided position and rotation
  2. Computes per-triangle panel-space rest data via _compute_panel_triangles
  3. Adds particles, triangles, and edges to the ModelBuilder
  4. Attaches Style3D-specific attributes including style3d:tri_aniso_ke for anisotropic stretch and edge rest areas

The function accepts a density parameter derived from mass-per-particle calculations (lines 79‑82) to ensure physically consistent mass distribution across irregular meshes.

Procedural Grid Generation with add_cloth_grid

For regular rectangular cloth, add_cloth_grid (lines 389‑508) provides a higher-level interface. It generates vertex positions and panel UVs procedurally, then delegates to add_cloth_mesh for actual construction.

Boundary conditions are handled through boolean flags (fix_left, fix_right, fix_top, fix_bottom). When enabled, these pin selected vertices by clearing the ParticleFlags.ACTIVE flag and zeroing their mass, creating fixed constraints without additional constraint objects.

Implementing Self-Collision Detection

The Sewing Springs Approach

Newton handles self-collision through sewing springs—short distance constraints that connect vertices lying closer than a user-specified threshold. These springs act as soft repulsion forces that prevent inter-penetration before the narrow-phase collision step, avoiding expensive triangle-triangle queries.

The public entry point is sew_close_vertices (lines 674‑689 in newton/_src/solvers/style3d/cloth.py), which computes proximity pairs and adds springs to the ModelBuilder using default stiffness and damping parameters.

BVH Acceleration and GPU Kernels

The proximity query leverages a Bounding Volume Hierarchy (BVH) for acceleration. The implementation spans three components:

  1. create_mesh_sew_springs (lines 600‑671) – Constructs a BVH over all mesh edges using the Warp kernel compute_edge_aabbs, then queries each vertex's AABB to find candidate edges within sew_distance.

  2. compute_sew_v (Warp kernel) (lines 228‑311) – Parallelized GPU/CPU kernel that iterates over candidate edges for each vertex, evaluates Euclidean distances, and stores up to max_num_sew nearest neighbors.

  3. sew_close_vertices – Consumes the neighbor pairs and instantiates spring constraints in the simulation graph.

Enabling Self-Collisions in the Pipeline

The enable_self_collisions flag propagates through Newton's import utilities. In newton/_src/utils/import_usd.py (lines 67‑71) and newton/_src/utils/import_urdf.py (lines 81‑85), the schema attributes newton:selfCollisionEnabled and physxArticulation:enabledSelfCollisions are parsed and passed to the builder. When enabled, the mesh import pipeline automatically invokes the sewing spring generation.

Validation tests in newton/tests/test_cloth.py (lines 1091‑1105) verify that enabling self-collision prevents spurious contacts inside the cloth mesh, confirming the system's correctness.

Complete Simulation Workflow

The following example demonstrates the end-to-end pipeline: creating a grid cloth, enabling self-collision via sewing springs, registering Style3D attributes, and running the simulation at 240 Hz.

import newton
from newton.solvers import SolverStyle3D
from newton._src.solvers.style3d.cloth import add_cloth_grid, sew_close_vertices

# 1️⃣ Build the scene

builder = newton.ModelBuilder()
add_cloth_grid(
    builder,
    pos=[0, 0, 0],
    rot=[0, 0, 0, 1],          # identity quaternion

    vel=[0, 0, 0],
    dim_x=30,
    dim_y=30,
    cell_x=0.05,
    cell_y=0.05,
    mass=0.01,
    fix_top=True,
)

# 2️⃣ Enable self‑collision (sewing springs)

sew_close_vertices(builder, sew_distance=2e-3, sew_interior=False)

# 3️⃣ Register Style3D custom attributes and create the model

SolverStyle3D.register_custom_attributes()
model = builder.finalize()

# 4️⃣ Create a solver and run the simulation

solver = SolverStyle3D(model, device="cpu")
for step in range(200):
    solver.step(dt=1/240)   # 240 Hz integration

    # optional: visualize or log state here

Practical Code Examples

Example 1 – Simple Hanging Cloth with Self-Collision

This snippet creates a 20×20 grid pinned at the top edge with self-collision enabled via 1mm sewing springs:

import newton
from newton.solvers import SolverStyle3D
from newton._src.solvers.style3d.cloth import add_cloth_grid, sew_close_vertices

builder = newton.ModelBuilder()
add_cloth_grid(
    builder,
    pos=[0, 2, 0],
    rot=[0, 0, 0, 1],
    vel=[0, 0, 0],
    dim_x=20,
    dim_y=20,
    cell_x=0.1,
    cell_y=0.1,
    mass=0.02,
    fix_top=True,                 # pin top edge

)
sew_close_vertices(builder, sew_distance=1e-3)

SolverStyle3D.register_custom_attributes()
model = builder.finalize()

solver = SolverStyle3D(model, device="cpu")
for i in range(300):
    solver.step(dt=1/240)

Example 2 – Cloth Draped Over a Sphere (Mesh Import)

For arbitrary topology, use add_cloth_mesh with pre-computed vertices and indices:

import newton
from newton.solvers import SolverStyle3D
from newton._src.solvers.style3d.cloth import add_cloth_mesh, sew_close_vertices

# Load a pre‑computed sphere‑covered mesh (e.g., from an OBJ loader)

vertices, indices = load_obj("sphere_cloth.obj")   # user‑provided loader

builder = newton.ModelBuilder()
add_cloth_mesh(
    builder,
    pos=[0, 1, 0],
    rot=[0, 0, 0, 1],
    vel=[0, 0, 0],
    vertices=vertices,
    indices=indices,
    density=0.5,
    panel_verts=None,               # use XY as UVs

)
sew_close_vertices(builder, sew_distance=2e-3, sew_interior=True)

SolverStyle3D.register_custom_attributes()
model = builder.finalize()
solver = SolverStyle3D(model, device="cpu")
for _ in range(400):
    solver.step(dt=1/240)

Example 3 – Visualising Self-Collision Forces

Debug sewing spring forces using Newton's built-in viewer:

import newton
from newton.solvers import SolverStyle3D
from newton._src.solvers.style3d.cloth import add_cloth_grid, sew_close_vertices
from newton.viewer import Viewer   # simple OpenGL viewer

builder = newton.ModelBuilder()
add_cloth_grid(
    builder,
    pos=[0, 1.5, 0],
    rot=[0, 0, 0, 1],
    vel=[0, 0, 0],
    dim_x=30,
    dim_y=30,
    cell_x=0.08,
    cell_y=0.08,
    mass=0.015,
    fix_top=True,
)
sew_close_vertices(builder, sew_distance=1.5e-3)

SolverStyle3D.register_custom_attributes()
model = builder.finalize()
solver = SolverStyle3D(model, device="cpu")

viewer = Viewer(model)          # automatically creates a viewer

for _ in range(200):
    solver.step(dt=1/240)
    viewer.render()            # shows cloth with spring forces as red lines

Key Source Files and Implementation Details

File Purpose
newton/_src/solvers/style3d/cloth.py Core cloth helpers (add_cloth_mesh at lines 91‑129, add_cloth_grid at lines 389‑508) and self‑collision utilities (sew_close_vertices at lines 674‑689, create_mesh_sew_springs at lines 600‑671, compute_sew_v kernel at lines 228‑311).
newton/_src/sim/builder.py ModelBuilder API for adding particles, triangles, edges, and springs.
newton/_src/solvers/style3d/__init__.py Public API exports for the Style3D solver components.
newton/_src/utils/import_usd.py Parses newton:selfCollisionEnabled schema flag (lines 67‑71).
newton/_src/utils/import_urdf.py Handles physxArticulation:enabledSelfCollisions (lines 81‑85).
newton/tests/test_cloth.py Validation suite including test_cloth_collision (lines 1091‑1105) for self-collision correctness.
newton/solvers.py High-level SolverStyle3D registration and solver factory.

Summary

  • Newton's cloth simulation relies on the Style3D solver, which requires custom attributes like style3d:tri_aniso_ke for anisotropic stretch and bending cotangents.
  • Use add_cloth_mesh (lines 91‑129) for arbitrary topology or add_cloth_grid (lines 389‑508) for procedural rectangular cloth with pinned boundaries.
  • Self-collision detection is implemented via sewing springs generated by sew_close_vertices (lines 674‑689), which uses BVH acceleration (create_mesh_sew_springs, lines 600‑671) and the Warp kernel compute_sew_v (lines 228‑311) for GPU-parallel proximity queries.
  • Enable self-collision import via USD (newton:selfCollisionEnabled, lines 67‑71) or URDF (physxArticulation:enabledSelfCollisions, lines 81‑85) schemas, or explicitly call sew_close_vertices in Python.
  • Always call SolverStyle3D.register_custom_attributes() (lines 321‑324) before finalizing the model to ensure the solver recognizes Style3D-specific data.

Frequently Asked Questions

How does Newton's sewing spring method compare to traditional triangle-triangle collision detection?

Newton's sewing springs act as soft constraints that prevent vertices from approaching each other within a specified sew_distance, effectively providing continuous collision response without explicit triangle-triangle intersection tests. This approach, implemented in create_mesh_sew_springs (lines 600‑671), is computationally cheaper than full narrow-phase collision detection and resolves inter-penetrations before they occur, whereas traditional methods require expensive geometric intersection queries after penetration happens.

What is the performance impact of enabling self-collision on large cloth meshes?

The self-collision system uses BVH acceleration and Warp GPU kernels (compute_sew_v, lines 228‑311) to parallelize proximity queries across vertices. For a 30×30 grid (900 vertices), the overhead is negligible on modern GPUs, but memory usage scales with the number of sewing springs generated. The max_num_sew parameter limits the number of springs per vertex to control memory consumption, and the BVH construction in create_mesh_sew_springs (lines 600‑671) ensures O(log n) query complexity rather than O(n²) brute-force comparison.

Can self-collision be enabled when importing cloth from USD or URDF files?

Yes. Newton parses the newton:selfCollisionEnabled schema attribute in newton/_src/utils/import_usd.py (lines 67‑71) and the physxArticulation:enabledSelfCollisions attribute in newton/_src/utils/import_urdf.py (lines 81‑85). When these flags are set to true in the source file, the import pipeline automatically invokes the sewing spring generation logic equivalent to calling sew_close_vertices manually in Python.

Why must I call SolverStyle3D.register_custom_attributes() before finalizing the model?

The Style3D solver requires custom attributes such as style3d:tri_aniso_ke (anisotropic stiffness), edge rest areas, and bending cotangents that are not part of the standard Newton particle model. The register_custom_attributes function (lines 321‑324 in newton/_src/solvers/style3d/cloth.py) registers these attributes with the ModelBuilder so that builder.finalize() correctly serializes the Style3D-specific data required by the solver. Without this call, the solver will fail to locate the necessary attribute buffers during simulation stepping.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →