Simple 3D Rain Simulation

#1

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(){
    vel.add(gravity);
    pos.add(vel);
    // 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
      vel.add(gravity);
      pos.add(vel);
    }
  }

  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++) {
      splashes.add(new Splash(x, y, z, size));
    }
  }
}
8 Likes
#2

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 ) {
        toRemove.add(d);
    }
    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?

#3

Thanks for the feedback! love it :smiley:

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