# @ferret/physics-stretch: API

springs, ropes and bands that stretch and tear; cloth and soft bodies by position-based dynamics.

13 exports. Generated from the source (`packages/physics-stretch/src`), so it matches the code.

## Classes

### Cloth

*class* · `packages/physics-stretch/src/cloth.ts:50`

```ts
class Cloth
```

- `readonly n: number`
- `readonly x: Float64Array`
- `readonly prev: Float64Array`
- `readonly inv: Float64Array`
- `readonly links: Link[]`
- `readonly colliders: ClothCollider[]`
- `gravity: Vec3`
- `wind: ((p: Vec3) => Vec3) | null` — wind velocity at a point
- `readonly def: Required<Omit<ClothDef, 'origin' | 'u' | 'v' | 'pinned' | 'tearStrain'>> & { origin: Vec3; u: Vec3; v: Vec3; tearStrain?: number }`
- `onTear: ((l: { i: number; j: number; kind: string }) => void) | null` — called for each link that tears, after the step
- `torn: number` — links torn so far
- `time: number`
- `constructor(d: ClothDef)`
- `position(i: number): Vec3`
- `pin(i: number)`
- `release(i: number)`
- `move(i: number, p: Vec3)` — Move a pinned particle (a hand holding a flag).
- `maxStrain(): number` — The largest stretch of any weave link above its rest length (0.1 = 10 %).
- `step(dt: number)`

### Link

*class* · `packages/physics-stretch/src/links.ts:32`

```ts
class Link
```

- `readonly a: Body`
- `readonly b: Body`
- `readonly L0: number`
- `readonly k: number`
- `readonly damping: number`
- `readonly rope: boolean`
- `readonly yieldStrain: number`
- `readonly hardening: number`
- `readonly breakStrain: number`
- `readonly name?: string`
- `plastic: number` — permanent strain and the accumulated plastic strain (they differ only after a reversal)
- `alpha: number`
- `broken: boolean`
- `c: Constraint | null`
- `constructor(private readonly kernel: PhysicsKernel, d: LinkDef)`
- `get distance(): number`
- `get strain(): number` — (L − L0)/L0
- `get elastic(): number` — the elastic part of the strain
- `get force(): number` — tension, N (negative in compression)
- `get rest(): number` — the length the link now rests at, m
- `update(): boolean` — Called after the kernel step. Returns true on the step the link breaks.
- `break()`
- `remove()`

### SoftBody

*class* · `packages/physics-stretch/src/soft.ts:27`

```ts
class SoftBody
```

