Java 中的柏林噪声

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5531019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:33:41  来源:igfitidea点击:

Perlin Noise in Java

javarandomnoise

提问by jt78

For a cellular automata project I'm working on I need to generate two dimensional boolean arrays randomly using different algorithms and techniques. At the moment I have just one type of randomization in the application - looping through every cell in the array and generating a random double variable, then if the random number is higher than 0.5 then I set that cell to true, if not it gets set to false.

对于我正在进行的元胞自动机项目,我需要使用不同的算法和技术随机生成二维布尔数组。目前,我在应用程序中只有一种类型的随机化 - 循环遍历数组中的每个单元格并生成一个随机双变量,然后如果随机数高于 0.5,那么我将该单元格设置为 true,如果不是则设置为假。

I would like to look into generating these boolean matrices using more interesting algorithms such as Perlin Noise or something like that. Noise generators that are used in terrain generation or something like that might be good if you know of any other than Perlin Noise (Minecraft's world generation gave me this idea).

我想研究使用更有趣的算法(例如 Perlin Noise 或类似算法)生成这些布尔矩阵。如果您知道除 Perlin Noise(Minecraft 的世界生成给了我这个想法)之外的任何其他东西,那么用于地形生成或类似的噪声生成器可能会很好。

The only problem is I have no idea where to start (any ideas?) :)

唯一的问题是我不知道从哪里开始(任何想法?):)

回答by Simon G.

The first thing I thought of was a random displacement fractal. It is also used to generate terrain and is easier than Perlin Noise.

我首先想到的是随机位移分形。它也用于生成地形,比 Perlin Noise 更容易。

package so;

import java.util.Random;

public class Noise {
    /** Source of entropy */
    private Random rand_;

    /** Amount of roughness */
    float roughness_;

    /** Plasma fractal grid */
    private float[][] grid_;


    /** Generate a noise source based upon the midpoint displacement fractal.
     * 
     * @param rand The random number generator
     * @param roughness a roughness parameter
     * @param width the width of the grid
     * @param height the height of the grid
     */
    public Noise(Random rand, float roughness, int width, int height) {
        roughness_ = roughness / width;
        grid_ = new float[width][height];
        rand_ = (rand == null) ? new Random() : rand;
    }


    public void initialise() {
        int xh = grid_.length - 1;
        int yh = grid_[0].length - 1;

        // set the corner points
        grid_[0][0] = rand_.nextFloat() - 0.5f;
        grid_[0][yh] = rand_.nextFloat() - 0.5f;
        grid_[xh][0] = rand_.nextFloat() - 0.5f;
        grid_[xh][yh] = rand_.nextFloat() - 0.5f;

        // generate the fractal
        generate(0, 0, xh, yh);
    }


    // Add a suitable amount of random displacement to a point
    private float roughen(float v, int l, int h) {
        return v + roughness_ * (float) (rand_.nextGaussian() * (h - l));
    }


    // generate the fractal
    private void generate(int xl, int yl, int xh, int yh) {
        int xm = (xl + xh) / 2;
        int ym = (yl + yh) / 2;
        if ((xl == xm) && (yl == ym)) return;

        grid_[xm][yl] = 0.5f * (grid_[xl][yl] + grid_[xh][yl]);
        grid_[xm][yh] = 0.5f * (grid_[xl][yh] + grid_[xh][yh]);
        grid_[xl][ym] = 0.5f * (grid_[xl][yl] + grid_[xl][yh]);
        grid_[xh][ym] = 0.5f * (grid_[xh][yl] + grid_[xh][yh]);

        float v = roughen(0.5f * (grid_[xm][yl] + grid_[xm][yh]), xl + yl, yh
                + xh);
        grid_[xm][ym] = v;
        grid_[xm][yl] = roughen(grid_[xm][yl], xl, xh);
        grid_[xm][yh] = roughen(grid_[xm][yh], xl, xh);
        grid_[xl][ym] = roughen(grid_[xl][ym], yl, yh);
        grid_[xh][ym] = roughen(grid_[xh][ym], yl, yh);

        generate(xl, yl, xm, ym);
        generate(xm, yl, xh, ym);
        generate(xl, ym, xm, yh);
        generate(xm, ym, xh, yh);
    }


    /**
     * Dump out as a CSV
     */
    public void printAsCSV() {
        for(int i = 0;i < grid_.length;i++) {
            for(int j = 0;j < grid_[0].length;j++) {
                System.out.print(grid_[i][j]);
                System.out.print(",");
            }
            System.out.println();
        }
    }


    /**
     * Convert to a Boolean array
     * @return the boolean array
     */
    public boolean[][] toBooleans() {
        int w = grid_.length;
        int h = grid_[0].length;
        boolean[][] ret = new boolean[w][h];
        for(int i = 0;i < w;i++) {
            for(int j = 0;j < h;j++) {
                ret[i][j] = grid_[i][j] < 0;
            }
        }
        return ret;
    }


    /** For testing */
    public static void main(String[] args) {
        Noise n = new Noise(null, 1.0f, 250, 250);
        n.initialise();
        n.printAsCSV();
    }
}

random displacement fractal plot 1random displacement fractal plot 2random displacement fractal plot 3

随机位移分形图 1随机位移分形图 2随机位移分形图 3

回答by mikera

I have some perlin noise implementations and some other noise generation functions in my library code:

我的库代码中有一些柏林噪声实现和一些其他噪声生成函数:

http://code.google.com/p/mikeralib/source/browse/#svn%2Ftrunk%2FMikera%2Fsrc%2Fmain%2Fjava%2Fmikera%2Fmath

http://code.google.com/p/mikeralib/source/browse/#svn%2Ftrunk%2FMikera%2Fsrc%2Fmain%2Fjava%2Fmikera%2Fmath

Feel free to explore / use (code is open source GPL, based on the J3D code).

随意探索/使用(代码是开源GPL,基于J3D代码)。