// 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; }