int NUM_PARTICLES = 64; int NUM_ATTRACTORS = 3; int BLEN = 128; // buffer length float damp = 0.9; float accel = 50.0; Particle[] particle; Attractor[] attractor; float depth; class Attractor { float x,y,z; float tx,ty,tz; Attractor() { init(); x = tx; y = ty; z = tz; } void init() { tx = random(width); ty = random(height); tz = random(depth); } void step() { x += (tx-x) / 50.0; y += (ty-y) / 50.0; z += (tz-z) / 50.0; } } class Particle { float x,y,z,vx,vy,vz; float[] bx; float[] by; float[] bz; int currentb = 0; Particle() { init(); } void init() { x = random(width); y = random(height); z = random(depth); vx = random(-accel/2,accel/2); vy = random(-accel/2,accel/2); vz = random(-accel/2,accel/2); bx = new float[BLEN]; by = new float[BLEN]; bz = new float[BLEN]; for (int i = 0; i < bx.length; i++) { bx[i] = x; by[i] = y; bz[i] = z; } } void step() { for (int i = 0; i < attractor.length; i++) { float d2 = sq(attractor[i].x-x) + sq(attractor[i].y-y) + sq(attractor[i].z-z); if (d2 > 0.1) { float id2 = 1.0 / d2; vx += accel * (attractor[i].x-x) * id2; vy += accel * (attractor[i].y-y) * id2; vz += accel * (attractor[i].z-z) * id2; } } bx[currentb] = x; by[currentb] = y; bz[currentb] = z; currentb++; currentb %= bx.length; x += vx; y += vy; z += vz; vx *= damp; vy *= damp; vz *= damp; if (x < 0 || x > width || y < 0 || y > height || z < 0 || z > depth) { vx = vy = vz = 0; } } void show() { beginShape(LINE_STRIP); for (int i = 0; i < bx.length; i++) { stroke(((128*i)/bx.length) << 24 | 0x00ff40b0); vertex(bx[(i+currentb)%bx.length], by[(i+currentb)%bx.length], bz[(i+currentb)%bx.length]); } endShape(); } } void setup() { size(512,512); depth = (width + height) * 0.5; framerate(30); attractor = new Attractor[NUM_ATTRACTORS]; particle = new Particle[NUM_PARTICLES]; for (int i = 0; i < attractor.length; i++) { attractor[i] = new Attractor(); } for (int i = 0; i < particle.length; i++) { particle[i] = new Particle(); particle[i].init(); } } int f = 0; float a = 0.0; void draw() { background(80,80,80); push(); translate(0,0,-depth); translate(width/2,height/2,depth/2); rotateX(a/15.0); rotateY(a); rotateZ(a/2.0); a+= 0.02; translate(-width/2,-height/2,-depth/2); for (int i = 0; i < attractor.length; i++) { attractor[i].step(); push(); translate(attractor[i].x, attractor[i].y, attractor[i].z); noStroke(); fill(255,0,0,40); sphere(5); pop(); } for (int j = 0; j < particle.length; j++) { particle[j].show(); particle[j].step(); } f++; if (mousePressed || (f % 360 == 0)) { for (int i = 0; i < attractor.length; i++) { attractor[i].init(); } } pop(); }