const numPts = 70, radiArr = [0.01, 0.02, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], da = 0.05;
createCanvas(S=min(windowWidth, windowHeight), S);
describe("wobbling quantum rays");
noiseSeed(~~random(123456789));
translate(width/2, height/2);
const d = noise(frameCount/123)/2;
for (let i = 0; i < numPts; i++) {
stroke(pal[~~(i+frameCount/33)%pal.length])
const clr = getClrFromPalette(pal, ((i+frameCount/15)%pal.length)/pal.length);
for (let j = 0; j < radiArr.length; j++) {
const na = i/numPts * TAU;
const ns = noise(345345+cos(na)*nr, 123412+sin(na)*nr, frameCount/120);
const ra = ((j % 2 == 0) ? da : -da) * sin(frameCount/120);
const ang = i/numPts * TAU + ra + frameCount / 240;
const r = S * radiArr[j] * map(ns, 0, 1, d, 1-d);
svgSplines.push(svgSpline);
function getClrFromPalette(palette, fr, al = 0) {
const ci = fr * palette.length;
const clr1 = color(palette[(~~ci+0) % palette.length]);
const clr2 = color(palette[(~~ci+1) % palette.length]);
return lerpColor(clr1, clr2, fract(ci));
function mouseClicked() {
if (mouseButton != RIGHT) setup();
for (let i = 0; i < pal.length; i++) {
const h_h = ~~(height/2);
for (let j = 0; j < svgSplines.length; j++) {
const svgSpline = svgSplines[j];
let svgLine = `<polyline points="`;
for (let i = 0; i < svgSpline.length-3; i++) {
const p1 = svgSpline[i+0]
const p2 = svgSpline[i+1]
const p3 = svgSpline[i+2]
const p4 = svgSpline[i+3]
for (let f = 0.1; f <=1; f += 0.1) {
const x = curvePoint(p1.x, p2.x, p3.x, p4.x, f) + w_h;
const y = curvePoint(p1.y, p2.y, p3.y, p4.y, f) + h_h;
svgLine += `${nf(x,0,1)} ${nf(y,0,1)} `;
svgGrps[j%pal.length] += svgLine;
let svgStr = `<svg width="${width}" height="${width}" version="1.1" xmlns="http://www.w3.org/2000/svg">\n`;
for (let i = 0; i < svgGrps.length; i++) {
svgStr += `<g stroke="${pal[i]}" fill="none">\n${svgGrps[i]}\n</g>\n`;
save(svgStr.split("\n"), "epi_quantum_rays.svg.txt")