// Life3D
// Dave Bollinger, Oct 2006
// http://www.davebollinger.com
// for Processing 0119 Beta
/**
Press 'u' to toggle auto-update
Press 's' to step update once (when auto-update is off)
Press 'r' to toggle auto-rotate
Press space to reseed randomly
Press '1'..'0' to set box size from small..large
*/
int [][][] cellsA; // cell storage
int [][][] cellsB; // cell storage
int [][][] currgen; // reference to the current generation of cells
int [][][] nextgen; // reference to the next generation of cells
int [] rgbs; // to store precalculated rgb values within cube
static final int DEAD = 0; // cell state constant
static final int ALIVE = 1; // cell state constant
static final int N = 16; // dimensions of cell array
static final float M = N / 2.0f; // half of N
static final float SCALE = 150.0f / N; // overall scaling of coordinates to fit display
float boxsize = 0.7f * SCALE; // size of box as percentage of scale
float rotx = 0.0f; // x rotation
float roty = 0.0f; // y rotation
float density = 0.01f; // density of 1's when random seeding
int ticks = 0; // a frame counter
static final int TICKS_PER_UPDATE = 15; // update the ca after this many ticks
boolean autoUpdate = true; // automatically update the ca after specified number of ticks
boolean autoRotate = true; // automatically rotate the display each frame
// These values define the "rules" for a particular variant of life.
// Given 26 possible neighbors..
int birthlo = 3; // born when neighbors >= birthlo
int birthhi = 3; // born when neighbors <= birthhi
int deathlo = 2; // dies when neighbors < deathlo
int deathhi = 3; // dies when neighbors > deathhi
void setup() {
size(300, 300, P3D); // or OPENGL
frameRate(30);
sphereDetail(8);
currgen = cellsA = new int[N][N][N];
nextgen = cellsB = new int[N][N][N];
rgbs = new int[N];
for (int i=0; i TICKS_PER_UPDATE) {
updateLife();
ticks = 0;
}
}
}
void drawLife() {
background(0);
translate(width/2.0f, height/2.0f, 0f);
directionalLight(255, 255, 255, 0.5f, 0.5f, -0.5f);
directionalLight(255, 255, 255, 0.5f, 0.5f, -0.5f);
rotateX(rotx);
rotateY(roty);
noStroke();
for (int z=0; z=birthlo) && (sum<=birthhi))
result = ALIVE;
} else {
if ((sumdeathhi))
result = DEAD;
}
nextgen[z][y][x] = result;
nalive += result;
}
}
}
int [][][] temp = currgen;
currgen = nextgen;
nextgen = temp;
// if (nalive == 0)
// reseed();
// nope, decided to let user do this on their own so they can "see" the death
}
int neighbors(int x, int y, int z) {
int zm1 = (z+N-1) % N;
int zp1 = (z+1) % N;
int ym1 = (y+N-1) % N;
int yp1 = (y+1) % N;
int xm1 = (x+N-1) % N;
int xp1 = (x+1) % N;
int [][] czm1 = currgen[zm1];
int [][] czoo = currgen[z];
int [][] czp1 = currgen[zp1];
int sum = czm1[ym1][xm1] + czm1[ym1][x] + czm1[ym1][xp1] +
czm1[y][xm1] + czm1[y][x] + czm1[y][xp1] +
czm1[yp1][xm1] + czm1[yp1][x] + czm1[yp1][xp1] +
czoo[ym1][xm1] + czoo[ym1][x] + czoo[ym1][xp1] +
czoo[y][xm1] + + czoo[y][xp1] +
czoo[yp1][xm1] + czoo[yp1][x] + czoo[yp1][xp1] +
czp1[ym1][xm1] + czp1[ym1][x] + czp1[ym1][xp1] +
czp1[y][xm1] + czp1[y][x] + czp1[y][xp1] +
czp1[yp1][xm1] + czp1[yp1][x] + czp1[yp1][xp1];
return sum;
}