Files
bubblechambersimart/tools/qft-carpet.mjs

50 lines
4.2 KiB
JavaScript
Raw Normal View History

/* ============================================================
qft-carpet.mjs render VACUUM CARPET studies + a plexi deck.
Logic lives in src/qft/carpet.js (shared with tools/layering.mjs).
Usage: node tools/qft-carpet.mjs [size]
============================================================ */
import { writeFileSync, mkdirSync } from 'node:fs';
import { carpetSVG } from '../src/qft/carpet.js';
const SIZE = +(process.argv[2] || 1500);
const ROOT = 'output/qft/carpet';
mkdirSync(`${ROOT}/explore`, { recursive: true });
mkdirSync(`${ROOT}/layers`, { recursive: true });
// EXPLORE — soft sinusoidal/spiralling blips across the chaos range
const EXPLORE = [
{ name: '01_calm-ridgeline', label: 'calm · low-q swells, few blips', o: { chaos: 0.22, blips: 0.5, rows: 44, overlap: 1.6 } },
{ name: '02_vacuum-seethe', label: 'vacuum seethe · many spiralling blips', o: { chaos: 0.8, blips: 1.4, rows: 50, overlap: 1.8, salt: 'seethe' } },
{ name: '03_dense-fine', label: 'dense fine weave', o: { chaos: 0.5, blips: 1.0, rows: 70, overlap: 1.5, strokeNear: 1.2, salt: 'fine' } },
{ name: '04_sparse-bold', label: 'sparse · bold soft swells', o: { chaos: 0.55, blips: 0.9, rows: 30, overlap: 2.2, strokeNear: 2.2, salt: 'bold' } },
{ name: '05_deep-horizon', label: 'deep horizon · more sky above the mound', o: { chaos: 0.5, blips: 0.9, rows: 56, horizon: 0.44, wFar: 0.58, wNear: 0.74, salt: 'deep' } },
{ name: '06_verdigris-seethe', label: 'verdigris vacuum · oxidised', o: { chaos: 0.7, blips: 1.2, rows: 48, hue: 0.40, hue2: 0.47, sat: 0.42, salt: 'verd' } },
];
console.log(`carpet · explore (${EXPLORE.length}) → ${ROOT}/explore/`);
for (const v of EXPLORE) {
writeFileSync(`${ROOT}/explore/${v.name}.svg`, carpetSVG(SIZE, { ...v.o, mode: 'solid' }));
console.log(` ${v.name}${v.label}`);
}
{
const cap = (v) => `${v.name.replace(/^\d+_/, '').replace(/-/g, ' ')} · ${v.label}`;
writeFileSync(`${ROOT}/explore/m.html`, `<!DOCTYPE html><html><head><meta charset="utf-8">
<style>html,body{margin:0;background:#222}.grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;padding:10px;width:2000px}figure{margin:0;position:relative;background:#fff;overflow:hidden}img{width:100%;display:block}figcaption{position:absolute;left:0;bottom:0;right:0;padding:6px 10px;font:13px ui-monospace,monospace;color:#fff;background:linear-gradient(transparent,#000d)}</style></head><body>
<div class="grid">${EXPLORE.map(v => `<figure><img src="${v.name}.svg"><figcaption>${cap(v)}</figcaption></figure>`).join('')}</div></body></html>`);
}
// LAYERS — three transparent PLATE sheets for a spaced plexi deck
const DECK = [
{ name: 'L3_back', salt: 'fieldA', hue: 0.58, hue2: 0.62, chaos: 0.55, blips: 0.8 },
{ name: 'L2_mid', salt: 'fieldB', hue: 0.52, hue2: 0.56, chaos: 0.65, blips: 1.0 },
{ name: 'L1_front', salt: 'fieldC', hue: 0.47, hue2: 0.50, chaos: 0.75, blips: 1.2 },
];
const deckBase = { mode: 'plate', rows: 46, horizon: 0.36, wFar: 0.58, wNear: 0.7, overlap: 1.7, mound: 0.4, sat: 0.6, lightNear: 0.33, lightFar: 0.55 };
console.log(`carpet · plexi deck (${DECK.length}) → ${ROOT}/layers/`);
for (const v of DECK) { writeFileSync(`${ROOT}/layers/${v.name}.svg`, carpetSVG(SIZE, { ...deckBase, ...v })); console.log(` ${v.name}`); }
writeFileSync(`${ROOT}/stack.html`, `<!DOCTYPE html><html><head><meta charset="utf-8"><title>vacuum carpet · plexi deck</title>
<style>html,body{margin:0;background:#0c0c0c}.stage{position:relative;width:${SIZE}px;height:${SIZE}px;margin:30px auto;background:rgb(226,219,199);box-shadow:0 0 120px #000 inset}.stage img{position:absolute;inset:0;width:100%;height:100%}.L3{filter:blur(2.2px);opacity:.5;transform:translateY(-6px) scale(1.01)}.L2{filter:blur(1px);opacity:.72;transform:translateY(-2px)}.L1{opacity:.95}.cap{max-width:${SIZE}px;margin:0 auto;color:#888;font:12px ui-monospace,monospace;padding:0 4px}</style></head><body>
<div class="stage"><img class="L3" src="layers/L3_back.svg"><img class="L2" src="layers/L2_mid.svg"><img class="L1" src="layers/L1_front.svg"></div>
<p class="cap">deck (backfront): film/diffusion · L3 · L2 · L1 · [bubble chamber]. back sheets blurred+dimmed = air-gap depth of field.</p></body></html>`);
console.log(`stack -> ${ROOT}/stack.html ; explore -> ${ROOT}/explore/m.html`);