let cool1 = "https://coolors.co/c2efb3-97abb1-746f72-735f3d-594a26".split("/").pop().split("-").map((a) => "#" + a);
let cool11 = "https://coolors.co/f1fbee-c5d0d3-a5a1a4-b2986c-9d8243".split("/").pop().split("-").map((a) => "#" + a);
let cool2 = "https://coolors.co/e2dadb-dae2df-a2a7a5-6d696a-ffffff".split("/").pop().split("-").map((a) => "#" + a);
let cool21 = "https://coolors.co/f6f4f4-f4f6f5-cacecc-9b9798-c2c2c2".split("/").pop().split("-").map((a) => "#" + a);
let cool3 = "https://coolors.co/a63446-fbfef9-0c6291-000004-7e1946".split("/").pop().split("-").map((a) => "#" + a);
let cool31 = "https://coolors.co/ce6474-d0f3b9-129ae2-000066-cc2872".split("/").pop().split("-").map((a) => "#" + a);
let x, y, xp, yp, xx, yy;
let traceCubeLines = false;
seed = int(Math.random() * 9999999);
createCanvas(iw, iw / ar);
createCanvas(ih * ar, ih);
let rwis = wisW / sizeMod;
col1 = random([cool1, cool2, cool3]);
col2 = random([cool11, cool21, cool31]);
applyMonochromaticGrain(gS);
customLayout = generateRandomLayout();
for (let i = 0; i < customLayout.length; i++) {
let { x, y } = customLayout[i];
let cubeColor = color(random(col1));
let tesseract = new Tesseract(x, y, _size, cubeColor, sizeMod);
tesseracts.push(tesseract);
cascadeBand = new CascadeBand(tesseracts);
for (let tesseract of tesseracts) {
function generateRandomLayout() {
let numRows = random(2, 6);
let numCols = random(2, 6);
let tesseractSize = _size * sizeMod;
let colSpacing = width / (numCols + 1);
let rowSpacing = height / (numRows + 1);
let xOffset = colSpacing / 2;
let yOffset = rowSpacing / 2;
for (let row = 0; row < numRows; row++) {
for (let col = 0; col < numCols; col++) {
let x = col * colSpacing + random(-xOffset, xOffset);
let y = row * rowSpacing + random(-yOffset, yOffset);
layout.push({ x, y, connected: false });
for (let i = 0; i < layout.length; i++) {
let connectedCubes = [cube];
for (let j = i + 1; j < layout.length; j++) {
let otherCube = layout[j];
if (!otherCube.connected && areCubesConnected(cube, otherCube)) {
connectedCubes.push(otherCube);
otherCube.connected = true;
if (connectedCubes.length === 4) {
if (connectedCubes.length === 4) {
alignCubesToHypercube(connectedCubes, tesseractSize);
function areCubesConnected(cube1, cube2) {
let distanceThreshold = 1.5;
let distance = dist(cube1.x, cube1.y, cube2.x, cube2.y);
return distance <= distanceThreshold;
function alignCubesToHypercube(cubes, tesseractSize) {
let centerX = (cubes[0].x + cubes[1].x + cubes[2].x + cubes[3].x) / 4;
let centerY = (cubes[0].y + cubes[1].y + cubes[2].y + cubes[3].y) / 4;
for (let i = 0; i < cubes.length; i++) {
let angle = i * (360 / cubes.length);
let x = centerX + cos(angle) * tesseractSize;
let y = centerY + sin(angle) * tesseractSize;
function drawTessClass() {
let rwis = wisW / sizeMod;
let offsetY = _size / 2 * sizeMod;
for (let i = 0; i < rwis; i++) {
for (let j = 0; j < rwis; j++) {
let x = i * _size * sizeMod/2;
let y = j * _size * sizeMod/2;
let cubeColor = color(random(col1));
let tesseract = new Tesseract(x, y, _size, cubeColor, sizeMod);
constructor(tesseracts) {
this.tesseracts = tesseracts;
this.currentPos = createVector(width / 2, 0);
this.targetPos = createVector(0, 0);
let currentCube = this.tesseracts[this.currentIndex];
this.targetPos = createVector(currentCube.outerCube.x, currentCube.outerCube.y);
let distance = p5.Vector.dist(this.currentPos, this.targetPos);
let direction = p5.Vector.sub(this.targetPos, this.currentPos).normalize();
let speed = 0.01 * distance;
this.currentPos.add(direction.mult(speed));
let cubeTop = currentCube.outerCube.y - currentCube.outerCube._size / 2;
let cubeBottom = currentCube.outerCube.y + currentCube.outerCube._size / 2;
if (this.currentPos.y < cubeBottom) {
this.currentPos.y = cubeBottom;
this.currentIndex = (this.currentIndex + 1) % this.tesseracts.length;
currentCube = this.tesseracts[this.currentIndex];
this.tracePoints.push(this.currentPos.copy());
for (let i = 0; i < this.tracePoints.length; i++) {
vertex(this.tracePoints[i].x, this.tracePoints[i].y);
constructor(x, y, _size, fillCol, sizeMod) {
this.outerCube = new Cube(x, y, _size, fillCol, sizeMod);
this.innerCube = new Cube(x + _size / random(0, 2.5) * sizeMod, y + _size / random(0, 2.5) * sizeMod, _size / random(0, 2.5), fillCol, sizeMod);
let outerVertices = this.outerCube.getVertices();
let innerVertices = this.innerCube.getVertices();
for(let i = 0; i < outerVertices.length; i++) {
let [x1, y1] = outerVertices[i];
let [x2, y2] = innerVertices[i];
let dx = Math.cos(this.frame / 20) * 10;
let dy = Math.sin(this.frame / 20) * 10;
function drawClassCubes() {
let rwis = wisW / sizeMod;
let offsetY = _size / 2 * sizeMod;
for (let i = 0; i < rwis; i++) {
for (let j = 0; j < rwis; j++) {
let x = i * _size * sizeMod;
let y = j * _size * sizeMod;
let cubeColor = color(random(col1));
let cube = new Cube(x, y, _size, cubeColor, sizeMod);
let vertices = cube.getVertices();
console.log(cube.getVertices());
constructor(x, y, _size, fillCol, sizeMod) {
this._size = _size * sizeMod;
translate(this.x, this.y);
} else if (nosColor == true) {
quad(0, 0, this._size / 2, this._size / 4, 0, this._size / 2, -this._size / 2, this._size / 4);
quadraticVertex(0, 0, this._size / 2, this._size / 4);
quadraticVertex(0, this._size / 2, -this._size / 2, this._size / 4);
quadraticVertex(this._size / 4, 0, 0, this._size / 2);
translate(this._size / 4, 0);
let showPosX = "x:" + round((this.x + Number.EPSILON) * 1000) / 1000;
let showPosY = "y:" + round((this.y + Number.EPSILON) * 1000) / 1000;
text(showPosX, -this._size / 2, this._size / 4);
text(showPosY, -this._size / 2, this._size / 3);
for (let ll = 0; ll < this._size; ll += this._size / 3) {
drawingContext.setLineDash([5, 15, 25, 2, 12, 100]);
line(-this._size / 2, (this._size / 4) + ll / 2, 0, (this._size / 2) + ll / 2);
vertex(-this._size / 2, this._size / 4);
vertex(0, this._size / 2);
vertex(-this._size / 2, this._size / 4 * 3);
curveVertex(-this._size / 2, this._size / 4);
curveVertex(0, this._size / 2);
curveVertex(0, this._size);
curveVertex(-this._size / 2, this._size / 4 * 3);
for (let l = 0; l < this._size; l += this._size / 5) {
drawingContext.setLineDash([3, 5, 15]);
line(0, (this._size / 2) + l / 2, this._size / 2, (this._size / 4) + l / 2);
vertex(this._size / 2, this._size / 4);
vertex(0, this._size / 2);
vertex(this._size / 2, this._size / 4 * 3);
curveVertex(this._size / 2, this._size / 4);
curveVertex(0, this._size / 2);
curveVertex(0, this._size);
curveVertex(this._size / 2, this._size / 4 * 3);
if (traceCubeLines == true) {
if (xp !== null && yp !== null) {
strokeWeight(random(0.015, 0.075) * m);
drawingContext.setLineDash([0, 3, 0, 2, 1]);
line(0, 0, xp - this.x, yp - this.y);
line(this._size / 2, this._size / 4, xp - this.x + this._size / 2, yp - this.y + this._size / 4);
drawingContext.setLineDash([1, 0, 3, 1, 2]);
random() < 0.1 ? line(0, xp - this.x, 0, yp - this.y) : null;
[this.x + this._size / 2, this.y + this._size / 4],
[this.x, this.y + this._size / 2],
[this.x - this._size / 2, this.y + this._size / 4],
[this.x - this._size / 2, this.y + this._size * 3/4],
[this.x, this.y + this._size],
[this.x + this._size / 2, this.y + this._size * 3/4],
[this.x, this.y + this._size / 2],
saveCanvas('cubes_tess_f' + floor(random(100)), 'png');