let t = (frameCount%N_FRAMES)/N_FRAMES;
function createCompo(t) {
let nCorners = 4, r = 150, thetaStep = TAU/nCorners;
let theta0 = t*TAU/nCorners;
for (let i = 0; i < nCorners; i++) {
let x1 = width/2 + r*cos(i*thetaStep+theta0);
let y1 = height/2 + r*sin(i*thetaStep+theta0);
let x2 = width/2 + r*cos((i+1)*thetaStep+theta0);
let y2 = height/2 + r*sin((i+1)*thetaStep+theta0);
for (let j = 0; j < nPoints; j++) {
points.push({x: x, y: y});
contains: [...Array(points.length).keys()]
function subdivide({x: x, y: y, w: w, h: h, contains: contains}, horizontally) {
let rectangle1, rectangle2;
let w1 = random(w/4, 3*w/4), w2 = w-w1;
rectangle1 = {x: x1, y: y, w: w1, h: h, contains: []};
rectangle2 = {x: x2, y: y, w: w2, h: h, contains: []};
let h1 = random(h/4, 3*h/4), h2 = h-h1;
rectangle1 = {x: x, y: y1, w: w, h: h1, contains: []};
rectangle2 = {x: x, y: y2, w: w, h: h2, contains: []};
for (let idx of contains) {
if (pointInRectangle(points[idx], rectangle1)) rectangle1.contains.push(idx);
else rectangle2.contains.push(idx);
if (rectangle1.contains.length > 1) subdivide(rectangle1, !horizontally);
else rect(rectangle1.x, rectangle1.y, rectangle1.w, rectangle1.h);
if (rectangle2.contains.length > 1) subdivide(rectangle2, !horizontally);
else rect(rectangle2.x, rectangle2.y, rectangle2.w, rectangle2.h);
function pointInRectangle({x: px, y: py}, {x: rx, y: ry, w: rw, h: rh}) {
return px > rx && px < rx+rw && py > ry && py < ry+rh;