Specimen Report · TypeScript

clothos

phiat/clothos

WebGL cloth-simulation prototype — a gravity-draped sheet that fills the viewport and reacts to cursor/touch with smoothstep falloff and spring-overshoot inertia.

Stars
★ 1
Forks
⑂ 0
Language
TypeScript
Size
2,303 kB
Last Push
12h ago
Forged
9d ago
# clothos [![Live](https://img.shields.io/badge/live-clothos.norfnorf.com-77b989?style=flat-square)](https://clothos.norfnorf.com) [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-3178c6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Three.js](https://img.shields.io/badge/Three.js-r169-000?style=flat-square&logo=three.js&logoColor=white)](https://threejs.org/) [![Vite](https://img.shields.io/badge/Vite-5-646cff?style=flat-square&logo=vite&logoColor=white)](https://vitejs.dev/) [![License: MIT](https://img.shields.io/badge/license-MIT-c9cbd6?style=flat-square)](LICENSE) A WebGL cloth-simulation prototype: a gravity-draped sheet that fills the viewport and reacts to cursor/touch with smoothstep falloff and spring-overshoot inertia. ![clothos preview](docs/preview.gif) ## Run ```bash npm install just dev # vite dev server just build # tsc --noEmit + production bundle just deploy # build + rsync dist/ to the host in .env ``` Run `just` alone for the full recipe list (also includes `ssh`, `logs`, `open`, `gif`, `mp4`, `screenshot`). ## Layout ``` src/ main.ts scene, lights, render loop, resize, touch detection cloth.ts Verlet cloth: particles, Jakobsen constraints, normals interaction.ts pointer → cloth force with damped-spring overshoot panelShift.ts glass-panel hue/sat driven by cursor dwell nav.ts tap-to-toggle dropdowns styles.css overlay, dropdowns, glass panel ``` - **Cloth** — `cols × rows` Verlet particles connected by structural / shear / bend constraints, solved with 5 Jakobsen relaxation passes. Perimeter pinned; pre-warmed ~60 steps so the sheet opens already draped. `applyPointerForce` walks only the grid bbox under the influence radius. - **Interaction** — projects the pointer onto z = 0 and deforms vertices with a smoothstep-falloff radius. A damped-spring "center" tracks the pointer with injected velocity, so an abrupt stop overshoots and springs back. - **PanelShift** — accumulates dwell while the cursor sits over the glass and writes `--glass-hue` / `--glass-sat`. Slow ramp up, fast snap back. Touch / coarse-pointer devices get a high-contrast variant (stronger lights, lower roughness, bigger push) — see the `*_TOUCH` constants in `main.ts`. ## Knobs `Cloth` (`cloth.ts` module-level): `GRAVITY`, `DAMPING`, `ITERATIONS`, `SLACK`, `PREWARM_STEPS`. `Interaction` (per-instance fields): - `radiusFrac` — influence radius as a fraction of cloth width. - `pushStrength` — z-push (inward dent). - `dragStrength` — lateral pull scaled by center velocity. - `springStiffness` / `springDamping` — return-to-cursor spring; lower damping vs. stiffness = bigger overshoot. - `trackingGain` — how fast the center matches pointer velocity. - `velocitySmoothing` — one-pole filter on raw pointer velocity. `PanelShift` (per-instance fields): `buildupSec`, `decaySec`, `baseHue` + `hueRange`, `baseSat` + `satRange`. `main.ts`: `CLOTH_COLS`, `CLOTH_ROWS`, `SIZE_MARGIN`, plus paired `*_DESKTOP` / `*_TOUCH` constants for lights, material, and interaction. ## Deploy `just deploy` runs `npm run build` then rsyncs `dist/` to the host configured in `.env` (see `.env.example`). Host is served by nginx with a Let's Encrypt cert; auto-renewal is handled by `certbot.timer`. ## Media The preview gif was generated with `just gif clothos.gif` — a two-pass ffmpeg palette method that shrank a 14MB source down to ~2MB. Also available: `just mp4 <input>` (h264) and `just screenshot` (headless chromium). ## License [MIT](LICENSE) © phiat
↗ GitHub Homepage