int NUM_PARTICLES = 8192; int NUM_ATTRACTORS = 8; Particle[] particle; Attractor[] attractor; float damp = 0.00002; float accel = 10000; float buffer[]; float vxbuffer[]; float vybuffer[]; class Particle { float x,y,vx,vy; Particle() { x = random(width); y = random(height); vx = random(-accel/2,accel/2); vy = random(-accel/2,accel/2); } void step() { for (int i = 0; i < attractor.length; i++) { float d2 = sq(attractor[i].x-x) + sq(attractor[i].y-y); if (d2 > 0.1) { vx += accel * (attractor[i].x-x) / d2; vy += accel * (attractor[i].y-y) / d2; } } x += vx; y += vy; // deposit(x,y,vx,vy); aadeposit(x,y,vx,vy); vx *= damp; vy *= damp; } } void deposit(float x, float y, float vx, float vy) { if (x >= 0 && x < width && y >= 0 && y < height) { int index = (int)x+((int)y*width); buffer[index]++; vxbuffer[index] += vx; vybuffer[index] += vy; } } float fx,fy,cx,cy,totd,prop; float xs[]; float ys[]; int index[]; float d[]; final void aadeposit(float x, float y, float vx, float vy) { fx = floor(x); fy = floor(y); cx = ceil(x); cy = ceil(y); xs = new float[] { fx, fx, cx, cx }; ys = new float[]{ fy, cy, fy, cy }; index = new int[] {(int)fx+((int)fy*width),(int)fx+((int)cy*width),(int)cx+((int)fy*width),(int)cx+((int)cy*width)}; d = new float[]{ distance(x,y,fx,fy), distance(x,y,fx,cy), distance(x,y,cx,fy), distance(x,y,cx,cy) }; totd = 0.0; for (int i = 0; i < d.length; i++) { totd += d[i]; } for (int i = 0; i < index.length; i++) { if (index[i] >= 0 && index[i] < pixels.length) { prop = d[i]/totd; buffer[index[i]]+=prop; vxbuffer[index[i]] += abs(xs[i]-x)*vx; vybuffer[index[i]] += abs(ys[i]-y)*vy; } } } final float distance(float x1, float y1, float x2, float y2) { return sqrt(sq(x1-x2)+sq(y1-y2)); } class Attractor { float x,y; Attractor() { x = random(width); y = random(height); } } void setup() { size(600,600); colorMode(HSB); attractor = new Attractor[NUM_ATTRACTORS]; particle = new Particle[NUM_PARTICLES]; scatter(); } int t = 0; float power = 0.4; float maxbuf,maxspeed,value,speed,angle,h,s,b; void loop() { for (int j = 0; j < particle.length; j++) { particle[j].step(); } if (t % 32 == 0) { background(255); maxbuf = 0; maxspeed = 0.0; for (int i = 0; i < buffer.length; i++) { maxbuf = max(maxbuf,buffer[i]); maxspeed = max(maxspeed,sqrt(sq(vybuffer[i])+sq(vxbuffer[i]))); } for (int i = 0; i < pixels.length; i++) { if (buffer[i] > 0) { value = buffer[i]/maxbuf; b = 255.0-(255.0*pow(value,power)); speed = sqrt(sq(vybuffer[i])+sq(vxbuffer[i]))/maxspeed;; s = (255.0*pow(speed,power)); angle = PI+atan2(vybuffer[i],vxbuffer[i]); h = 255.0-(angle*255.0/TWO_PI); pixels[i] = color(h,s,b); } } } t++; } void scatter() { background(255); for (int i = 0; i < attractor.length; i++) { attractor[i] = new Attractor(); } for (int i = 0; i < particle.length; i++) { particle[i] = new Particle(); } buffer = new float[pixels.length]; vxbuffer = new float[pixels.length]; vybuffer = new float[pixels.length]; t = 0; } void keyPressed() { scatter(); } void mousePressed() { power = float(mouseX)/float(width); }