2
\$\begingroup\$

I've decided to code Perlin noise generator in Java. It works pretty well, I just want to know If I am doing everything right and if it is a valid implementation!

PS : The metaVector2f and metaVector2i are just 2D vector classes

public float[][] generate(long seed, metaVector2i size, metaVector2i gridSize) {
    Random rand = new Random(seed);
    metaVector2f[][] gvectors = new metaVector2f[gridSize.x][gridSize.y];

    for (int y = 0; y < gridSize.y; y++)
        for (int x = 0; x < gridSize.x; x++)
            gvectors[x][y] = new metaVector2f(rand.nextFloat(),rand.nextFloat());

    float[][] data = new float[size.x][size.y];

    for (int y = 0; y < size.y; y++)
        for (int x = 0; x < size.x; x++) {
            data[x][y] = perlinPoint(new metaVector2f(x/(float)(size.x/gridSize.x),y/(float)(size.y/gridSize.y)), gvectors);
        }

    return data;
}

private float perlinPoint(metaVector2f position, metaVector2f[][] gvectors) {

    int x0 = (int)position.x;
    int y0 = (int)position.y;
    int x1 = (int)position.x+1;
    int y1 = (int)position.y+1;

    float dx0 = position.x-x0;
    float dy0 = position.y-y0;

    float dx1 = position.x-x1;
    float dy1 = position.y-y1;

    float h1 = dotProduct(new metaVector2f(dx0, dy0), gvectors[x0%gvectors.length][y0%gvectors[0].length]);
    float h2 = dotProduct(new metaVector2f(dx1, dy0), gvectors[x1%gvectors.length][y0%gvectors[0].length]);
    float fin1 = lerp(h1, h2, dx0);

    float v1 = dotProduct(new metaVector2f(dx0, dy1), gvectors[x0%gvectors.length][y1%gvectors[0].length]);
    float v2 = dotProduct(new metaVector2f(dx1, dy1), gvectors[x1%gvectors.length][y1%gvectors[0].length]);
    float fin2 = lerp(v1, v2, dx0);

    return lerp(fin1,fin2,dy0);

}

private float lerp(float x, float y, float t) {
    return (1.0f - t)*x + t*y;
}

private float dotProduct(metaVector2f vec, metaVector2f grad) {
    return vec.x*grad.x+vec.y*grad.y;
}

Here is the output (value/2+0.5f) :

1

\$\endgroup\$
  • \$\begingroup\$ That output doesn't look right. Generally the x/y coordinates within each square are passed through a smoothstep function, otherwise you get those artifacts around the edges of each square (can clearly see a 10x10 grid here, it shouldn't be that apparent). This article is good if you haven't seen it: flafla2.github.io/2014/08/09/perlinnoise.html \$\endgroup\$ – user11536834 Jul 24 at 23:12
1
\$\begingroup\$

Consider warmwaffle's code at GitHub (re: https://github.com/warmwaffles/Noise). The one difference I see between the two solutions is how the 'metaVector2f's are created. Your code is using non-repeatable random numbers; whereas, the other uses a mathematical calculation which includes prime numbers and bit shifting operations. The latter would produce a repeatable solution with the same seed versus yours. This may be worth something if you're testing or troubleshooting elsewhere.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.