// Particles.pde (part of IsoBlox) // Dave Bollinger, Sep 2006 // http://www.davebollinger.com // for Processing 0115 Beta // (updated 08/16/2006 for 0125 Beta) interface Mover { boolean move(); } // This is perhaps the most inefficient way ever devised // to draw a box, but that is INTENTIONAL, ok? :-D // IsoMaker walks along the bottom edge of an iso block // and spawns IsoPainters that travel vertically upwards // to do the actual drawing. class IsoMaker implements Mover { static final int BLACK = 0xFF000000; static final int WHITE = 0xFFFFFFFF; int xo, yo, zo; // origin int xd, yd, zd; // dimensions int curx, cury, curz; // current location int curh1, curh2; // current vertical dimensions for painters int i; // current draw step int n; // number of draw steps color c0, c1, c2, c3; // fill colors: vertical edges, dark right wall, base left wall, light roof IsoMaker(int xo, int yo, int zo, int xd, int yd, int zd, float sat, float bri) { this.xo = xo; this.yo = yo; this.zo = zo; this.xd = xd; this.yd = yd; this.zd = zd; curx = xo - yd; cury = yo - yd/2; curz = zo*2; curh1 = zd; curh2 = 0; i = 0; n = yd + 2 + xd; c0 = BLACK; colorMode(HSB); c2 = color( random(256), sat, bri); colorMode(RGB); c1 = lerpColor(c2, BLACK, 0.25); c3 = lerpColor(c2, WHITE, 0.5); } boolean move() { if (i >= n) return false; if ((i==0) || (i==yd) || (i==yd+xd+1)) { // make an edger movers.add(new IsoPainter(curx,cury,curz+cury,curh1,curh2,c0,c3)); } else { // make a filler color c = (i < yd) ? c2 : c1; movers.add(new IsoPainter(curx,cury,curz+cury,curh1,curh2,c,c3)); } if ((i&1)==1) { if (i < yd) { curh2+=2; cury++; } else { cury--; } if (i > xd) { curh2-=2; } } curx++; i++; return true; } } class IsoPainter implements Mover { int x, y, z; // current location int h1; // height to near edge of roof, the wall height int h2; // height to far edge of roof, total draw length int i; // current draw stage (range 0..h2) color c1; // "wall" color color c2; // "roof" color boolean lastplotok; // did we successfully plot during last move? IsoPainter(int x, int y, int z, int h1, int h2, color c1, color c2) { this.x = x; this.y = y; this.z = z; this.h1 = h1; this.h2 = h1 + h2; // h2 passed in as just roof length, but stored as total length this.c1 = c1; this.c2 = c2; i = 0; lastplotok = false; } boolean move() { boolean thisplotok = false; // figure out color if ((i==0) || (i==h1) || (i==h2)) { // edges stroke(0); } else if (i < h1) { // lower wall fill stroke(c1); } else if (i < h2) { // upper roof fill stroke(c2); } else { // done! return false; } // attempt to plot this point if (thisplotok = zbuffer.set(x,y,z)) { point(x,y); } // attempt to recover some edges that might otherwise be missed: if (lastplotok && !thisplotok) { stroke(0); point(x,y); } lastplotok = thisplotok; // move if (i >= h1) z--; y--; i++; return true; } }