# Simple 3D Rain Simulation

**URL:** <https://discourse.processing.org/t/simple-3d-rain-simulation/10834>\
**Category:** Gallery\
**Created:** [May 2, 2019, 9:19am UTC](https://discourse.processing.org/t/simple-3d-rain-simulation/10834 "2019-05-02T09:19:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![humayung](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/humayung/32/6089_2.png) [@humayung](https://discourse.processing.org/u/humayung)\
**Post date:** [May 2, 2019, 9:19am UTC](https://discourse.processing.org/t/simple-3d-rain-simulation/10834/1 "2019-05-02T09:19:18Z")

</div>

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

bit.ly/2GWCEYT

[![](https://img.youtube.com/vi/_SeUvcTWMuE/maxresdefault.jpg "3D Rain Meditation - Simulation") ](https://www.youtube.com/watch?v=_SeUvcTWMuE&t=126s)

```auto
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));
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![Nathan](https://avatars.discourse-cdn.com/v4/letter/n/c5a1d2/32.png) [@Nathan](https://discourse.processing.org/u/Nathan)\
**Post date:** [May 14, 2019, 8:38pm UTC](https://discourse.processing.org/t/simple-3d-rain-simulation/10834/2 "2019-05-14T20:38:31Z")

</div>

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.

```auto
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.

```auto
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?

---

<div class="post-metadata">

**Author:** ![humayung](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/humayung/32/6089_2.png) [@humayung](https://discourse.processing.org/u/humayung)\
**Post date:** [May 15, 2019, 12:13pm UTC](https://discourse.processing.org/t/simple-3d-rain-simulation/10834/3 "2019-05-15T12:13:04Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![adaptinnovative](https://avatars.discourse-cdn.com/v4/letter/a/2acd7d/32.png) [@adaptinnovative](https://discourse.processing.org/u/adaptinnovative)\
**Post date:** [January 23, 2020, 7:27am UTC](https://discourse.processing.org/t/simple-3d-rain-simulation/10834/4 "2020-01-23T07:27:46Z")

</div>

Really love this bit of coding.
