// wave particle program // version 20 - sources start as pi or 2pi int sX, sY, sZ, p, tick; float energyLoss, pAmp, colorScheme, pBrightness, pSaturation, sPhase; float pMass, pElasticity, pFriction, dFriction, pStress, dOmega; Particle particles[][]; // set up an array to access the objects void setup() { colorScheme = random(7, 15); tick = 0; size(400, 400); framerate(12); sX = width; sY = height; sZ = 100; //depth colorMode(HSB, sZ); background(getColor(sZ/2)); // parameters with defaults in parenthesis pBrightness = 20; //particle brightness pSaturation = 50; //particle saturation sPhase = 0; // phase of first source pAmp = 0.5; // amplitude of sources relative to sZ (0.5) dOmega = 0.002; // angular velocity in radians per frame (0.01) pMass = 5; // (range 2 upwards, higher values smoother & slower) pElasticity = 1; // relates particle stress to strain (1) pFriction = 0; dFriction = 0; // additional friction per source (0.001) //there is an invisible border of 1px loadPixels(); particles = new Particle[sY + 2][sX + 2]; for (int row = 0; row < sY + 2; row++) { for (int col = 0; col < sX + 2; col++) { particles[row][col] = new Particle(row, col); } } } void draw() { // calculate forces but do NOT move (Newton!) for (int row = 1; row < sY + 1; row++) { for (int col = 1; col < sX + 1; col++) { pStress = particles[row-1][col].getZ() + particles[row+1][col].getZ() + particles[row][col-1].getZ() + particles[row][col+1].getZ() - 4 * particles[row][col].getZ(); particles[row][col].setForce(pStress); } } // move and draw the particles //loadPixels(); for (int row = 1; row < sY + 1; row++) { for (int col = 1; col < sX + 1; col++) { particles[row][col].moveParticle(); particles[row][col].drawParticle(); } } updatePixels(); } void mouseReleased() { particles[mouseY][mouseX].setSource(); pFriction += dFriction; pFriction = min(0.9, pFriction); } color getColor(float z) { float h, s, b; h=z; b = (z <= sZ/2) ? sZ/2 - z : z - sZ/2; b = pBrightness * sqrt(b); s = pSaturation; return color(h,s,b); } class Particle { float z, oldZ, f, v, omega; int row, col; boolean source; Particle(int inRow, int inCol){ row = inRow; col = inCol; oldZ = 0; z = sZ/2; v = 0; f = 0; source = false; } float getZ() { return z; } void setSource() { source = true; omega = sPhase; sPhase = (sPhase + PI) % (2*PI); } boolean isSource() { return source; } void setForce(float stress) { f = pElasticity * stress; } void moveParticle() { oldZ = z; if (source) { omega += dOmega; omega = omega % (2*PI); // sin wave z = sZ * (0.5 + pAmp * sin(omega)); } else { float a = f / pMass; v = (v + a)*(1-pFriction); z = max(0, z + v); } } void drawParticle() { if (z == oldZ) {return;} pixels[(row-1)*width + col-1] = getColor(z); } }