# Performing Cloth Simulation with Self-Collision Detection in Newton

> Learn how Newton performs cloth simulation with self-collision detection using BVH proximity queries and the Style3D solver for realistic fabric dynamics and inter-penetration prevention.

- Repository: [Newton Physics/newton](https://github.com/newton-physics/newton)
- Tags: tutorial
- Published: 2026-03-19

---

**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`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_usd.py) (lines 67‑71) and [`newton/_src/utils/import_urdf.py`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/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.

```python
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:

```python
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:

```python
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:

```python
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`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/newton/_src/sim/builder.py) | `ModelBuilder` API for adding particles, triangles, edges, and springs. |
| [`newton/_src/solvers/style3d/__init__.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/solvers/style3d/__init__.py) | Public API exports for the Style3D solver components. |
| [`newton/_src/utils/import_usd.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_usd.py) | Parses `newton:selfCollisionEnabled` schema flag (lines 67‑71). |
| [`newton/_src/utils/import_urdf.py`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_urdf.py) | Handles `physxArticulation:enabledSelfCollisions` (lines 81‑85). |
| [`newton/tests/test_cloth.py`](https://github.com/newton-physics/newton/blob/main/newton/tests/test_cloth.py) | Validation suite including `test_cloth_collision` (lines 1091‑1105) for self-collision correctness. |
| [`newton/solvers.py`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/newton/_src/utils/import_usd.py) (lines 67‑71) and the **`physxArticulation:enabledSelfCollisions`** attribute in [`newton/_src/utils/import_urdf.py`](https://github.com/newton-physics/newton/blob/main/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`](https://github.com/newton-physics/newton/blob/main/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.