0

I've been trying to implement a perlin noise generator in java, based on this article. Homever, my generator produces noise that is not continuous but instead "blocky", forming visible lines between every even numbered -coordinate. Below is my current code:

private static final Point[] grads = {
    new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(0, -1),
    new Point(1, 1), new Point(1, -1), new Point(-1, 1), new Point(-1, -1)
};

private int permutations[] = new int[512];

private int frequency;
private int seed;
private double[][] heightMap;
private double amplitude;

public PerlinNoise(int frequency, int seed, double[][] heightMap, double amplitude) {
    this.frequency = frequency;
    this.seed = seed; //Seed for randomizing the permutation table
    this.heightMap = heightMap; //The Heightmap where the finalt result will be stored
    this.amplitude = amplitude;
}

private void seedPermutationTables() {
    LinkedList<PermutationValue> l = new LinkedList<PermutationValue>();
    Random rand = new Random(this.seed);
    for (int i = 0; i < 256; i++) {
        l.add(new PermutationValue(i, rand));
    }
    Collections.sort(l);
    for (int i = 0; i < 512; i++) {
        permutations[i] = l.get(i & 255).getValue();
    }
}

public void generateNoise() {
    this.seedPermutationTables();
    int sWidth = this.heightMap.length / frequency;
    int sHeight = this.heightMap[0].length / frequency;
    for (int i = 0; i < this.heightMap.length; i++) {
        for (int j = 0; j < this.heightMap[i].length; j++) {
            double x = (double)i / sWidth;
            double y = (double)j / sHeight;
            this.heightMap[i][j] = this.noise(x, y);
        }
    }
}

private double noise(double x, double y) {
    int xi = (int)x & 255;
    int yi = (int)y & 255;
    double xf = x - (int)x;
    double yf = y - (int)y;

    double u = this.fade(xf);
    double v = this.fade(yf);

    int aa = permutations[permutations[xi] + yi];               
    int ab = permutations[permutations[xi] + yi + 1];           
    int ba = permutations[permutations[xi + 1] + yi];           
    int bb = permutations[permutations[xi + 1] + yi + 1];       

    double x1 = this.lerp(this.grad(aa, xf, yf), this.grad(ab, xf - 1, yf), u);
    double x2 = this.lerp(this.grad(ba, xf, yf - 1), this.grad(bb, xf - 1, yf - 1), u);
    double noise = this.lerp(x1, x2, v);
    return (1D + noise) / 2 * this.amplitude;   //The noise returns values between -1 and 1
                                                //So we change the range to 0-amplitude
}

private double grad(int hash, double x, double y) {
    hash = hash & 7;
    Point p = grads[hash];
    return p.x * x + p.y * y;
}

private double lerp(double a, double b, double x) {
    return a + x * (b - a);
}

private double fade(double x) {
    return x * x * x * (x * (x * 6 - 15) + 10);
}

private class PermutationValue implements Comparable<PermutationValue> {
    private int value;
    private double sortValue;

    public PermutationValue(int value, Random rand) {
        this.setValue(value);
        this.sortValue = rand.nextDouble();
    }

    @Override
    public int compareTo(PermutationValue pv) {
        if (pv.sortValue > this.sortValue) {
            return -1;
        }
        return 1;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    } 
}

The heightmap array simply stores the height value for every pixel. Any suggestions or ideas what might be causing these formations?

Mr. Noise
  • 1
  • 1

1 Answers1

0

hash tables can be replaced with 1-2 multiplications as in rndng fct: blocky can come from lack of cubic interpolation or digital noise from the hash table. in your case it sounds like it's not lerping between two values of the hash table. lerp just takes any 2 values and smooths between them. so if that's not running ok, it's blocky.

function rndng ( n: float ): float //total noise pseudo
{//random proportion -1, 1
    var e = ( n *321.9)%1;
    return  (e*e*111.0)%2-1;
}


function lerps(o:float, v:float, alpha:float):float
{
    o += ( v - o ) * alpha;
    return o;
}

function lnz ( vtx: Vector3 ): float//3d noise
{   
    vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
    var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
    var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
    D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
    var W = I.x + I.y*71.0 + 125.0*I.z;

    return lerps(           
                lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
                ,
                lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
                ,
                D.z
                );
}

function lnzo ( vtx: Vector3 ): float
{
    var total = 0.0;    
    for (var i:int = 1; i < 5; i ++)
    {
        total+= lnz2(Vector3 (vtx.x*(i*i),0.0,vtx.z*(i*i)))/(i*i);
    }

    return total*5;

}
function lnzh ( vtx: Vector3 ): float//3 axis 3d noise
{   
    vtx= Vector3 ( Mathf.Abs(vtx.z) , Mathf.Abs(vtx.z*.5-vtx.x*.866) , Mathf.Abs(vtx.z*.5+vtx.x*.866) ) ;
    var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
    var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
   //D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
    var W = I.x + I.y*71.0 + 125.0*I.z;

    return lerps(           
                lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.y)
                ,
                lerps( lerps(rndng(W+125.0),rndng(W+126.0),D.x) , lerps(rndng(W+153.0),rndng(W+154.0),D.x) , D.y)
                ,
                D.z
                );
}

function lnz2 ( vtx: Vector3 ): float//2d noise
{   
    vtx= Vector3 ( Mathf.Abs(vtx.x) , Mathf.Abs(vtx.y) , Mathf.Abs(vtx.z) ) ;
    var I = Vector3 (Mathf.Floor(vtx.x),Mathf.Floor(vtx.y),Mathf.Floor(vtx.z));
    var D = Vector3(vtx.x%1,vtx.y%1,vtx.z%1);
    D = Vector3(D.x*D.x*(3.0-2.0*D.x),D.y*D.y*(3.0-2.0*D.y),D.z*D.z*(3.0-2.0*D.z));
    var W = I.x + I.y*71.0 + 125.0*I.z;

    return lerps(       
                lerps( lerps(rndng(W+0.0),rndng(W+1.0),D.x) , lerps(rndng(W+71.0),rndng(W+72.0),D.x) , D.z)
                ,
                lerps( rndng(W+125.0), rndng(W+126.0),D.x)
                ,
                D.z
                );                  
}
bandybabboon
  • 2,210
  • 1
  • 23
  • 33