celly bunches[]; int cellmax = 200; int celln; BImage source; BImage buf; BFont mf; int bottom[]; float huefact; float satfact; float brifact; float redfact; float grnfact; float blufact; int srcoff; int bmouseX; int bmouseY; int peakX; boolean displaylayer; float rots; void setup() { size ( 400, 400 ); displaylayer= true; rots = 0; bunches = new celly[cellmax]; background(#000000); mf = loadFont ("Futura-Bold.vlw.gz"); textFont(mf, 16); source = loadImage("pollock.jpg"); buf = new BImage( width/2, height/2 ); for ( int i = 0; i < buf.width * buf.height ; i++ ) buf.pixels[i] = #000000; srcoff = ( buf.width - source.width )/2; buf.set ( srcoff, 0, source ); bottom = new int[source.width]; for ( int i = 0 ; i < source.width; i++ ) { bottom[i] = source.height-1; } huefact = 0; satfact = 0; brifact = 0; redfact = 0; grnfact = 0; blufact = 0; } void loop() { //if ( mousePressed ) { if ( celln < source.width * source.height ) { for ( int j = 0 ; j < source.width/4 ; j++ ) { int rx = int( random(source.width)); int ry = bottom[rx]--; if ( ry >= 0 ) { addcell (rx + srcoff, ry, source.get( rx, ry ) ) ; source.set( rx + srcoff, ry, #000000 ); } //} } } bmouseX = mouseX / 2; bmouseY = mouseY / 2; if ( bmouseY > 16 ) peakX = bmouseX; background(255); // image( buf, width/2, width/2, width/2, -width/2 ); //image ( buf, 0,0,width, height); strokeWeight(2.0); push(); translate ( 0, height , 1); rotateX ( rots ); translate ( 0, -height, 0 ); scale ( 2.0, 2.0, 2.0 ); if ( celln > 0 ) { for ( int i = 0 ; i < celln; i++ ) { // bunches[int( random(celln-1))].behave(); bunches[i].behave(); } } pop(); if ( displaylayer ) { displayUI(); } } void displayUI() { fill ( 128, 128, 128 , 128); text( "hue", 0, 16 ); text( "sat", 32, 16 ); text( "bri", 64, 16 ); text( "red", 96, 16 ); text( "grn", 128, 16 ); text( "blu", 160, 16 ); stroke ( 128, 128, 128 , 128); line ( 0 , 56 + 40 * huefact, 32 , 56 + 40 * huefact ); line ( 32 , 56 + 40 * satfact, 64 , 56 + 40 * satfact ); line ( 64 , 56 + 40 * brifact, 96 , 56 + 40 * brifact ); line ( 96 , 56 + 40 * redfact, 128 , 56 + 40 * redfact ); line ( 128 , 56 + 40 * grnfact, 160 , 56 + 40 * grnfact ); line ( 160 , 56 + 40 * blufact, 192 , 56 + 40 * blufact ); } void addcell(int x, int y, color col) { if ( celln == cellmax ) { cellmax = cellmax << 1; celly temp[] = new celly[cellmax]; System.arraycopy( bunches, 0, temp, 0, bunches.length ); bunches = temp; } bunches[celln++] = new celly ( x, y, col ); } boolean gempty( int x, int y ) { if ( source.get( x, y ) == #000000 ) return true; return false; } void keyPressed( ) { if ( key == 'd' ) { displaylayer = !displaylayer; } } void mousePressed( ) { float yval = ( mouseY > 16 ) ? (float)(mouseY - 56) / 40.0 : 0 ; if ( mouseX < 32 ) huefact = yval; else if ( mouseX < 64 ) satfact = yval; else if ( mouseX < 96 ) brifact = yval; else if ( mouseX < 128 ) redfact = yval; else if ( mouseX < 160 ) grnfact = yval; else if ( mouseX < 192 ) blufact = yval; else if ( mouseX < 224 ) rots = HALF_PI * yval; } class celly { int x; int y; color col; celly ( int x, int y, color col ) { this.x = x; this.y = y; this.col = col; buf.set( x, y ,col ); } void behave() { //fall down if ( y < bmouseY ) { if ( empty( 0, 1 ) ) { if ( empty( 1, 1 ) || empty( -1, 1 ) ) { move ( 0, 1 ); return; } } } else { int xr = int( random ( -2, 2 )); if ( empty ( xr, 1 ) ) { move ( xr, 1 ); return; } } if ( empty ( 1, 0 ) && empty ( 1, 1 ) && empty ( 1, 2 ) ) { move( 1, 2 ); return ; } if ( empty ( -1, 0 ) && empty ( -1, 1 ) && empty ( -1, 2 ) ) { move( -1, 2 ); return ; } if ( empty ( 0, -1 ) ) { if ( bmouseY < y ) { if ( peakX > x ) { if ( empty( 1, 0 ) ) { move ( 1, 0 ); return; } if ( empty( 1, -1 ) ) { move ( 1, -1 ); return; } } else if ( peakX < x ) { if ( empty( -1, 0 ) ) { move ( -1, 0); return; } if ( empty( -1, -1 ) ) { move ( -1, -1 ); return; } } } } if ( y <= bmouseY ) { if ( full( 1, 0 ) && full ( -1, 0 ) && full ( 0, -1 ) /* && full ( 1,-1 ) && full ( -1, -1 )*/ ) { int yd = 0; while ( yd < y && full ( 0, -yd ) ) yd++; if ( yd != y ) move ( 0, -yd ); } } if ( !empty ( 0, -1 ) ) { int up = -1; float myev = eval(col); while ( up > -x && !empty ( 0, up ) && eval ( look ( 0, up ) ) < myev ) up--; if ( up > -x && empty ( 0, up ) ) { move ( 0, up ); return; } } // if ( full ( 0 , 1 ) ) { // if ( red(look(0,1)) < red( look(0,0)) ) swap ( other ) ; // } } float eval ( color c ) { float ret = 0; if ( huefact != 0 ) ret += huefact * hue(c) ; if ( brifact != 0 ) ret += brifact * brightness(c); if ( satfact != 0 ) ret += satfact * saturation(c); if ( redfact != 0 ) ret += redfact * red(c); if ( grnfact != 0 ) ret += grnfact * green(c); if ( blufact != 0 ) ret += blufact * blue(c); return ret; } void move(int dx, int dy) { int px = max( 0, min( buf.width-1 , x+dx) ); int py = max( 0, min( buf.height-1, y+dy ) ); buf.set(x, y, #000000 ); stroke ( col ); line ( x, y, 0, px, py, 10 ); x = px; y = py; buf.set(x, y, col); } void swap(celly other) { int tx = other.x; int ty = other.y; other.x = x; other.y = y; x = tx; y = ty; buf.set( other.x, other.y, other.col ); buf.set( x, y, col ); } color look( int dx, int dy ) { int px = max( 0, min( buf.width-1 , x+dx) ); int py = max( 0, min( buf.height-1, y+dy ) ); return buf.get(px, py); } boolean full ( int dx, int dy ) { return !empty(dx,dy); } boolean empty( int dx, int dy ) { if ( x + dx < 0 || x + dx >= buf.width ) return false; if ( y + dy < 0 || y + dy >= buf.height ) return false; if ( look(dx, dy) == #000000 ) return true; return false; } }