---
title: "Simulate cloth in C#"
url: https://recursiveai.org/onephysics/cookbook/simulate-cloth/
description: "Simulate cloth in C#: create a pinned sheet, advance a 3D physics world and read particle positions with OnePhysics. Download the runnable example."
version: "1.0.0"
---

# Simulate cloth in C#

**OnePhysics** is a free, open-source physics library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OnePhysics) · [GitHub](https://github.com/recursive-ai-oss/onephysics-csharp) · [Docs](https://recursiveai.org/onephysics/docs/) · [Download example (.zip)](https://recursiveai.org/onephysics/cookbook/simulate-cloth/simulate-cloth.zip)

Simulate a sheet that bends and sags while its four corners stay pinned. OnePhysics returns particle positions, not rendered frames; tearing is not supported.

```shell
dotnet new console
dotnet add package RecursiveAI.OnePhysics
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneMath;
using RecursiveAI.OnePhysics.Physics3D;

var world = new PhysicsWorld3D();
var cloth = world.AddCloth(
    width: 2f, depth: 2f, segments: 8,
    at: new Vector3D(0, 2, 0),
    pinCorners: true);
for (int i = 0; i < 120; i++)
    world.Step(1f / 60);
Console.WriteLine($"Corner Y: " +
    $"{cloth.GetPosition(0).Y:F3}");
// GetPosition(40) is the center particle.
Console.WriteLine($"Center Y: " +
    $"{cloth.GetPosition(40).Y:F3}");
```

The example needs no input files. It creates a 2 × 2 meter sheet centered at height 2, steps it for two simulated seconds and samples a pinned corner and the center.

`AddCloth` throws `SoftBodyException` when a supplied value is out of range.

`RecursiveAI.OneMath` comes with OnePhysics as a dependency.

Unzip [the example](https://recursiveai.org/onephysics/cookbook/simulate-cloth/simulate-cloth.zip), then `dotnet run`.

```text
Corner Y: 2.000
Center Y: 1.774
```

## Variations

### Pin one edge instead of four corners

Create an unpinned sheet, then pin its first row. With eight cells per side, that row has nine particles.

```csharp
using RecursiveAI.OneMath;
using RecursiveAI.OnePhysics.Physics3D;

var world = new PhysicsWorld3D();
var cloth = world.AddCloth(
    width: 2f, depth: 2f, segments: 8,
    at: new Vector3D(0, 2, 0));
for (int i = 0; i <= 8; i++)
    cloth.SetPinned(i, true);
for (int i = 0; i < 120; i++)
    world.Step(1f / 60);
Console.WriteLine($"Edge Y: " +
    $"{cloth.GetPosition(4).Y:F3}");
// GetPosition(40) is the center particle.
Console.WriteLine($"Center Y: " +
    $"{cloth.GetPosition(40).Y:F3}");
```

```text
Edge Y: 2.000
Center Y: 0.982
```

## Related recipes

[Start a 3D world](https://recursiveai.org/onephysics/cookbook/3d-preview/) · [Save and restore a world](https://recursiveai.org/onephysics/cookbook/rollback/)

---

## The short answer

Use `PhysicsWorld3D.AddCloth` to create a sheet, pin the particles that should stay fixed, and advance the world with `Step`. Read the deformed sheet with `GetPosition`. The program above creates the geometry itself, so you can run it without a mesh file, graphics engine or scene editor.

The important choice is what holds the fabric. Four pinned corners make a suspended sheet. A pinned edge lets the rest hang down. No pins allow the entire sheet to fall. Those are different boundary conditions, not different cloth materials.

## How do I simulate cloth in C#?

Start with the generated sheet in the snippet at the top. `width` and `depth` are its full extents in meters. `at` is the center of the sheet, which initially lies in the x–z plane. The `segments` argument gives the number of cells along each side, not the number of particles. Eight cells produce nine particles per row, and therefore 81 particles in total. The center index in this example is `4 * 9 + 4`, or 40.

Call `Step` at a fixed interval. Here, each step advances the world by one sixtieth of a second; 120 steps advance two simulated seconds. The output shows that the pinned corner stays at its initial height while the center drops. It does not draw the sheet: a renderer needs to consume the updated positions separately.

For an existing graphics mesh, keep its vertex indexing consistent with the simulation mesh. OnePhysics exposes `GetPosition` for a single particle and `CopyPositions` for bulk reads. Do not treat a particle’s new position as a rigid transform for the entire sheet: each particle can move independently within the constraints.

## What is a soft body?

In OnePhysics, a soft body is a mesh of particles held together by edge, bend and volume constraints. Cloth is an open surface; rubber and jelly presets also support volumetric objects. Use the cloth preset for a sheet rather than treating it as a thin rigid box.

Particles act as small spheres for collisions. The documented collision behavior includes static, kinematic and dynamic rigid shapes, and particle self-collision. The simple example has no floor or other collider, so it isolates sag under gravity and the effect of pinning. A hanging edge can descend below the original sheet’s height without that being a collision failure.

`SetPinned(i, true)` fixes a particle at its current position. This is useful when you want a whole edge or selected attachment points rather than the four corners provided by `pinCorners`. A destroyed soft-body handle throws `StaleHandleException`; do not keep reading it after calling `Destroy`.

## Is cloth simulation a mass-spring model?

OnePhysics documents its soft-body solver as extended position-based dynamics, or XPBD, rather than a mass-spring force model. You configure constraints and their compliance: zero compliance is the stiffest setting. The cloth preset resists stretching, bends easily and enables self-collision.

For more control, `SoftBodyDef` exposes edge and bend compliance, damping, particle radius, mass and pins. World options include soft-body substeps and iterations. Keep the mesh, attachment pattern and time step fixed while changing one setting, so you can tell which change affects the shape.

This release does not support tearing. A sheet’s constraints can deform its geometry, but you cannot use the example to simulate a rip opening through the fabric.

Source: [soft-body guide at the pinned release](https://github.com/recursive-ai-oss/onephysics-csharp/blob/11dad30ed91fae25354edb55930c67cc0f71fe25/docs/guide/soft-bodies.md) and [the sheet creation API](https://github.com/recursive-ai-oss/onephysics-csharp/blob/11dad30ed91fae25354edb55930c67cc0f71fe25/src/OnePhysics/Physics3D/PhysicsWorld3D.Soft.cs#L38-L56).
