int dimx = 500; int dimy = 500; float inc = 0.00; float porosity = 2.0; float maxarea = 160; float xmax, xmin, ymax, ymin; float vwx, vwy, vwscale; float locMX; float locMY; float flux = 0; BFont mFont; String message = "there aren't enough cookies in the cookie jar to fill your evil heart."; Cell mc; int cellnum; int cellmax = 80; Cell cells[] = new Cell[cellmax]; void setup () { size(500,500); background(0); rectMode(CORNER); stroke( 255, 255,255, 128 ); fill ( 128, 192, 96, 128 ); mFont = loadFont ( "Base_5.vlw" ); textFont(mFont, 18); cells[0] = new Cell ( 5, 0, -5, 0 , 11, 9 , 10 ); cellnum = 1; framerate ( 30 ) ; smooth(); vwx = 10; vwy = 0; vwscale = 20; } void loop () { background(64); translate ( dimx/2, dimy/2 ); scale ( vwscale, vwscale, vwscale ); translate( - vwx, - vwy ); if ( !mousePressed ) { flux = 10; cells[0].transferLower ( flux ); } cells[0].distribute(); for ( int i = 0; i < cellnum ; i++ ) cells[i].renderLit(); rescale(); } void rescale() { if ( mousePressed ) { vwx += 0.1 * ( locMX - vwx ); vwy += 0.1 * ( locMY - vwy ); vwscale *= 1.001; } else { vwx += 0.1 * ( 0.5 * ( xmin + xmax ) - vwx ); vwy += 0.1 * ( 0.5 * ( ymin + ymax ) - vwy ); float tscale = 0.45 * dimx / ( 10 + 0.5 * max ( xmax - xmin, ymax - ymin ) ); vwscale += 0.1 * ( tscale - vwscale ); } locMX = vwx + ( mouseX - dimx/2 ) / vwscale ; locMY = vwy + ( mouseY - dimy/2 ) / vwscale ; xmin = 0; xmax = 0; ymin = 0; ymax = 0; } float len ( float x, float y, float x2, float y2 ) { float dx = x2 - x; float dy = y2 - y; return sqrt( dx*dx + dy*dy ); } class Cell { float lh, rh; float topw, basew; float rx, ry, lx, ly; float brx,bry,blx,bly; int tchild; int lchild; int rchild; float age; float rsun, lsun; Cell (float x1, float y1, float x2, float y2, float lH, float rH, float tW) { setbase(x1,y1,x2,y2 ); lh = lH; rh = rH; topw = tW; tchild = 0; lchild = 0; rchild = 0; reshape(); } void reshape() { boolean isLeft = ( lh < rh ); float diagonal, lesser, greater; float arc1, arc2; if ( isLeft ) { lesser = lh; greater = rh; } else { lesser = rh; greater = lh; } diagonal = sqrt ( lesser*lesser + topw *topw ); arc1 = atan2 ( topw, lesser ); float cosC = - ( greater*greater - ( diagonal* diagonal + basew * basew ) ) / ( 2.0 * diagonal * basew) ; arc2 = float ( Math.acos ( cosC ) ); // println ( "basew " + basew + " topw is " + topw + " rh " + rh + " lh " + lh ); // println ( "diagonal is " + diagonal + " arc1 is " + arc1 + " and arc2 is " + arc2 ); // println ( "convex is " + isConvex() ); if ( isLeft ) { //left side float bAng = atan2( bry - bly, brx - blx ); float lAng = bAng + ( arc1 + arc2 ) ; lx = blx + lh * cos( lAng ); ly = bly + lh * sin( lAng ); rx = lx + topw * cos ( lAng - HALF_PI ); ry = ly + topw * sin ( lAng - HALF_PI ); } else { //right side float bAng = atan2( bly - bry, blx - brx ); float rAng = bAng - ( arc1 + arc2 ); rx = brx + rh * cos( rAng ); ry = bry + rh * sin( rAng ); lx = rx + topw * cos ( rAng + HALF_PI ); ly = ry + topw * sin ( rAng + HALF_PI ); } if ( tchild > 0 ) cells[tchild].setbase ( lx, ly, rx, ry ); if ( rchild > 0 ) cells[rchild].setbase ( rx, ry , brx, bry ); if ( lchild > 0 ) cells[lchild].setbase ( blx, bly, lx, ly ); } float expose( float x, float y, float x2, float y2) { float ld = len ( x, y, locMX, locMY ); float sd = len ( x, y, x2, y2 ); float dsx = locMX - x; float dsy = locMY - y; if ( ld != 0 ) { dsx /= ld; dsy /= ld; } float dx = x2 - x; float dy = y2 - y; if ( sd != 0 ) { dx /= sd; dy /= sd; } float dp = dsx * dy - dsy * dx ; return max ( 0, 255 * dp / max ( 1.0, (0.001 * ld*ld) ) ); } void distribute() { age += 0.02; rsun = expose( brx, bry, rx, ry ); lsun = expose( lx, ly, blx, bly ); if ( !mousePressed ) { setR( rh * (1.0 - 0.00002 * rsun) ); setL( lh * (1.0 - 0.00002 * lsun) ); } reshape(); float ar = area(); if ( flux < 1 ) { float xper = ( rh + topw + lh + basew) / 4.0; float factor = 0.02; float rhd = min ( factor, max ( -factor , xper - rh ) ); float lhd = min ( factor, max ( -factor , xper - lh ) ); if ( lh < rh ) { setR( rh + rhd ); setT( topw - rhd ); } else if ( lh < rh ) { setL( lh + lhd ); setT( topw - lhd ); } } else if ( ar >= basew*basew ) { float diff = ar - basew * basew; if ( tchild == 0 ) { tchild = cellnum++; if ( cellnum == cellmax ) { cellmax = cellmax << 1; Cell temp[] = new Cell[cellmax]; System.arraycopy( cells, 0, temp, 0, cells.length ); cells = temp; } cells[tchild] = new Cell ( lx, ly, rx, ry , 0.01 , 0.01 , topw ); if ( max (rsun, lsun) > 220.0 ) { if ( ++cellnum == cellmax ) { cellmax = cellmax << 1; Cell temp[] = new Cell[cellmax]; System.arraycopy( cells, 0, temp, 0, cells.length ); cells = temp; } if ( rsun > lsun ) { rchild = cellnum-1; cells[rchild] = new Cell ( rx, ry, brx, bry, 2.0, 2.0, rh ); } else { lchild = cellnum-1; cells[lchild] = new Cell ( blx, bly , lx, ly, 2.0,2.0, lh ); } } } if ( tchild > 0 || rchild > 0 || lchild > 0 ) { float tsurf = ( tchild > 0 ) ? topw : 0 ; //tsurf += ( rchild > 0 ) ? rh : 0 ; //tsurf += ( lchild > 0 ) ? lh : 0 ; float transfer = min ( ar - basew*basew , tsurf * porosity ); if ( tchild > 0 ) { transferUpper( -transfer * (topw/tsurf)); cells[tchild].transferLower( transfer * ( topw/tsurf ) ); } if ( rchild > 0 ) { //transferRight( -transfer * (rh / tsurf)); cells[rchild].transferLower( transfer * ( rh / tsurf ) ); } if ( lchild > 0 ) { //transferLeft( -transfer * (lh / tsurf)); cells[lchild].transferLower( transfer * ( lh / tsurf ) ); } } } reshape(); if ( tchild > 0 ) cells[tchild].distribute(); if ( rchild > 0 ) cells[rchild].distribute(); if ( lchild > 0 ) cells[lchild].distribute(); } float area() { float greater, lesser ; if ( rh >= lh ) { greater= rh; lesser = lh ; } else { lesser = rh; greater = lh; } float a1 = 0.5 * lesser * topw; float diag = sqrt ( lesser * lesser + topw * topw ); float hper = 0.5 * ( diag + greater + basew ) ; float a2 = sqrt ( hper * ( hper - diag ) * ( hper - greater ) * ( hper - basew ) ); return a1 + a2; } void transferLower( float amount ) { amount = max ( -area(), amount ); float target = area() + amount; float len; float diff = amount; while ( abs ( diff ) > 0.02 ) { len = (diff ) / basew; setR ( rh + len ); setL ( lh + len ); reshape(); diff = target - area(); } } void transferUpper( float amount) { amount = max ( -area(), amount ); float target = area() + amount; float len; float diff = amount; while ( abs ( diff ) > 0.02 ) { len = (diff ) / topw; setR ( rh + len ); setL ( lh + len ); reshape(); diff = target - area(); } } void transferRight( float amount) { amount = max ( -area(), amount ); float target = area() + amount; float len; float diff = amount; while ( abs ( diff ) > 0.02 ) { len = 2 * diff / rh; setT ( topw + len ); reshape(); diff = target - area(); } } void transferLeft ( float amount ) { amount = max ( -area(), amount ); float target = area() + amount; float len; float diff = amount; while ( abs ( diff ) > 0.02 ) { len = 2 * diff / lh; setT ( topw + len ); reshape(); diff = target - area(); } } void setbase(float x1,float y1,float x2,float y2) { blx = x1; bly = y1; brx = x2; bry = y2; basew = len ( x1,y1,x2,y2); } void setR(float rH) { float temp = rh; rh = rH; if ( !isConvex() ) rh = temp; } void setL(float lH) { float temp = lh; lh = lH; if ( !isConvex() ) lh = temp; } void setT(float tH) { float temp = topw; topw = tH; if ( !isConvex() ) topw = temp; } boolean isConvex() { float hper = 0.5 * ( rh + lh + topw + basew ); float greater, lesser; if ( rh > hper || lh > hper || topw > hper || basew > hper ) return false; if ( rh < lh ) { greater = lh; lesser = rh; } else { greater = rh; lesser = lh; } if ( greater*greater >= topw*topw + (lesser+basew)*(lesser+basew) ) return false; if ( (greater+basew ) * ( greater+basew ) <= lesser*lesser + topw * topw ) return false; return true; } void renderLit( ) { stroke ( 192 ); //renderQuad(); line ( rx, ry, lx, ly ); stroke ( rsun * 10 ); line ( brx, bry, rx, ry ); stroke ( lsun * 10 ); line ( blx, bly, lx, ly ); xmin = min ( xmin, rx ); xmax = max ( xmax, rx ); ymin = min ( ymin, ry ); ymax = max ( ymax, ry ); } void renderQuad( ) { beginShape(QUADS); renderVerts(); endShape(); } void renderVerts() { vertex( brx, bry ); vertex( rx, ry ) ; vertex( lx, ly ) ; vertex( blx, bly ) ; } }