sandbox/Antoonvh/ABL/perlin.h

    Generate Perlin’s noise.

    Here we generate a scalar map via Perlin’s noise procedure.

    double *gradp; //Perlin's gradients
    
    #define DELTAP_x (L0/(double)(nx))
    #define DELTAP_z (L0/(double)(nz))
    #ifndef SMOOTHSTP
    #define SMOOTHSTP(x) (6*cube(x)*sq(x) - 15*sq(sq(x)) + 10*cube(x)) //Perlin's function
    #endif
    #define interps(a0, a1, w) (a0*(1. - w) + a1*w)
    #define IND(j,k) ((2*(j*nz + k)))
    
    void init_perlin (int nx, int nz) {
      gradp = (double*)malloc((nx)*(nz)*sizeof(double)*2);
      for (int j = 0; j < nx; j++) {
        for (int k = 0; k < nz; k++) {
          double ang = noise()*pi;
          gradp[IND(j,k)]     = sin(ang);
          gradp[IND(j,k) + 1] = cos(ang);
        }
      }
    }
    
    double dotprdt (double xp, double xg, double zp, double zg, int j, int k, int nx, int nz) {
      double l = sqrt(sq(DELTAP_x) + sq(DELTAP_z));
      return (((xp - xg)*gradp[IND(j,k)] + (zp - zg)*gradp[IND(j,k) + 1])/l);
    }
    
    double perlin (double xp, double zp, int nx, int nz) {
      
      int j = (int)(((xp - X0)/DELTAP_x) + 0.5);
      int k = (int)(((zp - Z0)/DELTAP_z) + 0.5);
      double xl = X0 + ((double)j - 0.5)*DELTAP_x;
      double xr = xl + DELTAP_x;
      double zb = Z0 + ((double)k - 0.5)*DELTAP_z;
      double zt = zb + DELTAP_z;
      j--; k--;
      if (j < 0) 
        j += nx;
      if (k < 0)
        k += nz;
      double xw = (xp - xl)/DELTAP_x;
      double zw = (zp - zb)/DELTAP_z;
      double n0 = dotprdt (xp, xl, zp, zb, j, k, nx, nz);
      j++;
      if (j >= nx)
        j -= nx;
      double n1 = dotprdt (xp, xr, zp, zb, j, k, nx, nz);
      double ix0 = interps (n0, n1, SMOOTHSTP(xw));
      k++;
      if (k >= nz)
        k -= nz;
      n1 = dotprdt (xp, xr, zp, zt, j, k, nx, nz);
      j--;
      if (j < 0)
        j += nx;
      n0 = dotprdt (xp, xl, zp, zt, j, k, nx, nz);
      double ix1 = interps (n0, n1, SMOOTHSTP(xw));
      return interps (ix0, ix1, SMOOTHSTP(zw));
    }

    Test