0

So I've been trying to implement Perlin noise recently, and have run into some unusual problems. Whenever the edges of the grid in which the random vectors are stored are crossed, the derivative appears to be discontinuous.

Here's a link to a picture of the output (on the right), along with a 1 dimensional slice (on the left).

The Output

class perlin{
private double[][][] grid;
public perlin(int x,int y, int seed){
    Random r = new Random(seed);
    grid = new double[x+1][y+1][2];
    for(int i=0;i<grid.length;i++){
        for(int j=0;j<grid[0].length;j++){
            grid[i][j][0] = 2*r.nextDouble()-1;
            grid[i][j][1] = 2*r.nextDouble()-1;
        }
    }
}
public static double lerp(double a, double b, double t){
    double c = t * t * t * (t * (t * 6 - 15) + 10);
    return (b * c) + (a * (1 - c));
}
public double get(double x, double y){
    double x2;
    double y2;
    double x3;
    double y3;
    x2 = x * (grid.length-1);
    y2 = y * (grid[0].length-1);
    x3 = down(x2);
    y3 = down(y2);
    x2 = x2 - x3;
    y2 = y2 - y3;
    int i = (int) (x3);
    int j = (int) (y3);
    return lerp(lerp(dot(x2, y2, grid[i][j][0], grid[i][j][1] ), dot(1 - x2, y2, grid[i + 1][j][0], grid[i + 1][j][1]),x2), lerp(dot(x2, 1 - y2, grid[i][j + 1][0], grid[i][j +1][1] ), dot(1 - x2,1 -  y2, grid[i + 1][j + 1][0], grid[i + 1][j + 1][1] ), x2),y2 );
//  return 0;
}
public static double dot(double x1, double y1, double x2, double y2){
    return x1 * x2 + y1 * y2;
}
private static double down(double a){
    if (a == 0){
        return 0;
    }
    if(a == Math.floor(a)){
        return a - 1;
    }else{
        return Math.floor(a);
    }
}
}

From what I understand about the math behind this, the derivative of the noise should be continuous at all points, but that does not appear to be the case.

  • It does not look like you code matches what is in the wikipedia article. There it say the gradient vectors should lie on the unit circle. Yours seem to be in the anywhere in the interval [-1,1]X[-1,1]. To fix this you constructor would use something like `double angle = r.nextDouble() * 2 * pi; grid[i][j][0] = cos(angle); grid[i][j][1]=sin(angle);` – Salix alba Oct 11 '15 at 21:07
  • 1
    Your lerp function looks really odd. You have `double c = t * t * t * (t * (t * 6 - 15) + 10);` a quintic. Lerp should be linear interpolation. You probably just want `return (b * t) + (a * (1 - t));` – Salix alba Oct 11 '15 at 21:24

0 Answers0