← All projects

CabinFever

In development

A dependency-free browser library that produces 17 traditional paper-marbling patterns with area-preserving geometric maps.

Generative ArtComputational GeometrySimulationJavaScriptCanvas
The library itself, drawing live. Each drop displaces the ink already floating rather than covering it, squeezing earlier colours into rings; then a comb drags the whole surface at once. Every operation preserves area exactly, which is what a film of pigment on water actually does. Tap to drop pigment, drag to comb.

At a glance

  • Outcome: Implements 17 traditional pattern functions, including battal, gel-git, nonpareil, feather, şal, hatip, suminagashi, Italian hair vein and nine more. Treats every tool as an area-preserving plane map.
  • Status: Second engine, at version 0.1.0; the first engine and 12 prototypes before it were discarded. On September 11, 2026, 162 commits end at the August 27 rebuild. The demo vendors 94bcc65, two commits behind, using unchanged stone, gelGit and nonpareil to draw the same sheet. It predates the rake catalogue and 12 later patterns.
  • Role: Solo.
  • Stack & libraries: Uses plain ESM, zero dependencies, no build step and one canvas. Runs a fragment-shader-style texture pass over CPU ImageData, without WebGL and with headless support. Tooling uses Node, headless Firefox and WebDriver BiDi.
  • Source: Publishes the MIT-licensed source at github.com/Griffinhale/cabinFever.
  • Validation: Runs 41 one-file node --test cases in 0.4 seconds under Node 22 on September 11, 2026. Tests every map’s area preservation, every catalogue rake’s decay bound and r₁+r₂=√(r₁²+r₂²) composition to 1e-6. Every figure is generated from a seed with explicit timesteps and no clock.
  • Limitations: Provides no fluid solver, velocity field, timestepped physics or colour mixing because pigment displaces rather than blends. Spanish ripple shears film instead of lifting paper; its banding matches but its mechanism does not. Finite lines walk their path placing discs above a spacing floor because no closed-form map exists. Only the stylus lacks exact area preservation. italianVein takes about 2.4 seconds against feather’s 380ms for a reason that isn’t going away. The unpublished package makes npm install cabinfever fail, so this site vendors it.

Displacement model

Models ox-gall pigment on thickened size. New drops spread through noncompressible film and displace earlier colour into rings.

Maps every boundary. A radius r disc at C sends points to C + (P−C)·√(1 + r²/‖P−C‖²). Because ρ′ = √(ρ² + r²) and ρ′dρ′ = ρdρ, area is exact. Comb teeth create Jacobian-1 shears by moving points parallel to their lines according to perpendicular distance.

Preserves exact polygon edges through any stretching, including hair-width filaments. Quadrature makes a held press equal one large drop, enabling exact frame-by-frame growth.

Prototype results

Compared 12 standalone pigment sketches across two waves with a pre-code rubric covering beauty, feel, collisions and later displacement support. All 12 stopped regions at neighbors because the rubric never tested displacement itself.

Built and discarded a grid engine from two prototypes. The repository retains both rounds and an identical-input contact sheet of all 12.

Pattern operations

Adds one tool pass per traditional pattern. stone uses drops; gelGit uses an across-tray down-and-up needle; nonpareil uses a fine straight comb; feather adds a wide perpendicular comb.

Builds hatip from nested drops and an outward pull that forms petals. Equal drops thin its rings as √k, matching a rosette’s fine outer bands. Suminagashi nudges and shears two dozen alternating rings into contours rather than pushing. Italian hair vein repeats the final colour’s drops to represent extra gall without modelling it.

Comb spacing

Keeps comb decay well below tooth spacing. Similar values merge teeth into lane-free translation; full-spacing wave amplitude enters neighboring lanes, gives their teeth conflicting directions and creates cross-hatching.

Defines classic teeth as λ^(|s|/z). Its corner flips the derivative at s = 0, leaving creases and opposing cusps. The rounded λ^((s/z)²) removes that corner without moving the tooth while retaining both controls and one-decay-length displacement. Both are exact area-preserving shears based only on perpendicular distance.

Prior art

Uses Lu, Jaffer, Jin, Gao and Mao’s Mathematical Marbling (IEEE CG&A, 2012) and Aubrey Jaffer’s notes. The repository cites both, a contrasting fluid solver and the Turkish Cultural Foundation’s monograph. Original work includes the engine, gestures, rake catalogue, rounded tooth, texture pass and development account.