Snowflakes


  class Flake {
    float x,y,vx,vy;
    float rot,spin;
    float orad;
    int nbrPoints;
    PVector[]  pts;
    float sWeight;
  
    Flake() {
      init();
    }
    
    void init() {
      x = random(width);
      y = -(24 + random(height*2));
      rot = random(TWO_PI);
      spin = random(-.03,.03);
      vx = 0;
      vy = 0;
      orad = 12 + sq(random(1))*16;
      sWeight = orad/32.0;
      nbrPoints = int(random(5,15))*2;
      pts = new PVector[nbrPoints];
      for (int i = 0; i < nbrPoints; ++i) {
        pts[i] = new PVector( cos( random(TWO_PI))*random(orad), sin(random(TWO_PI))*random(orad) );   
      }
    }
  
    void physics() {
      vx += random(-.2,.2);
      vy += random(-.2,.2);
      vy += .2;
      vx *= .9;
      vy *= .9;
      x += vx;
      y += vy;
      rot += spin;
      if (y > height + 24) {
        init();
      }
      if (x > width+24) {
        x = -24;
      }
      if (x < -24) {
        x = width+24;
      }
    }
  
    void render() {
      strokeWeight(sWeight);
  
      // Shadow pass
      stroke( #aaaaaa );
      pushMatrix();
        translate(x+1, y+1);
        rotate(rot-PI/2); // Point upwards  
        for (int reflection = 0; reflection < 6; ++reflection) {
          for (int i = 0; i < nbrPoints-1; i += 2) {
              line( pts[i].x, pts[i].y, pts[i+1].x, pts[i+1].y );
            }
          rotate( radians(60) );
        }
      popMatrix();
  
      // Foreground pass
      stroke( #ffffff );
      pushMatrix();
        translate(x, y);
        rotate(rot-PI/2); // Point upwards  
        for (int reflection = 0; reflection < 6; ++reflection) {
          for (int i = 0; i < nbrPoints-1; i += 2) {
              line( pts[i].x, pts[i].y, pts[i+1].x, pts[i+1].y );
            }
          rotate( radians(60) );
        }
      popMatrix();
    }
  }
  
  ArrayList flakes;
  int nbrFlakes = 40;
  
  void setup()
  {
    size(500,500);
    smooth();
    strokeWeight(2);
    
    flakes = new ArrayList();
    for (int i = 0; i < nbrFlakes; ++i) {
       flakes.add( new Flake());
    }  
  }
  
  void draw() 
  {
    for (int i = 0; i < height; ++i) {
      stroke( lerpColor( #00bfff, #ffffff, i/(float)height));
      rect(0,i,width,1);
    }
    stroke( #ffffff );
    noFill();
    for (Flake f : flakes) {
      f.physics();
      f.render();
    }
  }