Blob Blame Raw


typedef struct {
  HMap *hmap;
  HMap *wmap;
} Water;



void waterInit(Water *w, HMap *hmap, HMap *wmap) {
  w->hmap = hmap;
  w->wmap = wmap;
  for(int i = 0; i < HMAP_SIZE; ++i)
    for(int j = 0; j < HMAP_SIZE; ++j)
      w->wmap->map[i][j] = w->hmap->map[i][j];
}


void waterRain(Water *w, double k) {
  for(int i = 0; i < HMAP_SIZE; ++i)
    for(int j = 0; j < HMAP_SIZE; ++j)
      w->wmap->map[i][j] += k;
}


void waterFall(Water *w, double wk, double hk) {
  static const int di[4] = { -1, 1,  0, 0 };
  static const int dj[4] = {  0, 0, -1, 1 };

  hmapCopy(w->hmap);
  hmapCopy(w->wmap);
  for(int i = 0; i < HMAP_SIZE; ++i) {
    for(int j = 0; j < HMAP_SIZE; ++j) {
      double dz = w->wmap->old[i][j] - w->hmap->old[i][j];
      dz *= 0.25;
      if (dz > 0) {
        double sum = 0;
        double v[4] = {};
        for(int k = 0; k < 4; ++k) {
          int ii = ((i+di[k]) + HMAP_SIZE)%HMAP_SIZE;
          int jj = ((j+dj[k]) + HMAP_SIZE)%HMAP_SIZE;
          double vv = w->wmap->old[i][j] - w->wmap->old[ii][jj];
          if (vv < 0) vv = 0;
          //vv = vv*vv*vv;
          v[k] = vv;
          sum += vv;
        }
        double s = wk*sum;
        if (s > dz) s = dz;
        if (sum > 1e-10) {
          for(int k = 0; k < 4; ++k) {
            int ii = ((i+di[k]) + HMAP_SIZE)%HMAP_SIZE;
            int jj = ((j+dj[k]) + HMAP_SIZE)%HMAP_SIZE;
            double vv = v[k]/sum*s;
            w->wmap->map[ii][jj] += v[k]/sum*s;
            w->wmap->map[i][j] -= vv;
            double dh = w->hmap->old[i][j] - w->hmap->map[ii][jj];
            dh *= 0.25;
            if (dh > 0) {
              vv = vv*hk;
              if (vv > dh) vv = dh;
              w->hmap->map[ii][jj] += vv;
              w->hmap->map[i][j] -= vv;
            }
          }
        }
      }
    }
  }
}


double waterEvaporation(Water *w, double k) {
  double sum;
  for(int i = 0; i < HMAP_SIZE; ++i) {
    for(int j = 0; j < HMAP_SIZE; ++j) {
      double dz = w->wmap->map[i][j] - w->hmap->map[i][j];
      if (dz < 0) dz = 0;
      if (dz > k) dz = k;
      sum += dz;
      w->wmap->map[i][j] -= dz;
    }
  }
  return sum;
}


void waterCycle(Water *w, double fallK, double erosionK, double evaK) {
  double sum = waterEvaporation(w, evaK);
  waterRain(w, sum/(HMAP_SIZE*HMAP_SIZE));
  for(int i = 0; i < 10; ++i) {
    waterFall(w, fallK/10, erosionK/10);
    printf(".");
    fflush(stdout);
  }
  printf("\n");
}