具有负坐标输入的Perlin噪声

时间:2012-05-22 15:56:25

标签: java interpolation noise perlin-noise negative-number

我的perlin噪声实现似乎有问题......每当我输入负坐标时,perlin噪声都不会平滑。我发现有些人和我一样有同样的问题,但除了我发现的this文章之外,没有人真的有解决方案。我在解决方案中工作,但这一代并没有修复。 (我可能做错了)这是我在Java中的Perlin Noise实现:

public B15(long seed, int f) {
    this.seed = seed;
    this.f = f;
    rand = new Random();
}

public static double[][] getTerrainFromChunks(int cX, int cY, int octaves, double[] amp, int[] freq, long seed) {
    double[][] noise = new double[16][16];
    for(int z = 0; z < octaves; z++) {
        B15 oct = new B15(seed, freq[z]);
        for(int y = 0; y < 16; y++) {
            for(int x = 0; x < 16; x++) {
                noise[x][y] = noise[x][y] + (amp[z] * oct.getNoiseLevelAtPosition((cX * 16) + x, (cY * 16) + y));
            }
        }
    }
    return noise;
}

public double getNoiseLevelAtPosition(int x, int y) {
    int xmin = (int) (double) x / f; 
    int xmax = xmin + 1;
    int ymin = (int) (double) y / f;
    int ymax = ymin + 1;
    return cosineInterpolate(
            cosineInterpolate((float) getRandomAtPosition(xmin, ymin), 
                    (float) getRandomAtPosition(xmax, ymin), (float) (x - xmin * f) / f),
            cosineInterpolate((float) getRandomAtPosition(xmin, ymax), 
                    (float) getRandomAtPosition(xmax, ymax), (float) (x - xmin * f) / f),
            ((float) y - (float) ymin * (float) f) / (float) f);
}

private float cosineInterpolate(float a, float b, float x) {
    float f = (float) ((1f - Math.cos(x * Math.PI)) * .5f);
    return a * (1f - f) + b * f;
}

private double getRandomAtPosition(int x, int y) {
    rand.setSeed((long) (10000 * (Math.sin(x) + Math.cos(y) + Math.tan(seed))));
    return rand.nextDouble();
}

我在明显的解决方案中工作如下:

public double getNoiseLevelAtPosition(int x, int y) {
    int xmin = (int) (double) x / f; 
    int xmax = xmin + 1;
    int ymin = (int) (double) y / f;
    int ymax = ymin + 1;
    x -= xmin;                                         |
    y -= ymin;                                         | - New Code which
    if(x < 0) { x += 1; xmax = (xmax + 255) & 255; }   |   I hoped would fix 
    if(y < 0) { y += 1; ymax = (ymax + 255) & 255; }   |   the issue
    return cosineInterpolate(
            cosineInterpolate((float) getRandomAtPosition(xmin, ymin), 
                    (float) getRandomAtPosition(xmax, ymin), (float) (x - xmin * f) / f),
            cosineInterpolate((float) getRandomAtPosition(xmin, ymax), 
                    (float) getRandomAtPosition(xmax, ymax), (float) (x - xmin * f) / f),
            ((float) y - (float) ymin * (float) f) / (float) f);
}

抱歉,我没有任何视觉图片,但上面的文章中有我的问题的图片,但它们是3维。如果它甚至可以解决,有没有人对如何解决这个问题有任何想法?谢谢!

编辑:这是解决方案的更新代码,但它只是在负x轴上反映了这一代...(实际上在整个x轴上包括正面和负面)

public B15(long seed, int f) {
    this.seed = seed;
    this.f = f;
    rand = new Random();
}

public static double[][] getTerrainFromChunks(int cX, int cY, int octaves, double[] amp, int[] freq, long seed) {
    double[][] noise = new double[16][16];
    for(int z = 0; z < octaves; z++) {
        B15 oct = new B15(seed, freq[z]);
        for(int y = 0; y < 16; y++) {
            for(int x = 0; x < 16; x++) {
                noise[x][y] = noise[x][y] + (amp[z] * oct.getNoiseLevelAtPosition((cX * 16) + x, (cY * 16) + y));
            }
        }
    }
    return noise;
}

public double getNoiseLevelAtPosition(int x, int y) {
    int xmin = (int) Math.floor((double) x / f); 
    int xmax = xmin + 1;
    int ymin = (int) Math.floor((double) y / f); 
    int ymax = ymin + 1;
    return cosineInterpolate(
            cosineInterpolate((float) getRandomAtPosition(xmin, ymin), 
                    (float) getRandomAtPosition(xmax, ymin), (float) (x - xmin * f) / f),
            cosineInterpolate((float) getRandomAtPosition(xmin, ymax), 
                    (float) getRandomAtPosition(xmax, ymax), (float) (x - xmin * f) / f),
            ((float) y - (float) ymin * (float) f) / (float) f);
}

private float cosineInterpolate(float a, float b, float x) {
    float f = (float) ((1f - Math.cos(x * Math.PI)) * .5f);
    return a * (1f - f) + b * f;
}

private double getRandomAtPosition(int x, int y) {
    rand.setSeed((long) (10000 * (Math.sin(x) + Math.cos(y) + Math.tan(seed))));
    return rand.nextDouble();
}

0 个答案:

没有答案