diff --git a/src/qft/carpet.js b/src/qft/carpet.js index cccddac..544d68b 100644 --- a/src/qft/carpet.js +++ b/src/qft/carpet.js @@ -43,6 +43,13 @@ export function carpetSVG(size, opts = {}) { blips: 1.0, // density of the spiralling wave-packet excitations hue: 0.52, hue2: 0.55, sat: 0.55, lightNear: 0.34, lightFar: 0.62, strokeNear: 1.7, strokeFar: 0.5, + // optional field injections (all default OFF → output unchanged): + // warpFn(t, d) → extra normalized vertical displacement (×amp) — an + // external field (e.g. wind) shaping the rows + // phaseFn(t, r) → phase shift added to every base mode (shimmer) + // modesFn(rng, o) → replace the base mode set entirely (e.g. a CMB + // power-spectrum-shaped spectrum) + warpFn: null, phaseFn: null, modesFn: null, }, opts); const W = size, H = size, u = size / 1000; const paper = resolveSubstrate(o.substrate).paper.flat; @@ -50,8 +57,10 @@ export function carpetSVG(size, opts = {}) { // ---- base sea: low-frequency field modes (phase drifts slowly per row) ---- const M = Math.round(4 + o.chaos * 8); - const modes = []; - for (let m = 0; m < M; m++) { + let modes = []; + if (o.modesFn) { + modes = o.modesFn(rng, o); + } else for (let m = 0; m < M; m++) { const f = range(rng, 0.4, 3.0 + o.chaos * 5); // low q: long swells dominate modes.push({ f, a: 1 / (1 + f * 1.0), phi: range(rng, 0, Math.PI * 2), drift: range(rng, -1, 1) * (0.06 + f * 0.02) }); } @@ -78,7 +87,8 @@ export function carpetSVG(size, opts = {}) { const value = (t, r) => { let s = 0; - for (const m of modes) s += m.a * Math.sin(2 * Math.PI * m.f * t + m.phi + r * m.drift); + const dphi = o.phaseFn ? o.phaseFn(t, r) : 0; + for (const m of modes) s += m.a * Math.sin(2 * Math.PI * m.f * t + m.phi + r * m.drift + dphi); s /= norm; let blip = 0; for (const e of exc) { @@ -112,7 +122,8 @@ export function carpetSVG(size, opts = {}) { for (let i = 0; i <= npts; i++) { const t = i / npts; const e = env(t); - pts.push({ x: cx - half + t * 2 * half, y: baseY[r] - amp * e * value(t, r) - amp * 0.55 * (e - eMin) * d }); + const warp = o.warpFn ? o.warpFn(t, d) * amp : 0; + pts.push({ x: cx - half + t * 2 * half, y: baseY[r] - amp * e * value(t, r) - amp * 0.55 * (e - eMin) * d + warp }); } const path = smoothPath(pts); const hue = o.hue + (o.hue2 - o.hue) * (1 - d);