int NUM_PARTICLES = 8192; int NUM_ATTRACTORS = 8; Particle[] particle; Attractor[] attractor; float damp = 0; float accel = 5000; float buffer[]; float vxbuffer[]; float vybuffer[]; boolean aa = false; 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; if (aa) { aadeposit(x,y,vx,vy); } else { deposit(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 = sq(1.0-d[i]/totd); buffer[index[i]]+=prop; vxbuffer[index[i]] += (1.0-abs(xs[i]-x))*vx; vybuffer[index[i]] += (1.0-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); } Attractor(float x, float y) { this.x = x; this.y = y; } } void setup() { size(600,600); colorMode(HSB); attractor = new Attractor[NUM_ATTRACTORS]; particle = new Particle[NUM_PARTICLES]; scatter(); attractor[0] = new Attractor(398.7855, 260.12); attractor[1] = new Attractor(430.83215, 433.03412); attractor[2] = new Attractor(257.5647, 411.41632); attractor[3] = new Attractor(231.67877, 426.55072); attractor[4] = new Attractor(127.697815, 317.10776); attractor[5] = new Attractor(165.1979, 245.52707); attractor[6] = new Attractor(332.07306, 104.05903); attractor[7] = new Attractor(465.398, 162.21806); } 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(); } pixels[t%32] = #d0d0d0; 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); println("attractors:"); for (int i = 0; i < attractor.length; i++) { attractor[i] = new Attractor(); attractor[i].x = (width*0.25*cos(TWO_PI*(float)i/(float)attractor.length)) + (width/2) + random(-width*0.1,width*0.1); attractor[i].y = (height*0.25*sin(TWO_PI*(float)i/(float)attractor.length)) + (height/2) + random(-height*0.1,height*0.1); println("attractor["+i+"] = new Attractor("+attractor[i].x+", "+attractor[i].y+");"); } println(); 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() { if (key == 'a' || key == 'A') { aa = !aa; 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; } else { scatter(); } } void mousePressed() { power = float(mouseX)/float(width); }