Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perlin Noise in Java

Tags:

java

random

noise

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.

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).

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

like image 756
jt78 Avatar asked Apr 03 '11 16:04

jt78


People also ask

Does Minecraft use Perlin noise?

Minecraft is specifically using Perlin noise calculations, like the kind you'd use to create a rough-looking texture for a 3D model. It starts out on a very broad level, painting a basic topographical map, and adds "noise" through finer terrain details like lakes, shrubbery and animals.

How 2D Perlin noise is generated?

Perlin's approach to producing a noisy 2-dimensional terrain involves computing a random 2- dimensional gradient vector at each vertex of the grid with the eventual aim that the smoothed noise function have this gradient value.

What is 2D Perlin noise?

The Perlin Noise 2D modifier adds one-dimensional Perlin noise to the stroke. The modifier generates noisy displacements using 2D coordinates of stroke vertices as the input of the noise generator.


1 Answers

The first thing I thought of was a random displacement fractal. It is also used to generate terrain and is easier than 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

like image 184
Simon G. Avatar answered Oct 11 '22 04:10

Simon G.