A soft body by position-based dynamics: a closed skin of particles held by its edges and by one constraint on the volume it encloses
(Müller's balloon), so a ball of jelly or a cushion squashes on the ground and bulges at the sides instead of losing its volume. Collides
with planes (`floor`); deterministic.

- `readonly n: number`
- `readonly x: Float64Array`
- `readonly prev: Float64Array`
- `readonly inv: number`
- `readonly tris: number[]`
- `readonly edges: Array<{ i: number; j: number; rest: number }>`
- `readonly rest: number`
- `gravity: Vec3`
- `floors: Array<{ normal: Vec3; offset: number }>`
- `readonly def: Required<Omit<SoftBodyDef, 'centre' | 'radius' | 'rings' | 'segments'>>`
- `constructor(d: SoftBodyDef)`
- `volume(): number` — Enclosed volume, m³ (the divergence theorem over the skin).
- `centre(): Vec3`
- `extent()` — Lowest point and widest extent across x, m.
- `step(dt: number)`

## Functions

### makeRope

*function* · `packages/physics-stretch/src/links.ts:122`

```ts
function makeRope(kernel: PhysicsKernel, d: RopeDef): RopeResult
```

A chain of beads joined by links; the stiffness of the whole is E·A/L, so each of n segments is n·E·A/L.

### stretch

*function* · `packages/physics-stretch/src/index.ts:30`

```ts
function stretch(): StretchCapability
```

## Interfaces

### ClothDef

*interface* · `packages/physics-stretch/src/cloth.ts:14`

```ts
interface ClothDef
```

- `nu: number` — particles along the two directions
- `nv: number`
- `spacing: number` — distance between neighbouring particles, m
- `origin?: Vec3` — position of particle (0, 0), and the directions the grid runs in
- `u?: Vec3`
- `v?: Vec3`
- `mass: number` — total mass, kg
- `stiffness?: number` — 0..1: how hard the weave links are corrected each iteration
- `bending?: number` — 0..1 for the bending links (0 = a flexible sheet, 1 = a stiff plate)
- `strainLimit?: number` — a link may not be longer than its rest length times this
- `damping?: number` — velocity lost per second, 0..1
- `thickness?: number` — half the thickness: particles stay this far outside colliders, m
- `friction?: number`
- `iterations?: number`
- `substeps?: number`
- `pinned?: 'top' | 'corners' | 'none' | number[]` — particles held where they are: 'top' (the first row of v), 'corners', or indices
- `drag?: number` — air drag coefficient, kg/s per particle against the wind
- `tearStrain?: number` — a weave or shear link still stretched past this strain at the end of a sub-step tears (0.15 = 15 %); never when missing. The strain of the solved sheet, so it is a dial of this model: a sheet of 12 rows hangs at about 5 % under its weight

### LinkDef

*interface* · `packages/physics-stretch/src/links.ts:8`

```ts
interface LinkDef
```

Springs, ropes and bands between two kernel bodies. A link is a kernel spring whose rest length and stiffness this layer keeps up
to date: elastic first, then plastic past the yield strain (a permanent set, with linear hardening), then broken past the tensile
strain. A rope-like link does not push: when the two ends are closer than the rest length it carries no force.

- `a: Body`
- `b: Body`
- `length?: number` — natural length, m (the present distance when missing)
- `k?: number` — stiffness N/m; or give E (Pa) and area (m²) and it is E·A/L
- `E?: number`
- `area?: number`
- `damping?: number` — N·s/m
- `rope?: boolean` — true: no force when slack
- `yieldStrain?: number` — strain (ΔL/L) where the link stops being elastic; never when missing
- `hardening?: number` — plastic hardening: the yield strain grows by this ratio of the plastic strain (0 = perfectly plastic)
- `breakStrain?: number` — strain where the link breaks; never when missing
- `name?: string`

### RopeDef

*interface* · `packages/physics-stretch/src/links.ts:98`

```ts
interface RopeDef
```

- `from: Vec3`
- `to: Vec3`
- `segments: number`
- `mass: number` — total mass, kg
- `E: number` — string area and Young's modulus, for the stiffness of the whole rope: k_total = E·A/L
- `area: number`
- `damping?: number`
- `anchorA?: Body` — body of the end(s): a static or kinematic body to hang from; otherwise a free end
- `anchorB?: Body`
- `yieldStrain?: number`
- `hardening?: number`
- `breakStrain?: number`
- `radius?: number` — radius of the beads, m
- `rope?: boolean`

### RopeResult

*interface* · `packages/physics-stretch/src/links.ts:119`

```ts
interface RopeResult
```

- `beads: Body[]`
- `links: Link[]`

### SoftBodyDef

*interface* · `packages/physics-stretch/src/soft.ts:3`

```ts
interface SoftBodyDef
```

- `centre: Vec3` — centre and radius of the ball the body starts as
- `radius: number`
- `rings?: number` — rings of latitude and segments of longitude of its surface
- `segments?: number`
- `mass: number`
- `stiffness?: number` — 0..1: how hard the skin's edges are corrected each iteration
- `pressure?: number` — the volume it keeps, as a share of the one it starts with (1 = a closed ball of water; above 1 = blown up)
- `iterations?: number`
- `substeps?: number`
- `damping?: number` — velocity lost per second, 0..1
- `friction?: number`

### StretchCapability

*interface* · `packages/physics-stretch/src/index.ts:20`

```ts
interface StretchCapability extends Capability
```

- `readonly links: Set<Link>`
- `readonly cloths: Map<string, Cloth>`
- `link(d: LinkDef): Link`
- `rope(d: RopeDef): RopeResult`
- `addCloth(name: string, d: ClothDef): Cloth`
- `particles(): { asked: number; stepped: number }` — Particles that cloths asked for, and the part the budget lets through.

## Types

### ClothCollider

*type* · `packages/physics-stretch/src/cloth.ts:8`

```ts
type ClothCollider = | { type: 'sphere'; center: Vec3; radius: number } | { type: 'plane'; normal: Vec3; offset: number } | { type: 'box'; center: Vec3; half: Vec3 } | { type: 'body'; body: Body }
```

Cloth and soft sheets by position-based dynamics: distance constraints along the weave and across it, bending constraints between
next-but-one neighbours, a hard limit on how far any link may stretch, and collisions with spheres, planes, boxes and the bodies of the
scene. Verlet integration at a fixed step with a fixed number of iterations, so a replay is identical.

## Constants

### STRETCH_DEFAULTS

*const* · `packages/physics-stretch/src/index.ts:18`

```ts
const STRETCH_DEFAULTS: { particleBudget: number; wind: [number, number, number]; }
```

things that stretch. Links (springs, ropes, bands) are kept elastic, plastic or broken by their strain; cloth is
stepped by position-based dynamics, with a particle budget so a scene cannot ask for more than it can pay.

values (each at world / level / zone / entity scope):
  particleBudget   most cloth particles stepped per frame, all cloths together   (4000)
  wind             wind velocity on cloth, [x, y, z] m/s                          ([0, 0, 0])

events: `stretch:yield` { link }, `stretch:break` { link }.

