/** "Hairball (Shadows)"
original by W. Xavier Snelgrove at:
http://www.wxs.ca/applets/hairball/

Left-click and/or drag to spawn particles
Right-click to clear

I really like Xavier's original sketch...
This is just some playing around I did with it after
he posted a message in the Processing forum looking for some
help with it. Main changes I made were restructuring the trig tables,
adding "shadows" (aka emboss) to the rendering, and adding a small
"margin" so that evolution wouldn't stop so hard at edge.
Dave Bollinger (http://www.davebollinger.com)
*/ ArrayList seeds; int toopie = 2048; int halfpie = toopie / 4; float[] sinLUT; float[] cosLUT; void setup() { size(600,400); background(255); // INitialize LUTs sinLUT = new float[toopie]; cosLUT = new float[toopie]; for (int i=0; i=0; i--) { Seed seed = (Seed) seeds.get(i); if (!seed.move()) seeds.remove(i); } } class Seed { static final float margin = 30f; static final float smallest = 0.5; boolean alive = true; int angle; float size = 5; float x; float y; int rot; float shrink = 0.99; float fertility = 0.02; Seed(float _x, float _y, int _angle, float _size, int _rot, float _shrink, float _fertility) { x = _x; y = _y; angle = _angle; size = _size; rot = _rot; shrink = _shrink; fertility = _fertility; } Seed(float _x, float _y) { x = _x; y = _y; angle = int(random(toopie)); rot = int(random(toopie/64)); shrink = random(0.98,0.99); fertility = random(0.01,0.03); } boolean move() { if (!alive) return false; if (y > height+margin || y < -margin || x > width+margin || x < -margin || size < smallest) { alive = false; return false; } // draw fill(0); ellipse(x+1,y+1,size,size); fill(255); ellipse(x,y,size,size); // move x += size*cosLUT[angle]; y += size*sinLUT[angle]; angle = ((angle+rot)+toopie)%toopie; size *= shrink; if (random(1) < fertility) { int angle2 = (angle+halfpie)%toopie; seeds.add(new Seed(x+size*cosLUT[angle2], y+size*sinLUT[angle2], angle2, size, rot, shrink, fertility)); } return true; } } void reset() { seeds.clear(); background(255); } void mousePressed() { if (mouseButton==LEFT) seeds.add(new Seed(mouseX, mouseY)); if (mouseButton==RIGHT) reset(); } void mouseDragged() { seeds.add(new Seed(mouseX, mouseY)); }