# Simple 3D Rain Simulation

i’ve just made simple 3D Rain Simulation system for relaxation.
you can see how it performs:

bit.ly/2GWCEYT

``````RainSystem rs; // Downpour
SplashSystem ss; // Droplet hits the ground, and splashed
PVector gravity = new PVector(0, 0.9, 0);

void setup() {
fullScreen(P3D);
stroke(255);
rs = new RainSystem(20); // 20 drops per frame
ss = new SplashSystem();
}

void draw() {
background(0);
rotateX(5.436); // Nice view from this angle
rs.run(); // Pouring
ss.run(); // Splashing
}
class Droplet{
PVector pos; // Keep track droplet position
PVector vel; // droplet velocity
boolean off; // hit the ground, and die
float size;
float len; // length

Droplet(float x, float y, float z){
pos = new PVector(x,y,z);
vel = new PVector();
this.len = random(10);
}

void show(){
strokeWeight(1.5);
line(pos.x, pos.y, pos.z, pos.x, pos.y + len, pos.z);
}

void update(){
// Hit the ground and splashed
if(pos.y > height) {
ss.init(pos.x, height, pos.z, vel.mag());
off = true;
}
}
}
class Splash {
PVector pos;
PVector vel;
boolean off;
float size;

Splash(float x, float y, float z, float size) {
this.pos = new PVector(x, y, z);
this.size = random(0, pow(size,0.15));
vel = PVector.random3D();
vel.mult(random(size/4));
}

void update() {
if (pos.y > height) {
off = true;
// Only inits another splashes if the size not too small
if (size >1) {
// Hit the ground and splashed
ss.init(pos.x, height, pos.z, size);
}
} else {
// Otherwise update it
}
}

void show() {
strokeWeight(size);
// the splash just a point
point(pos.x, pos.y, pos.z);
}
}
class RainSystem {
ArrayList<Droplet> droplets;
int f;

RainSystem(int f) {
this.f = f;
droplets = new ArrayList<Droplet>();
}

void run() {
for (int i = 0; i < f; i++) {
droplets.add(new Droplet(random(-width, width*2), random(-300), random(-2500, 500)));
}
for (int i = droplets.size() - 1; i >= 0; i--) {
if (droplets.get(i).off) {
droplets.remove(i);
} else {
droplets.get(i).update();
droplets.get(i).show();
}
}
}
}
class SplashSystem {
ArrayList<Splash> splashes;
SplashSystem() {
splashes = new ArrayList<Splash>();
}

void run() {
for (int i = splashes.size() - 1; i >= 0; i--) {
if (splashes.get(i).off) {
splashes.remove(i);
} else {
splashes.get(i).update();
splashes.get(i).show();
}
}
}

void init(float x, float y, float z, float size){
for (int i = 0; i < size/3; i++) {
}
}
}
``````
9 Likes

Looks interesting and fairly simple. Although I would note that from a coding perspective you could save some effort with either an enhanced for loop or at least a single object retrieval.

E.g.

``````for(Droplet d : droplets) {
if( d.off ) {
}
else {
d.update();
d.show();
}
}
``````

Obviously the above requires a collection (I called it ‘toRemove’) of stuff to remove later, but you can then just do a removeAll on the droplets since it’s a List. If the performance of non-simultaneous removal is a concern, you can still just do the get(i) part once and otherwise do the same thing. I.e.

``````for (int i = droplets.size() - 1; i >= 0; i--) {
Droplet d = droplets.get(i);

if (d.off) {
droplets.remove(i);
}
else {
d.update();
d.show();
}
}
``````

How did you create audio to go with this? I’m not seeing anything in the code excerpt that would handle that. Did you consider tweaking it for different “materials” or to reflect how water drops sound when they hit a puddle as opposed to a solid surface?

1 Like

Thanks for the feedback! love it

Btw, for the audio i just put a ‘backsound.mp3’ on that video. It doesn’t reflects the simulation

Really love this bit of coding.