/** * cloth-verlet — pure Verlet+constraint cloth solver. * * Extracted from `packages/runtime/src/traits/PhysicsTraits.ts` ClothTrait * (was lines 120-214) to apply the RULING 2 per-trait wrapper pattern * established by NeuralAnimation: engine-agnostic core math, both core/traits * and runtime/traits get thin wrappers around the same engine. * * No THREE.js / PhysicsWorld dependency. Operates on raw Float32Array * position buffers — caller supplies them, engine modifies in place. * * /stub-audit 2026-04-26 flagged ClothTrait at 15 effective LOC + 17 compiler * refs as a CONFIRMED Pattern B violation. The core/traits/ClothTrait.ts * handler emits cloth_create/cloth_step/cloth_apply_force events that ZERO * runtime listeners ever consume. The actual cloth simulation lives in * runtime/traits/PhysicsTraits.ts (Pattern E manifestation: two unbridged * TraitSystems). This engine extraction is the first step toward bridging * — the math now lives in a place both can call. */ /** * Mutable simulation state. Caller owns the buffers; engine modifies in place * on every step. Float32Array layout is row-major xyz: positions[i*3..i*3+3]. */ export interface ClothVerletState { /** Current vertex positions (count * 3 floats). Modified in place by stepClothVerlet. */ positions: Float32Array; /** Previous-tick vertex positions (count * 3 floats). Modified in place. */ prevPositions: Float32Array; /** Vertex indices that are pinned (immovable). */ pinned: Set; /** Distance constraints — each entry is [vertexA, vertexB, restLength]. */ constraints: Array<[number, number, number]>; /** Wall-clock simulation time (seconds). Caller-managed; engine reads only. */ time: number; } export interface ClothVerletConfig { /** 0–1 — how strongly constraints pull vertices back to rest length. */ stiffness: number; /** 0–1 — velocity damping per step (0 = no damping, 1 = full stop). */ damping: number; /** Gravity scale (1 = -9.81 m/s² on Y). */ gravityScale: number; /** 0–1 — turbulent wind force magnitude. */ windResponse: number; } /** * Build the structural-spring constraint set for a square cloth grid. * * Connects each vertex to its right + bottom neighbor (no diagonals — that's * the shear constraint set, intentionally omitted here for backward parity * with the previous runtime impl). Rest length is computed from the actual * positions in the buffer at construction time, so non-uniform initial * grids are supported. */ export declare function buildClothConstraints(resolution: number, positions: Float32Array): Array<[number, number, number]>; /** * Advance one Verlet integration step + iterative constraint solve. * * Modifies state.positions and state.prevPositions in place. * Caller is responsible for advancing state.time before/after the call — * engine reads it for wind turbulence but does not modify. * * Iteration count for constraint solve = ceil(stiffness * 5). */ export declare function stepClothVerlet(state: ClothVerletState, config: ClothVerletConfig, delta: number): void;