ArrayList <Cell> cellsList;
float scalar = 1, scalarT = 1;
hint(DISABLE_DEPTH_TEST);
cellsList = new ArrayList<Cell>();
rootCell = new Cell(0, 300);
rXT = (mouseY-height*.5)*.01;
rYT = (mouseX-width*.5)*.01;
scalar = lerp(scalar, scalarT, .25);
translate(width*.5, height*.5);
boolean hasChildren, hasSeg;
ArrayList <CurveSeg> segs, cSegs;
Cell(int lv, float cellSize) {
this.cellSize = cellSize;
Cell(int lv, Vtx bd0, Vtx bd1, Vtx bd2, Vtx bd3, Vtx bd4, Vtx bd5, Vtx bd6, Vtx bd7) {
initBds(bd0, bd1, bd2, bd3, bd4, bd5, bd6, bd7);
segs = new ArrayList<CurveSeg>();
for (int i=cSegs.size ()-1; i>-1; i--) {
for (int i=cCells.size ()-1; i>-1; i--) {
for (int i=segs.size ()-1; i>-1; i--) {
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
bds[lyrIdx][rowIdx][colIdx].occupied = false;
segs = new ArrayList<CurveSeg>();
for (int i=0; i<2; i++) {
int sLyr = round(random(1))*2;
int sRow = round(random(1))*2;
int sCol = round(random(1))*2;
int eLyr = round(random(1))*2;
int eRow = round(random(1))*2;
int eCol = round(random(1))*2;
if ((sLyr == eLyr && sRow == eRow && sCol == eCol) ||
(sLyr != eLyr && sRow != eRow && sCol != eCol) ||
(bds[sLyr][sRow][sCol].occupied || bds[eLyr][eRow][eCol].occupied)) {
bds[sLyr][sRow][sCol].occupied = true;
bds[eLyr][eRow][eCol].occupied = true;
CurveSeg initSeg = new CurveSeg(bds[sLyr][sRow][sCol], bds[eLyr][eRow][eCol]);
initSeg.setV1Indices(sLyr, sRow, sCol);
initSeg.setV2Indices(eLyr, eRow, eCol);
int [] ctlIndices = initSeg.ctlIndices();
initSeg.setCtls(bds[ctlIndices[0]][ctlIndices[1]][ctlIndices[2]], bds[ctlIndices[3]][ctlIndices[4]][ctlIndices[5]]);
void addSeg(CurveSeg seg) {
for (int l=0; l<2; l++) {
for (int m=0; m<2; m++) {
for (int n=0; n<2; n++) {
if (seg.acr1 == bds[l*interval][m*interval][n*interval])seg.setV1Indices(l*interval, m*interval, n*interval);
else if (seg.acr2 == bds[l*interval][m*interval][n*interval])seg.setV2Indices(l*interval, m*interval, n*interval);
int [] ctlIndices = seg.ctlIndices();
seg.setCtls(bds[ctlIndices[0]][ctlIndices[1]][ctlIndices[2]], bds[ctlIndices[3]][ctlIndices[4]][ctlIndices[5]]);
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
bds[lyrIdx][rowIdx][colIdx] = new Vtx(new PVector(0, 0, 0), new PVector(cellSize*(-.5+k), cellSize*(-.5+j), cellSize*(.5-i)), 0);
void initBds(Vtx bd0, Vtx bd1, Vtx bd2, Vtx bd3, Vtx bd4, Vtx bd5, Vtx bd6, Vtx bd7) {
bds[0][0][interval] = bd1;
bds[0][interval][interval] = bd2;
bds[0][interval][0] = bd3;
bds[interval][0][0] = bd4;
bds[interval][0][interval] = bd5;
bds[interval][interval][interval] = bd6;
bds[interval][interval][0] = bd7;
PVector itpPos(Vtx v1, Vtx v2, float ratio) {
PVector result = new PVector(
v1.acr.x*ratio + v2.acr.x*(1-ratio),
v1.acr.y*ratio + v2.acr.y*(1-ratio),
v1.acr.z*ratio + v2.acr.z*(1-ratio)
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
for (int k=0; k<3; k++) {
if (k==1 && i!=1 && j!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i][j][k-1], bds[i][j][k+1], random(1)), itpPos(bds[i][j][k-1], bds[i][j][k+1], .5), lv);
} else if (i==1 && k!=1 && j!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i-1][j][k], bds[i+1][j][k], random(1)), itpPos(bds[i-1][j][k], bds[i+1][j][k], .5), lv);
} else if (j==1 && k!=1 && i!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i][j-1][k], bds[i][j+1][k], random(1)), itpPos(bds[i][j-1][k], bds[i][j+1][k], .5), lv);
} else if (i==1 && j==1 && k!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i-1][j-1][k], bds[i+1][j+1][k], random(1)), itpPos(bds[i-1][j-1][k], bds[i+1][j+1][k], .5), lv);
} else if (i==1 && k==1 && j!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i-1][j][k-1], bds[i+1][j][k+1], random(1)), itpPos(bds[i-1][j][k-1], bds[i+1][j][k+1], .5), lv);
} else if (j==1 && k==1 && i!=1) {
bds[i][j][k] = new Vtx(itpPos(bds[i][j-1][k-1], bds[i][j+1][k+1], random(1)), itpPos(bds[i][j-1][k-1], bds[i][j+1][k+1], .5), lv);
} else if (i==1 && j==1 && k==1) {
bds[i][j][k] = new Vtx(itpPos(bds[i-1][j-1][k-1], bds[i+1][j+1][k+1], random(1)), itpPos(bds[i-1][j-1][k-1], bds[i+1][j+1][k+1], .5), lv);
cCells = new ArrayList<Cell>();
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
Cell cCell = new Cell(lv+1, bds[i][j][k], bds[i][j][k+1], bds[i][j+1][k+1], bds[i][j+1][k], bds[i+1][j][k], bds[i+1][j][k+1], bds[i+1][j+1][k+1], bds[i+1][j+1][k]);
for (int i=0; i<cSegs.size (); i++) {
CurveSeg cSeg = cSegs.get(i);
int randIndex = floor(random(cCells.size()));
Cell randCCell = cCells.get(randIndex);
for (int l=0; l<2; l++) {
for (int m=0; m<2; m++) {
for (int n=0; n<2; n++) {
if (v1 == randCCell.bds[l*interval][m*interval][n*interval]) matched++;
else if (v2 == randCCell.bds[l*interval][m*interval][n*interval]) matched++;
} else if (iterations == 100) {
cSegs = new ArrayList<CurveSeg>();
for (int i=segs.size ()-1; i>-1; i--) {
CurveSeg seg = segs.get(i);
int [] sNbBound = nbRandBd(seg.sLyr, seg.sRow, seg.sCol);
int [] eNbBound = nbRandBd(seg.eLyr, seg.eRow, seg.eCol);
if (sNbBound[0] == eNbBound[0] && sNbBound[1] == eNbBound[1] && sNbBound[2] == eNbBound[2]) {
bds[sNbBound[0]][sNbBound[1]][sNbBound[2]].occupied = true;
CurveSeg cSeg1 = new CurveSeg(seg.acr1, bds[sNbBound[0]][sNbBound[1]][sNbBound[2]]);
CurveSeg cSeg2 = new CurveSeg(bds[sNbBound[0]][sNbBound[1]][sNbBound[2]], seg.acr2);
bds[sNbBound[0]][sNbBound[1]][sNbBound[2]].occupied = true;
bds[1][1][1].occupied = true;
bds[eNbBound[0]][eNbBound[1]][eNbBound[2]].occupied = true;
CurveSeg cSeg1 = new CurveSeg(seg.acr1, bds[sNbBound[0]][sNbBound[1]][sNbBound[2]]);
CurveSeg cSeg2 = new CurveSeg(bds[sNbBound[0]][sNbBound[1]][sNbBound[2]], bds[1][1][1]);
CurveSeg cSeg3 = new CurveSeg(bds[1][1][1], bds[eNbBound[0]][eNbBound[1]][eNbBound[2]]);
CurveSeg cSeg4 = new CurveSeg(bds[eNbBound[0]][eNbBound[1]][eNbBound[2]], seg.acr2);
int [] nbRandBd(int lyrIdx, int rowIdx, int colIdx) {
int nxtLyrIdx = 0, nxtRowIdx = 0, nxtColIdx = 0;
if (lyrIdx == 0) nxtLyrIdx = lyrIdx + round(random(1));
else if (lyrIdx == interval) nxtLyrIdx = lyrIdx - round(random(1));
if (rowIdx == 0) nxtRowIdx = rowIdx + round(random(1));
else if (rowIdx == interval) nxtRowIdx = rowIdx - round(random(1));
if (colIdx == 0) nxtColIdx = colIdx + round(random(1));
else if (colIdx == interval) nxtColIdx = colIdx - round(random(1));
if ((lyrIdx == nxtLyrIdx && rowIdx == nxtRowIdx && colIdx == nxtColIdx) ||
(lyrIdx != nxtLyrIdx && rowIdx != nxtRowIdx && colIdx != nxtColIdx)||
(bds[nxtLyrIdx][nxtRowIdx][nxtColIdx].occupied)) {
nxtLyrIdx, nxtRowIdx, nxtColIdx
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
bds[lyrIdx][rowIdx][colIdx].update();
for (int i=0; i<cCells.size (); i++) {
Cell cCell = cCells.get(i);
for (int i=0; i<cCells.size (); i++) {
Cell cCell = cCells.get(i);
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
if (k<1) drawEdge(bds[lyrIdx][rowIdx][colIdx], bds[lyrIdx][rowIdx][colIdx+interval]);
if (j<1) drawEdge(bds[lyrIdx][rowIdx][colIdx], bds[lyrIdx][rowIdx+interval][colIdx]);
if (i<1) drawEdge(bds[lyrIdx][rowIdx][colIdx], bds[lyrIdx+interval][rowIdx][colIdx]);
for (int i=0; i<segs.size (); i++) {
CurveSeg seg = segs.get(i);
void drawEdge(Vtx v1, Vtx v2) {
line(v1.pos.x, v1.pos.y, v1.pos.z, v2.pos.x, v2.pos.y, v2.pos.z);
Cell randCell = cellsList.get(floor(random(cellsList.size())));
if (!randCell.hasChildren && randCell.hasSeg && randCell.lv<maxLv) {
randCell.spawnChildren();
} else if (iterations == 100) {
Vtx acr1, acr2, ctl1, ctl2;
int sLyr, sRow, sCol, eLyr, eRow, eCol;
CurveSeg(Vtx acr1, Vtx acr2){
void setCtls(Vtx ctl1, Vtx ctl2){
void setV1Indices(int sLyr, int sRow, int sCol){
void setV2Indices(int eLyr, int eRow, int eCol){
int [] result = new int[]{};
if(sLyr == eLyr && sRow == eRow){
if(boolean(round(random(1)))){
result = new int[]{(sLyr+2)%4, sRow, sCol, (eLyr+2)%4, eRow, eCol};
result = new int[]{sLyr, (sRow+2)%4, sCol, eLyr, (eRow+2)%4, eCol};
}else if(sLyr == eLyr && sCol == eCol){
if(boolean(round(random(1)))){
result = new int[]{(sLyr+2)%4, sRow, sCol, (eLyr+2)%4, eRow, eCol};
result = new int[]{sLyr, sRow, (sCol+2)%4, eLyr, eRow, (eCol+2)%4};
}else if(sRow == eRow && sCol == eCol){
if(boolean(round(random(1)))){
result = new int[]{sLyr, (sRow+2)%4, sCol, eLyr, (eRow+2)%4, eCol};
result = new int[]{sLyr, sRow, (sCol+2)%4, eLyr, eRow, (eCol+2)%4};
if(boolean(round(random(1)))){
result = new int[]{sLyr, (sRow+2)%4, sCol, sLyr, (sRow+2)%4, sCol};
result = new int[]{sLyr, sRow, (sCol+2)%4, sLyr, sRow, (sCol+2)%4};
if(boolean(round(random(1)))){
result = new int[]{(sLyr+2)%4, sRow, sCol, (sLyr+2)%4, sRow, sCol};
result = new int[]{sLyr, sRow, (sCol+2)%4, sLyr, sRow, (sCol+2)%4};
if(boolean(round(random(1)))){
result = new int[]{(sLyr+2)%4, sRow, sCol, (sLyr+2)%4, sRow, sCol};
result = new int[]{sLyr, (sRow+2)%4, sCol, sLyr, (sRow+2)%4, sCol};
bezier(acr1.pos.x, acr1.pos.y, acr1.pos.z,
ctl1.pos.x*ratio+acr1.pos.x*(1-ratio),ctl1.pos.y*ratio+acr1.pos.y*(1-ratio), ctl1.pos.z*ratio+acr1.pos.z*(1-ratio),
ctl2.pos.x*ratio+acr2.pos.x*(1-ratio), ctl2.pos.y*ratio+acr2.pos.y*(1-ratio), ctl2.pos.z*ratio+acr2.pos.z*(1-ratio),
acr2.pos.x, acr2.pos.y, acr2.pos.z);
Vtx(PVector initPos, PVector acr, int lv){
this.acr = new PVector(acr.x, acr.y, acr.z);
tgt = new PVector(acr.x, acr.y, acr.z);
pos = new PVector(initPos.x, initPos.y, initPos.z);
vel = new PVector(0, 0, 0);
acc = new PVector(0, 0, 0);
decay = random(0.8, 0.9);
acc = PVector.sub(tgt, pos);
} else if ( key == '2') {
for (int i=cellsList.size ()-1; i>-1; i--) {
Cell eachCell = cellsList.get(i);
if (eachCell != rootCell)cellsList.remove(i);
scalarT = constrain(scalarT, .25, 5);
scalarT = constrain(scalarT, .25, 5);