class Particle { PVector position; PVector velocity; int timer; Particle (float x, float y) { position = new PVector(x, y); // velocity = new PVector(); velocity = new PVector(0.01 - random(0.02), 0.01 - random(0.02)); timer = int(random(120)); } void Update() { int cellX = int(position.x); int cellY = int(position.y); flow[cellX][cellY].x = flow[cellX][cellY].x * 0.95 + velocity.x * 0.05; flow[cellX][cellY].y = flow[cellX][cellY].y * 0.95 + velocity.y * 0.05; density[cellX][cellY] += 0.1; flow[cellX][cellY].limit(1); velocity.x += 0.2 * flow[cellX][cellY].x; velocity.y += 0.2 * flow[cellX][cellY].y; //velocity.y += 0.01 * wind[cellY]; velocity.mult(0.9); position.x = (position.x + velocity.x + resolutionX) % resolutionX; position.y = (position.y + velocity.y + resolutionY) % resolutionY; timer ++; if (timer > 240) { timer = int(random(120)); position = new PVector(random(resolutionX), random(resolutionY)); velocity = new PVector(-1 + random(2), -1 + random(2)); } } void Draw(float zoom) { stroke(0, min(255, int(255 * abs(velocity.x) / 0.2)), min(255, int(255 * abs(velocity.y / 0.2)))); line(zoom * position.x, zoom * position.y, zoom * (position.x + velocity.x), zoom * (position.y + velocity.y)); } }

int resolutionX = 192; int resolutionY = resolutionX / 2; PVector flow[][] = new PVector[resolutionX][resolutionY]; float density[][] = new float[resolutionX][resolutionY]; float wind[] = new float[resolutionY]; // horizontal bands int particleCount = 8192; Particle particle[] = new Particle[particleCount]; int currentParticle; int oldMouseX; int oldMouseY; void setup() { size(960, 480); frameRate(60); for (int y = 0; y < resolutionY; y ++) { wind[y] = 1 * sin(4 * PI * y / resolutionY); for (int x = 0; x < resolutionX; x ++) { flow[x][y] = new PVector(); //flow[x][y] = new PVector(0.2 - random(0.4), 0.2 - random(0.4)); } } for (int i = 0; i < particleCount; i ++) { particle[i] = new Particle(random(resolutionX), random(resolutionY)); } } void draw() { fill(0); rect(0, 0, width, height); int zoom = min(width / resolutionX, height / resolutionY); for (int y = 0; y < resolutionY; y ++) { for (int x = 0; x < resolutionX; x ++) { density[x][y] = 0; } } // Particles? stroke(255); for (int i = 0; i < particleCount; i ++) { particle[i].Update(); //particle[i].Draw(zoom); } noStroke(); for (int y = 0; y < resolutionY; y ++) { for (int x = 0; x < resolutionX; x ++) { fill( /*min(255, int(255 * abs(flow[x][y].x) / 0.2)), min(255, int(255 * abs(flow[x][y].y / 0.2))),*/ int(max(0, min(255, 255 * density[x][y])))); rect(x * zoom, y * zoom, zoom, zoom); } } // Randomization of flow //flow[int(random(resolutionX))][int(random(resolutionY))] //= new PVector(-1 + random(2), -1 + random(2)); // Painting int cellX = mouseX / zoom; int cellY = mouseY / zoom; if (mousePressed) { for (int i = 0; i < 32; i ++) { particle[currentParticle] = new Particle(cellX, cellY); currentParticle = (currentParticle + 1) % particleCount; } } // Make mouse movement affect flow float dX = cellX - oldMouseX; float dY = cellY - oldMouseY; for (int y = -8; y < 8; y ++) { for (int x = -8; x < 8; x ++) { flow[max(0, min(resolutionX - 1, cellX + x))] [max(0, min(resolutionY - 1, cellY + y))].add (new PVector(dX, dY)); } } oldMouseX = cellX; oldMouseY = cellY; } void keyPressed() { setup(); }

Report Sketch

Report for inappropriate content

Your have successfully reported the sketch. Thank you very much for helping to keep OpenProcessing clean and tidy :)

This was my second attempt at doing a fluid simulation. Like the first, it uses particles combined with a vector field. I'm happy with the way that interacting with this one feels. I'm currently trying an approach that doesn't use particles at all- I'll upload that soon.

Move the mouse to affect the vector field. Click to add particles. Press any key to reset.