Generating Perlin Noise

Someone has been saying that this is not Perlin Noise. If this is not Perlin Noise, tell me how it is not. Here is a link to wiki page. It describes Perlin Noise the same way I implemented it.
http://en.wikipedia.org/wiki/Perlin_noise

This is code I wrote to generate Perlin Noise.

It uses java.Random, and has a restriction of the width, height you specify. Also, it stores data in an array. It has some drawbacks, but should be enough for most uses.



import java.util.Random;

public class PerlinNoise {

	// Just a Random class object so I can fill my noise map with random directions.
	public static final Random random = new Random();

	// Width and Height of the map.
	public int width, height;

	// Random directions of length 1.
	private vec2[] values;

	// Contrast value.
	public float contrast = 1;
	
	private int canvasWidth = 0, canvasHeight = 0;
	
	/**
	 * Creates a noise map with specified dimensions.
	 * @param width of the noise map.
	 * @param height of the noise map.
	 */
	public PerlinNoise(int width, int height) {
		this.width = width;
		this.height = height;

		values = new vec2[(width + 1) * (height + 1)]; // Create an array to store random directions.

		for (int y = 0; y < height + 1; y++) {
			for (int x = 0; x < width + 1; x++) {
				int rot = random.nextInt(359); // Random direction.

				// Store random direction of length 1 to our directions array.
				values[x + y * width] = Rotation.point(new vec2(0, 0), new vec2(0, -1), rot);
			}
		}

		// If you're wondering why "width + 1" "height + 1", it is because map looks blurry 
		// at right and bottom edges of the image without it. Try removing it, you will see.
		
	}
	
	public void setCanvas(int w, int h) {
		this.canvasWidth = w;
		this.canvasHeight = h;
	}

	public float noise(float x, float y) {

		if(canvasWidth != 0 && canvasHeight != 0) {
			x /= canvasWidth * width;
			y /= canvasHeight * height;
		}
		
		if(x >= this.width) throw new IllegalArgumentException("X specified should be between 0 and (width-1)");
		if(y >= this.height) throw new IllegalArgumentException("Y specified should be between 0 and (width-1)");
		
		
		// Grid cell coordinates in integer values.
		int gx0 = (int) (Math.floor(x)); // Top-Left
		int gy0 = (int) (Math.floor(y)); // Top-Left
		int gx1 = gx0 + 1; // Down-Right
		int gy1 = gy0 + 1; // Down-Right

		// Random directions.
		vec2 g00 = g(gx0, gy0); // Top-Left
		vec2 g10 = g(gx1, gy0); // Top-Right
		vec2 g11 = g(gx1, gy1); // Down-Right
		vec2 g01 = g(gx0, gy1); // Down-Left

		// Subtract grid cells values from the point specified.
		vec2 delta00 = new vec2(x - gx0, y - gy0); // Top-Left
		vec2 delta10 = new vec2(x - gx1, y - gy0); // Top-Right
		vec2 delta11 = new vec2(x - gx1, y - gy1); // Down-Right
		vec2 delta01 = new vec2(x - gx0, y - gy1); // Down-Left

		// Compute a dot product between random directions and corresponding delta values.
		float s = dot(g00, new vec2(delta00.x, delta00.y)); // Top-Left
		float t = dot(g10, new vec2(delta10.x, delta10.y)); // Top-Right
		float u = dot(g11, new vec2(delta11.x, delta11.y)); // Down-Right
		float v = dot(g01, new vec2(delta01.x, delta01.y)); // Down-Left

		// Compute the weights for x and y axis.
		float sx = weigh(delta00.x);
		float sy = weigh(delta00.y);
		
		// Interpolate between values.
		float a = lerp(sy, s, v); // Interpolate Top-Left(s) and Down-Left(v). We can also call this LEFT
		float b = lerp(sy, t, u); // Interpolate Top-Right(t) and Down-Right(u) We can also call this RIGHT
		float h = lerp(sx, a, b); // Interpolate LEFT(a) and RIGHT(b). We can call this height(h)

		h *= contrast; // Multiply here so adjust contrast.
		
		// Make sure it is -1 to 1. If you don't change contrast, you don't have to do this.
		if(h > 1) h = 1;
		if(h < -1) h = -1;
		
		return h;
	}

	/**
	 * Computes a weight using S-curve function f(x) = 3 * (x * x) - 2 * (x * x * x).
	 * @param x NOT as in axis, but as a variable.
	 */
	private float weigh(float x) {
		return 3 * (x * x) - 2 * (x * x * x);
	}
	
	/**
	 * Interpolate between 2 values, using weight.
	 */
	private float lerp(float weight, float a, float b) {
		float result = a + weight * (b - a);
		return result;
	}
	
	/**
	 * Compute a dot product.
	 * Example: dot product between (a, b) and (c, d) is:
	 * a * c + b * d
	 */
	private float dot(vec2 v0, vec2 v1) {
		return (v0.x * v1.x) + (v0.y * v1.y);
	}

