# Jelly – soft‑body slime in Three.js

A glossy, translucent jelly blob resting on a floor. It is a real soft body: poke it, drag it, drop it, and it squishes, wobbles and settles.

## Run

No build step. Open `index.html` directly, or serve the folder:

```
python3 -m http.server 8000   # then open http://localhost:8000
```

three.js r159 is vendored in `vendor/three.min.js` (classic script, so it also works from `file://`). It prints a harmless "build/three.min.js is deprecated" console note.

## Controls

| Action | Mouse | Touch |
|---|---|---|
| Poke / squish (Poke mode) | press on the blob and hold; drag to slide the dent around | same, with a finger |
| Stretch (Grab mode) | press on the blob and drag; release to let it snap back | same |
| Orbit camera | drag on empty space | drag on empty space |
| Zoom | mouse wheel | – |
| Drop from height | **Drop** button (or `D` / `Space`) | **Drop** button |
| Set drop height | **Height** slider (1.5 – 6 m) | slider |
| Reset to resting blob | **Reset** button (or `R`) | **Reset** button |
| Jelly colour | colour dots | colour dots |

Tapping the blob gives an instant kick, so quick taps read as a dent; holding keeps pressing.

## How it works

- **Physics** (`SoftBlob`, plain JS, 2562 particles / 7680 edges, fixed 1/120 s step): edge springs, a shape‑memory pull toward the rest shape, an internal pressure term that conserves volume, thin‑shell bending resistance, and damping relative to the centre of mass (this is what makes it jiggle and then settle). The floor gives friction and no bounce, so the landing energy shows up as squash and wobble.
- **Look**: one custom shader. It uses analytic refraction of the checker floor and contact shadow, Beer‑Lambert absorption over the ellipsoid path length, in‑scattering, a back‑lit subsurface glow, rim light, Fresnel reflection of a procedural softbox studio, and sharp key‑light speculars. It needs no transmission pass or environment map, so it stays cheap.
- **Contact shadow**: the blob's own particles are splatted top‑down into a 192² half‑float map. Particles near the floor make tight dark contact; higher ones make a wider, fainter penumbra, and the shadow is tinted by the jelly colour. The floor samples that map.
- **Mobile**: pointer events with `touch-action: none`, pixel ratio capped at 2 and lowered automatically if frame time stays above ~21 ms, no backdrop blur on the UI, and the camera framing accounts for the control panel and portrait/landscape.
