Files
bubblechambersimart/tools/qft-variations-fine.mjs
2026-05-29 15:40:42 -04:00

252 lines
9.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
qft-variations-fine.mjs — sketch 05.
Two new mechanics exercised:
(a) DENSER cubic mesh (cubicN=2 → 125 vertices / ~300 edges)
+ finer photon waves (photonCyclesPerUnit ↑) → "even
finer oscillating sub-grid with each line another hue
in a gradient"
(b) LARGER softer rosettes — E8 cluster scaled 0.550.85
with lightness pushed ABOVE the paper's lightness and
opacity dropped to 0.350.55 → the rosette becomes a
soft luminous halo rather than a focal jewel.
Plus fewer / dimmer cross-field links so they punctuate
instead of dominate.
Output → output/qft/sketch05/
============================================================ */
import { writeFileSync, mkdirSync } from 'node:fs';
import { generateQFTScene } from '../src/qft/scene.js';
import { paramsFromSeed } from '../src/qft/params.js';
import { renderQFTSVG } from '../src/qft/renderer.js';
const BASE_SEED = 'FEYNMAN-7167';
const OUT_DIR = 'output/qft/sketch05';
const SIZE = 1800;
mkdirSync(OUT_DIR, { recursive: true });
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
({ hueStart, hueEnd, saturation, lightness, opacity });
const paper = (flat, glowInDelta = [18, 16, 14], glowOutDelta = [-25, -22, -20]) => ({
flat,
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
});
// shared base for the new sketches
// Dense cubic (300 edges) needs MUCH thinner strokes than sketch04, otherwise it
// piles into solid wallpaper and buries the soft rosettes. Stroke 1.0 + cubic
// opacity ~0.45 leaves room for the rosette + schlegel to read.
const FINE_BASE = {
cubicN: 2, // 5³=125 vertices / ~300 edges
photonCyclesPerUnit: 22, // finer waves than default (12)
segmentsPerEdge: 10,
linkCount: 5, // fewer cross-field links (was 8)
stroke: 1.0, // thin so the dense mesh stays atmospheric, not opaque
};
const variations = [
{
name: '01_spectral-comb-pearl',
label: 'Spectral comb · pearl · dense cubic + radial spectrum + soft rosette',
overrides: {
...FINE_BASE,
paperOverride: paper([240, 235, 230]),
vignOverride: [80, 70, 65], featureOverride: [80, 70, 60],
gradientMode: 'radial',
cubicScale: 1.40, schlegelScale: 0, // no schlegel — let cubic + rosette breathe
e8Origins: [{ x: 0, y: 0, scale: 0.72 }], // single large central rosette
fields: {
cubic: F(0.55, 0.04, 0.65, 0.45, 0.30), // cool centre → warm corners
schlegel: F(0, 0, 0, 0.5, 0), // off
e8: F(0.55, 0.08, 0.55, 0.48, 0.85), // very pale tinted-white halo (L > paper)
links: F(0.04, 0.10, 0.55, 0.45, 0.55), // dim warm links
},
},
},
{
name: '02_dense-radial-cream',
label: 'Dense radial spectrum · cream · large pale rosette',
overrides: {
...FINE_BASE,
substrate: 'cream',
gradientMode: 'radial',
cubicScale: 1.55, schlegelScale: 0.85,
e8Origins: [{ x: 0, y: 0, scale: 0.78 }],
fields: {
cubic: F(0.58, 0.05, 0.70, 0.40, 0.30),
schlegel: F(0.10, 0.05, 0.35, 0.45, 0.55),
e8: F(0.08, 0.04, 0.55, 0.48, 0.85), // pale warm halo on cream
links: F(0.05, 0.10, 0.60, 0.45, 0.55),
},
},
},
{
name: '03_linear-horizon-ivory',
label: 'Linear horizon · ivory · dense cubic with left→right gradient',
overrides: {
...FINE_BASE,
paperOverride: paper([232, 224, 202]),
vignOverride: [70, 55, 40], featureOverride: [60, 50, 35],
gradientMode: 'linear-x',
cubicScale: 1.65, schlegelScale: 0.90,
e8Origins: [{ x: -0.35, y: 0.25, scale: 0.55 },
{ x: 0.35, y: 0.25, scale: 0.55 }], // twin pale rosettes lower
fields: {
cubic: F(0.58, 0.04, 0.65, 0.36, 0.30),
schlegel: F(0.60, 0.08, 0.40, 0.40, 0.55),
e8: F(0.55, 0.10, 0.55, 0.48, 0.85),
links: F(0.06, 0.12, 0.60, 0.40, 0.55),
},
},
},
{
name: '04_twin-rosettes-mauve',
label: 'Twin overlapping rosettes · pale mauve · soft & atmospheric',
overrides: {
...FINE_BASE,
paperOverride: paper([222, 205, 224]),
vignOverride: [55, 35, 60], featureOverride: [75, 50, 90],
gradientMode: 'along-edge',
cubicScale: 1.45, schlegelScale: 0, // no schlegel
e8Origins: [{ x: -0.20, y: 0, scale: 0.65 },
{ x: 0.20, y: 0, scale: 0.65 }],
fields: {
cubic: F(0.72, 0.92, 0.55, 0.38, 0.30),
schlegel: F(0, 0, 0, 0.5, 0),
e8: F(0.78, 0.92, 0.55, 0.48, 0.85), // pale lighter-than-mauve glow
links: F(0.82, 0.95, 0.65, 0.40, 0.55),
},
},
},
{
name: '05_finest-waves-linen',
label: 'Finest photon waves · linen · super-dense cubic + soft halo',
overrides: {
...FINE_BASE,
paperOverride: paper([225, 210, 178]),
vignOverride: [85, 60, 35], featureOverride: [80, 55, 30],
photonCyclesPerUnit: 30, // even finer ripples than the FINE_BASE
cubicScale: 1.50, schlegelScale: 0.75,
e8Origins: [{ x: 0, y: 0, scale: 0.82 }],
fields: {
cubic: F(0.08, 0.14, 0.60, 0.35, 0.30),
schlegel: F(0.04, 0.10, 0.40, 0.35, 0.55),
e8: F(0.10, 0.06, 0.55, 0.48, 0.85),
links: F(0.06, 0.10, 0.60, 0.40, 0.55),
},
},
},
{
name: '06_big-mandala-pale-blue',
label: 'Big central mandala · pale blue · single huge rosette',
overrides: {
...FINE_BASE,
paperOverride: paper([190, 215, 230]),
vignOverride: [40, 55, 70], featureOverride: [30, 50, 75],
gradientMode: 'radial',
cubicScale: 1.50, schlegelScale: 0.80,
e8Origins: [{ x: 0, y: 0, scale: 0.92 }], // very large central rosette
fields: {
cubic: F(0.60, 0.66, 0.65, 0.25, 0.30),
schlegel: F(0.58, 0.62, 0.45, 0.28, 0.55),
e8: F(0.55, 0.65, 0.55, 0.48, 0.85), // near-white tinted-blue halo
links: F(0.58, 0.66, 0.65, 0.32, 0.55),
},
},
},
{
name: '07_dense-ghostly-schlegel-bone',
label: 'Dense cubic + ghostly large Schlegel · bone china',
overrides: {
...FINE_BASE,
paperOverride: paper([234, 230, 222]),
vignOverride: [80, 70, 60], featureOverride: [70, 60, 50],
gradientMode: 'radial',
cubicScale: 1.55, schlegelScale: 1.85, // big BUT...
e8Origins: [{ x: 0, y: 0, scale: 0.72 }],
fields: {
cubic: F(0.55, 0.05, 0.65, 0.38, 0.30),
schlegel: F(0.62, 0.10, 0.25, 0.92, 0.35), // ...made ghostly: pale + low opacity
e8: F(0.10, 0.06, 0.55, 0.48, 0.85),
links: F(0.06, 0.10, 0.55, 0.40, 0.50),
},
},
},
{
name: '08_atmospheric-mint',
label: 'Atmospheric · pale mint · large soft rosette dominant',
overrides: {
...FINE_BASE,
paperOverride: paper([210, 225, 208]),
vignOverride: [30, 55, 35], featureOverride: [40, 70, 45],
stroke: 1.6, // thinner — let the rosette breathe
cubicScale: 1.30, schlegelScale: 0,
e8Origins: [{ x: 0, y: 0, scale: 0.85 }],
fields: {
cubic: F(0.42, 0.50, 0.45, 0.36, 0.30),
schlegel: F(0, 0, 0, 0.5, 0),
e8: F(0.40, 0.50, 0.55, 0.48, 0.85),
links: F(0.12, 0.18, 0.55, 0.42, 0.55),
},
},
},
{
name: '09_all-dense-layered-pearl',
label: 'Everything dense and layered · pearl · 4 rosettes, full spectrum',
overrides: {
...FINE_BASE,
paperOverride: paper([240, 235, 230]),
vignOverride: [80, 70, 65], featureOverride: [80, 70, 60],
gradientMode: 'radial',
cubicScale: 1.60, schlegelScale: 1.20,
e8Origins: [
{ x: -0.30, y: -0.30, scale: 0.42 },
{ x: 0.30, y: -0.30, scale: 0.42 },
{ x: -0.30, y: 0.30, scale: 0.42 },
{ x: 0.30, y: 0.30, scale: 0.42 },
],
linkCount: 8,
fields: {
cubic: F(0.55, 0.05, 0.65, 0.40, 0.30),
schlegel: F(0.58, 0.10, 0.35, 0.42, 0.55),
e8: F(0.55, 0.08, 0.55, 0.48, 0.85),
links: F(0.06, 0.10, 0.55, 0.42, 0.55),
},
},
},
{
name: '10_concentric-rosettes-pale-rose',
label: 'Concentric nested rosettes · pale rose · all centred',
overrides: {
...FINE_BASE,
paperOverride: paper([232, 210, 210]),
vignOverride: [80, 55, 55], featureOverride: [90, 55, 55],
gradientMode: 'radial',
cubicScale: 1.30, schlegelScale: 0,
e8Origins: [
{ x: 0, y: 0, scale: 0.95 }, // outermost
{ x: 0, y: 0, scale: 0.62 }, // middle
{ x: 0, y: 0, scale: 0.30 }, // innermost
],
linkCount: 0, // no links — the nested rosettes are the picture
fields: {
cubic: F(0.95, 0.03, 0.55, 0.38, 0.30),
schlegel: F(0, 0, 0, 0.5, 0),
e8: F(0.92, 0.05, 0.55, 0.48, 0.85),
links: F(0.9, 0.05, 0.55, 0.42, 0.50),
},
},
},
];
const base = paramsFromSeed(BASE_SEED);
for (const v of variations) {
const params = { ...base, ...v.overrides };
if (v.overrides.fields) params.fields = v.overrides.fields;
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
const path = `${OUT_DIR}/${v.name}.svg`;
writeFileSync(path, svg);
console.log(`ok ${v.name} · ${v.label}`);
}
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);