createCanvas(800, 800, WEBGL);
colorMode(HSB, 360, 100, 100, 100);
palette = shuffle(chromotome.get().colors);
ortho(-width / 4, width / 4, -height / 4, height / 4, -5000, 5000);
cos(theta_a) * cos(theta_b) * cr,
cos(theta_a) * sin(theta_b) * cr,
if (frameCount % 200 == 0) {
palette = shuffle(chromotome.get().colors);
randomSeed(frameCount / 200);
for (let y = 0; y < grid_len; y++) {
for (let x = 0; x < grid_len; x++) {
directionalLight(color(0, 0, 80), 1, 0, -1);
directionalLight(color(0, 0, 30), -1, 0, -1);
directionalLight(color(0, 0, 50), 0, 1, 0);
translate(0, height / 4, 0);
for (let i = 0; i < 250; i++) {
let cir = createCircle(0, 100);
let arr = getGridCircles(cir);
for (let p = 0; p < arr.length; p++) {
let len = dist(cir.x, cir.y, 0, c.x, c.y, 0) - c.l;
arr = getGridCircles(cir);
if (retry && retryCount < 100) {
this.xRes = int(random(5, 10));
this.yRes = int(random(5, 10));
this.color = shuffle(palette.concat());
this.num = int(random(2, 6));
let h = noise(this.x, this.y, frameCount / 100) * this.h * 2;
translate(this.x - width / 2, -h / 2, this.y - height / 2);
for (let i = 1; i <= this.num; i++) {
fill(this.color[i % this.color.length]);
cylinder((this.l * i) / this.num, h, 64, 1, false, false);
function createCircle(minL = 10, maxL = 80) {
return new Circle(random(0, width), random(0, height), random(minL, maxL));
return constrain(int(x / grid[0].length), 0, grid[0].length - 1);
return constrain(int(y / grid.length), 0, grid.length - 1);
function getGridCircles(cir) {
arr = arr.concat(grid[gridY(cir.y)][gridX(cir.x)]);
let x1 = gridX(cir.x - cir.l),
x2 = gridX(cir.x + cir.l);
let y1 = gridY(cir.y - cir.l),
y2 = gridY(cir.y + cir.l);
for (let y = y1; y <= y2; y++) {
for (let x = x1; x <= x2; x++) {
arr = arr.concat(grid[y][x]);
function gridAddCircle(cir) {
let x1 = gridX(cir.x - cir.l),
x2 = gridX(cir.x + cir.l);
let y1 = gridY(cir.y - cir.l),
y2 = gridY(cir.y + cir.l);
for (let y = y1; y <= y2; y++) {
for (let x = x1; x <= x2; x++) {