Skip to content

Instantly share code, notes, and snippets.

@waltton
Created March 9, 2025 13:08
Show Gist options
  • Save waltton/edd63d6bd9edfe37b88f812842398c9c to your computer and use it in GitHub Desktop.
Save waltton/edd63d6bd9edfe37b88f812842398c9c to your computer and use it in GitHub Desktop.
// https://processing.org/
float inc = 0.05;
float zinc = 0.0001;
int particleSize = 2;
int particleCount = 5000;
float pmod = 500; // particle mod for hue increment
float hincm = 0.1; // hue increment multiplier
float hueMin = 0;
float hueMax = 0.1;
// based on vel
float satMax = 1;
float satMin = 0.8;
float scl = 5;
int cols, rows;
float darkRate = 0.05;
float maxSpeed = 10;
float mag = 50;
boolean showFlowField = false;
boolean showParticles = true;
PVector[][] flowfield;
ArrayList < Particle > particles = new ArrayList < Particle > ();
void setup() {
// createCanvas(300, 300);
size(1000, 1000, P2D);
colorMode(HSB, 1);
cols = floor(width / scl);
rows = floor(height / scl);
flowfield = new PVector[cols + 1][rows + 1];
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
flowfield[x][y] = new PVector();
}
}
particles.clear();
for (int i = 0; i < particleCount; i++) {
particles.add(new Particle());
}
background(0);
frameRate(30);
}
float zoff = 0;
void draw() {
//stroke(1);
//strokeWeight(4);
fill(0, 0, 0, darkRate);
rect(0, 0, width, height);
float yoff = 0;
for (int x = 0; x <= rows; x++) {
float xoff = 0;
for (int y = 0; y <= cols; y++) {
var angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
var v = PVector.fromAngle(angle);
v.setMag(mag);
//v.setMag(map(noise(xoff, yoff), 0, 1, 0, mag));
flowfield[x][y] = v;
if (showFlowField) {
stroke(0, 0, 100, 50);
strokeWeight(1);
push();
translate(x * scl, y * scl);
rotate(v.heading());
line(0, 0, scl, 0);
pop();
}
xoff += inc;
}
yoff += inc;
zoff += zinc;
}
noFill();
strokeWeight(particleSize);
if (showParticles) {
for (int i = 0; i < particleCount ; i++) {
Particle p = particles.get(i);
p.follow(flowfield);
p.update();
p.edges();
stroke(
/* hue */ map(noise((i%pmod)*hincm+zoff), 0, 1, hueMin, hueMax),
/* saturation */ map(p.vel.mag(), 0, maxSpeed, satMax, satMin), // map(noise(zoff*0.1), 0, 1, 0.5, 1),
/* brightness */ 1, // map(noise(i+zoff), 0, 1, 0.8, 1),
1
);
p.show();
}
}
//noLoop();
}
class Particle {
PVector pos;
PVector prevPos;
PVector vel;
PVector acc;
Particle() {
pos = new PVector(random(width), random(height));
prevPos = pos.copy();
vel = new PVector();
acc = new PVector();
}
void update() {
vel.add(acc);
vel.limit(maxSpeed);
pos.add(vel);
acc.mult(0);
//acc.mult(0.5);
}
void follow(PVector[][] flowfield) {
int x = floor(pos.x / scl);
int y = floor(pos.y / scl);
PVector force = flowfield[x][y];
applyForce(force);
}
void applyForce(PVector force) {
acc.add(force);
}
void show() {
line(pos.x, pos.y, prevPos.x, prevPos.y);
updatePrev();
}
void updatePrev() {
prevPos.x = pos.x;
prevPos.y = pos.y;
}
void edges() {
if (pos.x > width) {
pos.x = 0;
updatePrev();
}
if (pos.x < 0) {
pos.x = width-1;
updatePrev();
}
if (pos.y > height) {
pos.y = 0;
updatePrev();
}
if (pos.y < 0) {
pos.y = height-1;
updatePrev();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment