// Bubb5 - Jostein Trondal jallamekk@hotmail.com june 2005 int bredde = 400; int hoyde = 300; float minRadius = 3; float maxRadius = 60; int maxCircles = 65536; int collisions, collisionLimit=1000; int fillSpeed = 10; Circle[] circles = new Circle[maxCircles]; int numCircles = 0; float r, dx, dy; boolean foundPoint; float testx, testy, d=maxRadius; float min_x, min_y, min_d=1000; void setup() { size(bredde,hoyde); noStroke(); framerate(20); background(0); fill(255); smooth(); } void draw() { for(int y=0; y<5; y++) { collisions=0; do { foundPoint = true; testx = random(0,width); testy = random(0,height); min_d = 1000; for(int i=0; i maxRadius) min_d = maxRadius; circles[numCircles] = new Circle(testx, testy, min_d); wrappedSphere(circles[numCircles]); numCircles++; } else { noLoop(); println("stopped"); break; } } } void wrappedSphere(Circle c) { float brightest = (c.r / maxRadius) * 255; for(float a=c.r; a>0; a-=0.5) { fill((sqrt(c.r*c.r - a*a) / c.r) * brightest); wrappedCircle(c.x, c.y, a); } } // Returns the (shortest) distance from a point to the edge of a (wrapped) circle c. // If the point is inside the circle, the returned value is negative // If the point is on the edge of the circle, the returned value is (very close to) 0. float distance(float x, float y, Circle c) { // We know for sure that the centre of the circle is not wrapped float d = distance(x,y, c.x,c.y) - c.r; float dt; // Check towards potentially wrapped edge directions dt = distance(x,y, c.x+width,c.y) - c.r; // check wrap left to right if (dt < d) d=dt; dt = distance(x,y, c.x+width,c.y+height) - c.r; // check wrap topleft to bottomright if (dt < d) d=dt; dt = distance(x,y, c.x,c.y+height) - c.r; // check wrap top to bottom if (dt < d) d=dt; dt = distance(x,y, c.x-width,c.y+height) - c.r; // check wrap topright to bottomleft if (dt < d) d=dt; dt = distance(x,y, c.x-width,c.y) - c.r; // check wrap right to left if (dt < d) d=dt; dt = distance(x,y, c.x-width,c.y-height) - c.r; // check wrap bottomright to topleft if (dt < d) d=dt; dt = distance(x,y, c.x,c.y-height) - c.r; // check wrap bottom to top if (dt < d) d=dt; dt = distance(x,y, c.x+width,c.y-height) - c.r; // check wrap bottomleft to topright if (dt < d) d=dt; return d; } float distance(float x1, float y1, float x2, float y2) { return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } void wrappedCircle(float x, float y, float r) { ellipseMode(CENTER); ellipse(x,y,r*2,r*2); if ((x-r) < 0) { ellipse(x+width,y,r*2,r*2); // wrap left to right if ((y-r)<0) ellipse(x+width,y+height,r*2,r*2); // wrap topleft to bottomright } if ((y-r) < 0) { ellipse(x,y+height,r*2,r*2); // wrap top to bottom if ((x+r)>width) ellipse(x-width,y+height,r*2,r*2); // wrap topright to bottomleft } if ((x+r) > width) { ellipse(x-width,y,r*2,r*2); // wrap right to left if ((y+r)>height) ellipse(x-width,y-height,r*2,r*2); // wrap bottomright to topleft } if ((y+r) > height) { ellipse(x,y-height,r*2,r*2); // wrap bottom to top if ((x-r)<0) ellipse(x+width,y-height,r*2,r*2); // wrap bottomleft to topright } } void wrappedCircle(Circle c) { wrappedCircle(c.x,c.y,c.r); } class Circle { float x, y, r; Circle(float init_x, float init_y, float init_r) { x = init_x; y = init_y; r = init_r; } }