Blame simple/world-gen/hmap.inc.c

878d83
878d83
#define HMAP_SIZE 1024
878d83
878d83
878d83
typedef struct {
878d83
  double x, y, z;
878d83
  double nx, ny, nz;
878d83
} Vertex;
878d83
878d83
typedef struct {
878d83
  double (*map)[HMAP_SIZE];
878d83
  double (*old)[HMAP_SIZE];
878d83
  double maps[2][HMAP_SIZE][HMAP_SIZE];
878d83
  double normals[HMAP_SIZE][HMAP_SIZE][3];
878d83
  double stepXY;
878d83
  double stepZ;
878d83
  double color[4];
878d83
  GLuint buf;
878d83
  int bufCount;
878d83
} HMap;
878d83
878d83
878d83
void hmapInit(HMap *hmap, double stepXY, double stepZ, double r, double g, double b, double a) {
878d83
  hmap->map = hmap->maps[0];
878d83
  hmap->old = hmap->maps[1];
878d83
  for(int i = 0; i < HMAP_SIZE; ++i) {
878d83
    for(int j = 0; j < HMAP_SIZE; ++j) {
878d83
      hmap->map[i][j] = 0;
878d83
      hmap->old[i][j] = 0;
878d83
      hmap->normals[i][j][0] = 0;
878d83
      hmap->normals[i][j][1] = 0;
878d83
      hmap->normals[i][j][2] = 0;
878d83
    }
878d83
  }
878d83
  hmap->stepXY = stepXY;
878d83
  hmap->stepZ = stepZ;
878d83
  hmap->color[0] = r;
878d83
  hmap->color[1] = g;
878d83
  hmap->color[2] = b;
878d83
  hmap->color[3] = a;
878d83
878d83
  hmap->buf = 0;
878d83
  hmap->bufCount = 0;
878d83
  glGenBuffers(1, &hmap->buf);
878d83
}
878d83
878d83
878d83
void hmapDeinit(HMap *hmap) {
878d83
  glDeleteBuffers(1, &hmap->buf);
878d83
}
878d83
878d83
878d83
void hmapSwap(HMap *hmap) {
878d83
  double (*m)[HMAP_SIZE] = hmap->map;
878d83
  hmap->map = hmap->old;
878d83
  hmap->old = m;
878d83
}
878d83
878d83
878d83
void hmapCopy(HMap *hmap) {
878d83
  for(int i = 0; i < HMAP_SIZE; ++i)
878d83
    for(int j = 0; j < HMAP_SIZE; ++j)
878d83
      hmap->old[i][j] = hmap->map[i][j];
878d83
}
878d83
878d83
878d83
void hmapGetVertex(const HMap *hmap, int i, int j, Vertex *v) {
878d83
  int ii = (i%HMAP_SIZE + HMAP_SIZE)%HMAP_SIZE;
878d83
  int jj = (j%HMAP_SIZE + HMAP_SIZE)%HMAP_SIZE;
878d83
  v->x = hmap->stepXY*(i - 0.5*HMAP_SIZE);
878d83
  v->y = hmap->stepXY*(j - 0.5*HMAP_SIZE);
878d83
  v->z = hmap->stepZ*hmap->map[ii][jj];
878d83
  v->nx = hmap->normals[ii][jj][0];
878d83
  v->ny = hmap->normals[ii][jj][1];
878d83
  v->nz = hmap->normals[ii][jj][2];
878d83
}
878d83
878d83
878d83
void hmapBuildBuf(HMap *hmap) {
878d83
  static Vertex buf[ (HMAP_SIZE*2 + 4)*HMAP_SIZE*10 ];
878d83
  Vertex *v = buf;
878d83
  for(int j = 0; j < HMAP_SIZE; ++j) {
878d83
    hmapGetVertex(hmap, 0, j, v++);
878d83
    for(int i = 0; i <= HMAP_SIZE; ++i) {
878d83
      hmapGetVertex(hmap, i, j, v++);
878d83
      hmapGetVertex(hmap, i, j+1, v++);
878d83
    }
878d83
    hmapGetVertex(hmap, HMAP_SIZE, j+1, v++);
878d83
  }
878d83
  hmap->bufCount = v - buf;
878d83
878d83
  glBindBuffer(GL_ARRAY_BUFFER, hmap->buf);
878d83
  glBufferData(GL_ARRAY_BUFFER, hmap->bufCount*sizeof(*v), buf, GL_STATIC_DRAW);
878d83
  glBindBuffer(GL_ARRAY_BUFFER, 0);
878d83
}
878d83
878d83
878d83
void hmapDraw(const HMap *hmap) {
878d83
  glColor4dv(hmap->color);
878d83
878d83
  glBindBuffer(GL_ARRAY_BUFFER, hmap->buf);
878d83
  glEnableClientState(GL_VERTEX_ARRAY);
878d83
  glEnableClientState(GL_NORMAL_ARRAY);
878d83
  glVertexPointer(3, GL_DOUBLE, sizeof(Vertex), (const void*)offsetof(Vertex, x));
878d83
  glNormalPointer(GL_DOUBLE, sizeof(Vertex), (const void*)offsetof(Vertex, nx));
878d83
878d83
  glDrawArrays(GL_TRIANGLE_STRIP, 0, hmap->bufCount);
878d83
878d83
  glDisableClientState(GL_VERTEX_ARRAY);
878d83
  glDisableClientState(GL_NORMAL_ARRAY);
878d83
  glBindBuffer(GL_ARRAY_BUFFER, 0);
878d83
878d83
  glColor4d(1, 1, 1, 1);
878d83
}
878d83
878d83
878d83
void hmapDrawWrap(const HMap *hmap) {
878d83
  for(int i = -1; i <= 1; ++i) {
878d83
    for(int j = -1; j <= 1; ++j) {
878d83
      glPushMatrix();
878d83
      glTranslated(HMAP_SIZE*i*hmap->stepXY, HMAP_SIZE*j*hmap->stepXY, 0);
878d83
      hmapDraw(hmap);
878d83
      glPopMatrix();
878d83
    }
878d83
  }
878d83
}
878d83
878d83
double hmapGet(const HMap *hmap, int i, int j) {
878d83
  i = (i%HMAP_SIZE + HMAP_SIZE)%HMAP_SIZE;
878d83
  j = (j%HMAP_SIZE + HMAP_SIZE)%HMAP_SIZE;
878d83
  return hmap->map[i][j];
878d83
}
878d83
878d83
878d83
void hmapCalcNormals(HMap *hmap) {
878d83
  double dxy2 = 4 * hmap->stepXY * hmap->stepXY;
878d83
  for(int i = 0; i < HMAP_SIZE; ++i) {
878d83
    for(int j = 0; j < HMAP_SIZE; ++j) {
878d83
      double dzx = (hmapGet(hmap, i+1, j) - hmapGet(hmap, i-1, j))*hmap->stepZ;
878d83
      double k = 1/sqrt(dzx*dzx + dxy2);
878d83
      double nz = dxy2*k;
878d83
      double nx = -dzx*k;
878d83
878d83
      double dzy = (hmapGet(hmap, i, j+1) - hmapGet(hmap, i, j-1))*hmap->stepZ;
878d83
      k = 1/sqrt(dzy*dzy + dxy2);
878d83
      nz += dxy2*k;
878d83
      double ny = -dzy*k;
878d83
878d83
      k = 1/sqrt(nx*nx + ny*ny + nz*nz);
878d83
      hmap->normals[i][j][0] = nx*k;
878d83
      hmap->normals[i][j][1] = ny*k;
878d83
      hmap->normals[i][j][2] = nz*k;
878d83
    }
878d83
  }
878d83
}
878d83
878d83
878d83
double cubicInterpolation(double x0, double x1, double x2, double x3, float l) {
878d83
    double a = x3 - x2 + x1 - x0;
878d83
    double b = x0 - x1 - a;
878d83
    double c = x2 - x0;
878d83
    double d = x1;
878d83
    return ((a*l + b)*l + c)*l + d;
878d83
}
878d83
878d83
878d83
double hmapGetBicubic(HMap *hmap, double x, double y, int step) {
878d83
  x /= step;
878d83
  y /= step;
878d83
  int i0 = (int)floor(x);
878d83
  int j0 = (int)floor(y);
878d83
  double dx = x - i0;
878d83
  double dy = y - j0;
878d83
878d83
  double m[4][4];
878d83
  for(int i = 0; i < 4; ++i)
878d83
    for(int j = 0; j < 4; ++j)
878d83
      m[i][j]= hmapGet(hmap, (i0 + i - 1)*step, (j0 + j - 1)*step);
878d83
878d83
  return cubicInterpolation(
878d83
    cubicInterpolation(m[0][0], m[1][0], m[2][0], m[3][0], dx),
878d83
    cubicInterpolation(m[0][1], m[1][1], m[2][1], m[3][1], dx),
878d83
    cubicInterpolation(m[0][2], m[1][2], m[2][2], m[3][2], dx),
878d83
    cubicInterpolation(m[0][3], m[1][3], m[2][3], m[3][3], dx),
878d83
    dy );
878d83
}
878d83
878d83
878d83
void hmapGenerate(HMap *hmap) {
878d83
  const int maxStep = HMAP_SIZE/2;
878d83
  const int minStep = 1;
878d83
  const double maxFactor = 0.25*maxStep;
878d83
878d83
  for(int i = 0; i < HMAP_SIZE; i += maxStep)
878d83
    for(int j = 0; j < HMAP_SIZE; j += maxStep)
878d83
        hmap->map[i][j] = (randomFloat() - 0.5)*2*maxFactor;
878d83
878d83
  double factor = 0.5*maxFactor;
878d83
  for(int step = maxStep/2; step >= minStep; step /= 2, factor /= 2) {
878d83
    for(int i = step; i < HMAP_SIZE; i += 2*step)
878d83
      for(int j = step; j < HMAP_SIZE; j += 2*step)
878d83
        hmap->map[i][j] = ( hmapGet(hmap, i - step, j - step)
878d83
                          + hmapGet(hmap, i + step, j - step)
878d83
                          + hmapGet(hmap, i - step, j + step)
878d83
                          + hmapGet(hmap, i + step, j + step) )*0.25
878d83
                        + (randomFloat() - 0.5)*2*factor;
878d83
    for(int i = 0; i < HMAP_SIZE; i += step)
878d83
      for(int j = step*(1 - i/step%2); j < HMAP_SIZE; j += 2*step)
878d83
        hmap->map[i][j] = ( hmapGet(hmap, i - step, j)
878d83
                          + hmapGet(hmap, i + step, j)
878d83
                          + hmapGet(hmap, i, j - step)
878d83
                          + hmapGet(hmap, i, j + step) )*0.25
878d83
                        + (randomFloat() - 0.5)*2*factor;
878d83
  }
878d83
878d83
  if (minStep > 1)
878d83
    for(int i = 0; i < HMAP_SIZE; ++i)
878d83
      for(int j = 0; j < HMAP_SIZE; ++j)
878d83
        if (i % minStep || j % minStep)
878d83
          hmap->map[i][j] = hmapGetBicubic(hmap, i, j, minStep);
878d83
878d83
  hmapCalcNormals(hmap);
878d83
}
878d83