Cyclops
"Root Burst" is a generative art script that creates an organic radial fractal. It features a textured spiral core and uses recursive branching logic to grow tendrils. Each tendril mimics biological growth through simulated line thickness, tapering off and splitting into smaller sub-branches based on distance and pseudo-random probability.
You can use the sliders to turn the whole thing from sharp, mechanical triangles into soft, organic bubbles.
Log in to post a comment.
// Root burst with solid core + tapering thickness + controllable recursion density
const core = 45; // min=10 max=90 step=1
const outer = 190; // min=80 max=230 step=1
const roots = 160; // min=20 max=250 step=5
const levels = 5; // min=1 max=8 step=1
const spread = 0.38; // min=0.05 max=1 step=0.01
const curl = 0.22; // min=-1 max=1 step=0.01
const density = 1.2; // min=0 max=2 step=0.01
const baseWidth = 7; // min=1 max=30 step=1
const taper = 1.4; // min=0.3 max=3 step=0.01
const bw = 1 // min=-1 max=1 step=0.01
const recurseStart = 0.25; // min=0 max=1 step=0.01
const branchBoost = 2.2; // min=0.5 max=4 step=0.01
const maxChildren = 4; // min=1 max=5 step=1
Canvas.setpenopacity(-0.55 * bw);
const t = new Turtle();
function rnd(n) {
return Math.abs(Math.sin(n * 43758.5453) * 9999) % 1;
}
function jump(x, y) {
t.penup();
t.goto(x, y);
t.pendown();
}
function circle(r) {
jump(r, 0);
for (let i = 0; i <= 180; i++) {
let a = Math.PI * 2 * i / 180;
t.goto(Math.cos(a) * r, Math.sin(a) * r);
}
}
function solidCore(radius) {
const passes = 3; // increase for darker fill
const step = 0.35; // smaller = denser
for (let p = 0; p < passes; p++) {
// horizontal fill
for (let y = -radius; y <= radius; y += step) {
let x = Math.sqrt(radius * radius - y * y);
jump(-x, y);
t.goto(x, y);
}
// vertical fill (important — fills gaps)
for (let x = -radius; x <= radius; x += step) {
let y = Math.sqrt(radius * radius - x * x);
jump(x, -y);
t.goto(x, y);
}
}
circle(radius);
}
function thickSegment(x1, y1, x2, y2, width) {
let a = Math.atan2(y2 - y1, x2 - x1);
let nx = Math.cos(a + Math.PI / 2);
let ny = Math.sin(a + Math.PI / 2);
for (let i = 0; i < width; i++) {
let off = (i - width / 2) * 0.05;
jump(x1 + nx * off, y1 + ny * off);
t.goto(x2 + nx * off, y2 + ny * off);
}
}
function branch(x, y, a, len, level, seed, startWidth) {
if (level <= 0 || len < 4 || startWidth < 1) return;
let px = x;
let py = y;
const steps = 9;
for (let i = 1; i <= steps; i++) {
let u = i / steps;
a += Math.sin(u * Math.PI * 2 + seed) * curl;
a += (rnd(seed + i) - 0.5) * 0.16;
let nx = px + Math.cos(a) * len / steps;
let ny = py + Math.sin(a) * len / steps;
if (Math.sqrt(nx * nx + ny * ny) > outer) return;
let w = Math.max(1, Math.floor(startWidth * Math.pow(1 - u, taper)));
thickSegment(px, py, nx, ny, w);
px = nx;
py = ny;
}
let dist = Math.sqrt(px * px + py * py);
let outward = (dist - core) / (outer - core);
let childCount = 1;
if (outward > recurseStart) {
childCount = 1 + Math.floor(maxChildren * outward * branchBoost);
}
for (let c = 0; c < childCount; c++) {
if (outward > recurseStart && rnd(seed * 17 + c) < density) {
let side = c % 2 === 0 ? -1 : 1;
branch(
px,
py,
a + side * spread * (0.6 + rnd(seed + c)),
len * (0.62 + rnd(seed + c * 2) * 0.12),
level - 1,
seed + c * 13.7 + level,
startWidth * 0.65
);
}
}
}
solidCore(core);
for (let i = 0; i < roots; i++) {
let a = Math.PI * 2 * i / roots;
let x = Math.cos(a) * core;
let y = Math.sin(a) * core;
branch(
x,
y,
a,
38 + rnd(i) * 18,
levels,
i + 1,
baseWidth
);
}
solidCore(core);