	/**
	 * Get the random direction.
	 */
	private vec2 g(int x, int y) {
		if (x < 0) x = 0;
		if (y < 0) y = 0;
		if (x >= width) x = width;
		if (y >= height) y = height;
		return values[x + y * width];
	}

	public static class vec2 {

		public float x, y;

		/**
		 * Just holds some float values.
		 * @param x
		 * @param y
		 */
		public vec2(float x, float y) {
			this.x = x;
			this.y = y;
		}
		
		public int getX() {
			return (int) x;
		}
		public int getY() {
			return (int) y;
		}
		
	}
	
	public static class Rotation {

		/** 
		 * Rotates specified point around pivot.
		 * @param pivot to rotate around.
		 * @param point to rotate around pivot.
		 * @param rotation - how many degrees to rotate.
		 * @return a new point, which was created by rotating given point around pivot by some degrees.
		 */
		public static vec2 point(vec2 pivot, vec2 point, float rotation) {
			
			float rot = (float)(1f / 180 * rotation * Math.PI);
			
			float x = point.x - pivot.x;
			float y = point.y - pivot.y;
			
			float newx = (float)(x * Math.cos(rot) - y * Math.sin(rot));
			float newy = (float)(x * Math.sin(rot) + y * Math.cos(rot));
			
			
			newx += pivot.x;
			newy += pivot.y;
			
			return new vec2(newx, newy);
		}
					
	}
	
}

This isn’t Perlin Noise though?

Then what is Perlin Noise? Explain.

Since you know how Perlin Noise works and how to implement it, could you post it here? I would be willing to learn.

Looks pretty much like simple 2d perlin noise to me. Perlin noise is just an algorithm.

I agree with jonjava. Looks pretty much like this article teaches:webstaff

I believe what opiop meant was that I’m storing values in an array. But this is still perlin noise.

Sorry, no I didn’t realize that was perlin noise.

Where else would you store your values? You need to have an array of some sort to at least throw your newly generated points using perlin noise into your terrain renderer so it can create a mesh.

The title is “Generating Perlin Noise” not “Generated Perlin Noise array”. This code will allow you to calculate the output array to your liking. Perlin Noise is an algorithm to generate smooth looking noise. It is not the generated product. IT IS ALGORITHM.

The nice thing about actual Perlin Noise, or better actual noise algorithms is that they’re deterministic.

Perlin noise is also often called a Noise Function.
So what does a function actually look like?
f(x) = whateveryoudowithyourx
For example
f(x) = 6x<sup>5</sup> - 15x<sup>4</sup> + 10x<sup>3</sup>
The nice thing about this function is you can call f(10) a million times and it will always give the same result.
Or generally speaking: A function that always gives the same result for the same input is called deterministic.
What’s nice about this? In minecraft the noise function looks like this: n(x, y, z, seed) = …
So at each position the minecraft world looks the same, as long as the seed is the same one.

Another property a function has is it’s infinity.
You can call f(x) with x = 1, x = 10, x = 100, x = 101000, as long as your number implementation allows it (with that I mean it wouldn’t work for [icode]int[/icode]s, i.e.). It’s out of the question that the function doesn’t stop at some kind of x value.
What’s nice about that? You can walk in one direction in minecraft almost infinitely. For generating the terrain minecraft only needs the position at which to generate whatever. It’s not liminted by any width bounds or similar.

So an actual noise function (in 2D) would look like that: n(x, y, seed) = ..., or in programming terms (and if you leave out the seed):


public float noise(float x, float y) { ... }

:wink:

So how would you generate an array of values out of this? Simply call it a couple of times with the array index as input.

That answer was kind of bloated but it’s intention was not answering a question but giving some trivia and trying to create some ‘ahaaaa’ moments :slight_smile:

PS: Ironically, with “actual” perlin noise I am talking about perlin noise that’s not dependent on any canvas size and is deterministic ;D
Still perlin noise, though! :slight_smile:

EDIT:
Having fully read through the source code now, it looks like he is only a small step away from a purely deterministic implementation that isn’t dependent on a specific size.

What he is doing is precomputing an array of unit vectors pointing in a random direction sequentially.
What he would need to change (if he even wanted such an implementation) is get a hashing function that takes two int arguments and produces a unit vector pointing in a random direction. Thats somehow what his method [icode]vec2 g(int x, int y)[/icode] is, but it can only return random unit vectors from inside the width-height-bounds. The next step (if even wanted) would be to code some hashing magic into that function to return a random unit vector from any (x, y).

Again, his implementation is perlin noise, I’m just explaining what I mean by ‘noise function’ and how it would be implemented.

Not true. As long as you’re working with finite numbers, you will never get close to infinity. :wink:

Yup. That’s what I was talking about when I said

This isn’t a reasonable way to generate noise.

On infinity. It’s a mathematical abstract. I can generate more unique images/terrains/whatever than you could ever look at…so it’s effectively infinite even though I’d only be working with finite numbers. Look at the magnitude local wiki page.