Created
September 12, 2014 15:27
-
-
Save Sythelux/7381b22837ee7f715242 to your computer and use it in GitHub Desktop.
PerlinNoise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.util.Arrays; | |
| import java.util.Random; | |
| /** | |
| * I'm not the Author of this Implementation, I just capsuled it the way i want it. Should I ever find him/her I will put them in here | |
| * | |
| * Perlin Noise is Noise Generator by Ken Perlin. | |
| * @author <unknown>,sythelux, origin: Ken Perlin | |
| */ | |
| public class PerlinNoise { | |
| private static int Scale = 0x100; | |
| private float numOctaves = 1; | |
| private Random randomGenerator; | |
| public PerlinNoise(long seed, float numOctaves) { | |
| randomGenerator = new Random(seed); | |
| this.numOctaves = numOctaves; | |
| init(); | |
| } | |
| public PerlinNoise(float numOctaves) { | |
| randomGenerator = new Random(); | |
| this.numOctaves = numOctaves; | |
| init(); | |
| } | |
| public PerlinNoise() { | |
| randomGenerator = new Random(); | |
| init(); | |
| } | |
| public boolean getb(float x) { | |
| return getf(x) >= 0; | |
| } | |
| public boolean getb(float x, float y) { | |
| return getf(x, y) >= 0; | |
| } | |
| public boolean getb(float x, float y, float z) { | |
| return getf(x, y, z) >= 0; | |
| } | |
| public float getf(float x) { | |
| return turbulence(x / Scale, numOctaves); | |
| } | |
| public float getf(float x, float y) { | |
| return turbulence(x / Scale, y / Scale, numOctaves); | |
| } | |
| public float getf(float x, float y, float z) { | |
| return turbulence(x / Scale, y / Scale, z / Scale, numOctaves); | |
| } | |
| /** | |
| * Compute turbulence using Perlin noise. | |
| * | |
| * @param x the x value | |
| * @param y the y value | |
| * @param octaves number of octaves of turbulence | |
| * @return turbulence value at (x,y) | |
| */ | |
| public float turbulence(float x, float octaves) { | |
| float t = 0.0f; | |
| for (float f = 1.0f; f <= octaves; f *= 2) | |
| t += noise(f * x) / f; | |
| return t; | |
| } | |
| /** | |
| * Compute turbulence using Perlin noise. | |
| * | |
| * @param x the x value | |
| * @param y the y value | |
| * @param octaves number of octaves of turbulence | |
| * @return turbulence value at (x,y) | |
| */ | |
| public float turbulence(float x, float y, float octaves) { | |
| float t = 0.0f; | |
| for (float f = 1.0f; f <= octaves; f *= 2) | |
| t += noise(f * x, f * y) / f; | |
| return t; | |
| } | |
| /** | |
| * Compute turbulence using Perlin noise. | |
| * | |
| * @param x the x value | |
| * @param y the y value | |
| * @param octaves number of octaves of turbulence | |
| * @return turbulence value at (x,y) | |
| */ | |
| public float turbulence(float x, float y, float z, float octaves) { | |
| float t = 0.0f; | |
| for (float f = 1.0f; f <= octaves; f *= 2) | |
| t += noise(f * x, f * y, f * z) / f; | |
| return t; | |
| } | |
| private final static int B = 0x100; | |
| private final static int BM = 0xff; | |
| private final static int N = 0x1000; | |
| int[] p = new int[B + B + 2]; | |
| float[][] g3 = new float[B + B + 2][3]; | |
| float[][] g2 = new float[B + B + 2][2]; | |
| float[] g1 = new float[B + B + 2]; | |
| private float sCurve(float t) { | |
| return t * t * (3.0f - 2.0f * t); | |
| } | |
| /** | |
| * Compute 1-dimensional Perlin noise. | |
| * | |
| * @param x | |
| * the x value | |
| * @return noise value at x in the range -1..1 | |
| */ | |
| public float noise(float x) { | |
| int bx0, bx1; | |
| float rx0, rx1, sx, t, u, v; | |
| t = x + N; | |
| bx0 = ((int) t) & BM; | |
| bx1 = (bx0 + 1) & BM; | |
| rx0 = t - (int) t; | |
| rx1 = rx0 - 1.0f; | |
| sx = sCurve(rx0); | |
| u = rx0 * g1[p[bx0]]; | |
| v = rx1 * g1[p[bx1]]; | |
| return 2.3f * linearInterpolation(sx, u, v); | |
| } | |
| /** | |
| * Compute 2-dimensional Perlin noise. | |
| * | |
| * @param x | |
| * the x coordinate | |
| * @param y | |
| * the y coordinate | |
| * @return noise value at (x,y) | |
| */ | |
| public float noise(float x, float y) { | |
| int bx0, bx1, by0, by1, b00, b10, b01, b11; | |
| float rx0, rx1, ry0, ry1, q[], sx, sy, a, b, t, u, v; | |
| int i, j; | |
| t = x + N; | |
| bx0 = ((int) t) & BM; | |
| bx1 = (bx0 + 1) & BM; | |
| rx0 = t - (int) t; | |
| rx1 = rx0 - 1.0f; | |
| t = y + N; | |
| by0 = ((int) t) & BM; | |
| by1 = (by0 + 1) & BM; | |
| ry0 = t - (int) t; | |
| ry1 = ry0 - 1.0f; | |
| i = p[bx0]; | |
| j = p[bx1]; | |
| b00 = p[i + by0]; | |
| b10 = p[j + by0]; | |
| b01 = p[i + by1]; | |
| b11 = p[j + by1]; | |
| sx = sCurve(rx0); | |
| sy = sCurve(ry0); | |
| q = g2[b00]; | |
| u = rx0 * q[0] + ry0 * q[1]; | |
| q = g2[b10]; | |
| v = rx1 * q[0] + ry0 * q[1]; | |
| a = linearInterpolation(sx, u, v); | |
| q = g2[b01]; | |
| u = rx0 * q[0] + ry1 * q[1]; | |
| q = g2[b11]; | |
| v = rx1 * q[0] + ry1 * q[1]; | |
| b = linearInterpolation(sx, u, v); | |
| return 1.5f * linearInterpolation(sy, a, b); | |
| } | |
| /** | |
| * Compute 3-dimensional Perlin noise. | |
| * | |
| * @param x | |
| * the x coordinate | |
| * @param y | |
| * the y coordinate | |
| * @param y | |
| * the y coordinate | |
| * @return noise value at (x,y,z) | |
| */ | |
| public float noise(float x, float y, float z) { | |
| int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; | |
| float rx0, rx1, ry0, ry1, rz0, rz1, q[], sy, sz, a, b, c, d, t, u, v; | |
| int i, j; | |
| t = x + N; | |
| bx0 = ((int) t) & BM; | |
| bx1 = (bx0 + 1) & BM; | |
| rx0 = t - (int) t; | |
| rx1 = rx0 - 1.0f; | |
| t = y + N; | |
| by0 = ((int) t) & BM; | |
| by1 = (by0 + 1) & BM; | |
| ry0 = t - (int) t; | |
| ry1 = ry0 - 1.0f; | |
| t = z + N; | |
| bz0 = ((int) t) & BM; | |
| bz1 = (bz0 + 1) & BM; | |
| rz0 = t - (int) t; | |
| rz1 = rz0 - 1.0f; | |
| i = p[bx0]; | |
| j = p[bx1]; | |
| b00 = p[i + by0]; | |
| b10 = p[j + by0]; | |
| b01 = p[i + by1]; | |
| b11 = p[j + by1]; | |
| t = sCurve(rx0); | |
| sy = sCurve(ry0); | |
| sz = sCurve(rz0); | |
| q = g3[b00 + bz0]; | |
| u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2]; | |
| q = g3[b10 + bz0]; | |
| v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2]; | |
| a = linearInterpolation(t, u, v); | |
| q = g3[b01 + bz0]; | |
| u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2]; | |
| q = g3[b11 + bz0]; | |
| v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2]; | |
| b = linearInterpolation(t, u, v); | |
| c = linearInterpolation(sy, a, b); | |
| q = g3[b00 + bz1]; | |
| u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2]; | |
| q = g3[b10 + bz1]; | |
| v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2]; | |
| a = linearInterpolation(t, u, v); | |
| q = g3[b01 + bz1]; | |
| u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2]; | |
| q = g3[b11 + bz1]; | |
| v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2]; | |
| b = linearInterpolation(t, u, v); | |
| d = linearInterpolation(sy, a, b); | |
| return 1.5f * linearInterpolation(sz, c, d); | |
| } | |
| public static float linearInterpolation(float t, float a, float b) { | |
| return a + t * (b - a); | |
| } | |
| private static void normalize2(float v[]) { | |
| float s = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1]); | |
| v[0] = v[0] / s; | |
| v[1] = v[1] / s; | |
| } | |
| static void normalize3(float v[]) { | |
| float s = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); | |
| v[0] = v[0] / s; | |
| v[1] = v[1] / s; | |
| v[2] = v[2] / s; | |
| } | |
| private int random() { | |
| return randomGenerator.nextInt() & 0x7fffffff; | |
| } | |
| private void init() { | |
| int i, j, k; | |
| for (i = 0; i < B; i++) { | |
| p[i] = i; | |
| g1[i] = (float) ((random() % (B + B)) - B) / B; | |
| for (j = 0; j < 2; j++) | |
| g2[i][j] = (float) ((random() % (B + B)) - B) / B; | |
| normalize2(g2[i]); | |
| for (j = 0; j < 3; j++) | |
| g3[i][j] = (float) ((random() % (B + B)) - B) / B; | |
| normalize3(g3[i]); | |
| } | |
| for (i = B - 1; i >= 0; i--) { | |
| k = p[i]; | |
| p[i] = p[j = random() % B]; | |
| p[j] = k; | |
| } | |
| for (i = 0; i < B + 2; i++) { | |
| p[B + i] = p[i]; | |
| g1[B + i] = g1[i]; | |
| for (j = 0; j < 2; j++) | |
| g2[B + i][j] = g2[i][j]; | |
| for (j = 0; j < 3; j++) | |
| g3[B + i][j] = g3[i][j]; | |
| } | |
| } | |
| /** | |
| * Returns the minimum and maximum of a number of random values of the given | |
| * function. This is useful for making some stab at normalising the | |
| * function. | |
| */ | |
| public static float[] findRange(PerlinNoise f, float[] minmax) { | |
| if (minmax == null) | |
| minmax = new float[2]; | |
| float min = 0, max = 0; | |
| // Some random numbers here... | |
| for (float x = -100; x < 100; x += 1.27139) { | |
| float n = f.getf(x); | |
| min = Math.min(min, n); | |
| max = Math.max(max, n); | |
| } | |
| minmax[0] = min; | |
| minmax[1] = max; | |
| return minmax; | |
| } | |
| public float getNumOctaves() { | |
| return numOctaves; | |
| } | |
| public static void main(String[] args) { | |
| System.out.println(Arrays.toString(findRange(new PerlinNoise(), null))); | |
| } | |
| /** | |
| * Returns the minimum and maximum of a number of random values of the given | |
| * function. This is useful for making some stab at normalising the | |
| * function. | |
| */ | |
| public static float[] findRange2D(PerlinNoise f, float[] minmax) { | |
| if (minmax == null) | |
| minmax = new float[2]; | |
| float min = 0, max = 0; | |
| // Some random numbers here... | |
| for (float y = -100; y < 100; y += 10.35173) { | |
| for (float x = -100; x < 100; x += 10.77139) { | |
| float n = f.getf(x, y); | |
| min = Math.min(min, n); | |
| max = Math.max(max, n); | |
| } | |
| } | |
| minmax[0] = min; | |
| minmax[1] = max; | |
| return minmax; | |
| } | |
| public static void setScale(int scale) { | |
| Scale = scale; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment