Physics · interface
ClothOptions
Cloth, as position-based dynamics with compliance.
Explained in Your first game, Rigid bodies.
interface ClothOptionsimport type { ClothOptions } from '@driftengine/physics';In depth
A separate solver from the rigid bodies, deliberately, and it is §5's decision in a different place. Thousands of rotationless particles are the wrong data layout for a rigid constraint graph: every particle would carry an orientation it never uses and an inertia tensor that is always zero. Two solvers with two jobs, not two implementations of one decision.
Compliance rather than a stiffness constant, for the same reason §7 states contact stiffness
as a frequency: α = compliance / h² makes a constraint's stiffness independent of the step
length, so the iteration count is a quality dial rather than a behaviour change. A raw
position-based solver's stiffness is a function of how many times you iterated, which means
tuning it is tuning the solver rather than the cloth.
Two-way coupled since 2026-08-27, by an impulse exchange rather than by a merged island. The
refusal this replaces was right about the price and wrong about the only way to pay it. Putting
particles into the rigid solver's constraint graph would merge islands — a character in a cloak
becomes one island with everything the cloak brushes, and merged islands are what §8a's
parallelism is made of. So that is still refused. What ships instead is the exchange the two
solvers can make without either learning about the other's structure: the collision pass
already moves a particle out of a body, and a particle moved by d in a tick of h has had its
momentum changed by m·d/h; the body receives the opposite of that at the contact point, through
the same applyImpulse any consumer would call.
What that costs, said plainly. The exchange is explicit — the body responds on the next
tick rather than in the same solve — so it is a spring with a one-tick delay in it, and a very
heavy sheet landing on a very light body can oscillate. coupling is a scale from 0 to 1 and
0 is the default, so no existing consumer's world moves by a millimetre until it asks. What
would reverse the remaining refusal: a consumer who needs the sheet and the body to converge
together in one solve, at which point the price is the island structure and it is a track rather
than a field.
Properties
| Name | Type | Description |
|---|---|---|
stretchComplianceoptional | number | Metres of stretch per newton. Zero is inextensible; larger is stretchier. |
bendComplianceoptional | number | The same, for the constraints that resist folding. |
iterationsoptional | number | Solver passes per tick. A quality dial: compliance keeps stiffness meaningful across it. |
selfDistanceoptional | number | How close two unconnected particles may come before they push each other apart, in metres.More0 is off and is the default, because self-collision is the half of cloth whose tuning
decides whether it ships: a sheet that resists itself at a distance larger than its own
spacing cannot lie flat, and one that resists at a distance far smaller than a fold's
thickness passes through itself anyway. A consumer sets this from the sheet they built, and
the honest starting point is a little under the grid spacing — Particles joined by a constraint are exempt, and that is not an optimisation. A stretch
link's rest length is the spacing, so a self-collision distance anywhere near it would have
every neighbour pair fighting its own link at every step — the sheet would inflate rather than
drape, which is the failure that reads as a solver bug. |
dampingoptional | number | Per-second velocity retained, as a fraction. |
thicknessoptional | number | How far a particle is held off a surface it meets. |
couplingoptional | number | How much of the momentum a pushed particle gave up is handed back to the body, 0 to 1.More0 by default, which is one-way coupling and is what every consumer had before this existed. 1 is the whole exchange; anything between is a sheet that pushes less than its mass says it should, which is the dial a consumer reaches for when the delay in the exchange makes a light body jitter. |
particleMassoptional | number | What one particle weighs, in kilograms. Only the coupling reads it.MoreSeparate from The default is fifty grams: a square metre of ordinary cloth is two to three hundred grams,
and |
gravityXoptional | number | |
gravityYoptional | number | |
gravityZoptional | number |