float threshold = 0.03; ArrayList metaballCenters; float[] sums; void setup() { size(320, 240); smooth(); frameRate(30); sums = new float[width * height]; metaballCenters = new ArrayList(); for (int i = 0; i < 100; i++) { metaballCenters.add(new Point((int)random(width / 2) + width / 4, (int)random(height / 2) + height / 4)); } } void draw() { background(255); Arrays.fill(sums, 0.0); for (int i = 0; i < metaballCenters.size(); i++) { Point each = (Point)metaballCenters.get(i); int rmax = 20; for (int y = max(0, each.y - rmax); y < min(height, each.y + rmax); y++) { for (int x = max(0, each.x - rmax); x < min(width, each.x + rmax); x++) { int offset = y * width + x; sums[offset] += metaballValue(each.x, each.y, x, y); } } } loadPixels(); for (int i = 0; i < width * height; i++) { if (sums[i] > threshold) pixels[i] = color(128); } updatePixels(); for (int i = 0; i < metaballCenters.size(); i++) { Point each = (Point)metaballCenters.get(i); each.x += (int)(random(5) - 2.5); each.x = constrain(each.x, 0, width); each.y += (int)(random(5) - 2.5); each.y = constrain(each.y, 0, height); } } float metaballValue(int cx, int cy, int x, int y) { return 1.0 / (pow(x - cx, 2) + pow(y - cy, 2)); }