Last active
November 11, 2024 13:50
-
-
Save alksily/7a85a1898e65c936f861ee93516e397d to your computer and use it in GitHub Desktop.
Perlin Noise (1D, 2D, 3D noise generator)
This file contains 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
package main.ru.aengine.noise; | |
import java.util.Random; | |
public class NoiseGenerator { | |
private double seed; | |
private long default_size; | |
private int[] p; | |
private int[] permutation; | |
public NoiseGenerator(double seed) { | |
this.seed = seed; | |
init(); | |
} | |
public NoiseGenerator() { | |
this.seed = new Random().nextGaussian() * 255; | |
init(); | |
} | |
private void init() { | |
// Initialize the permutation array. | |
this.p = new int[512]; | |
this.permutation = new int[] { 151, 160, 137, 91, 90, 15, 131, 13, 201, | |
95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, | |
37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, | |
197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, | |
237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, | |
165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, | |
229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, | |
244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, | |
132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, | |
86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, | |
124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, | |
206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, | |
213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, | |
167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, | |
224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, | |
193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, | |
249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, | |
84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, | |
205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, | |
215, 61, 156, 180 }; | |
this.default_size = 35; | |
// Populate it | |
for (int i = 0; i < 256; i++) { | |
p[256 + i] = p[i] = permutation[i]; | |
} | |
} | |
public void setSeed(double seed) { | |
this.seed = seed; | |
} | |
public double getSeed() { | |
return this.seed; | |
} | |
public double noise(double x, double y, double z, int size) { | |
double value = 0.0; | |
double initialSize = size; | |
while (size >= 1) { | |
value += smoothNoise((x / size), (y / size), (z / size)) * size; | |
size /= 2.0; | |
} | |
return value / initialSize; | |
} | |
public double noise(double x, double y, double z) { | |
double value = 0.0; | |
double size = default_size; | |
double initialSize = size; | |
while (size >= 1) { | |
value += smoothNoise((x / size), (y / size), (z / size)) * size; | |
size /= 2.0; | |
} | |
return value / initialSize; | |
} | |
public double noise(double x, double y) { | |
double value = 0.0; | |
double size = default_size; | |
double initialSize = size; | |
while (size >= 1) { | |
value += smoothNoise((x / size), (y / size), (0f / size)) * size; | |
size /= 2.0; | |
} | |
return value / initialSize; | |
} | |
public double noise(double x) { | |
double value = 0.0; | |
double size = default_size; | |
double initialSize = size; | |
while (size >= 1) { | |
value += smoothNoise((x / size), (0f / size), (0f / size)) * size; | |
size /= 2.0; | |
} | |
return value / initialSize; | |
} | |
public double smoothNoise(double x, double y, double z) { | |
// Offset each coordinate by the seed value | |
x += this.seed; | |
y += this.seed; | |
x += this.seed; | |
int X = (int) Math.floor(x) & 255; // FIND UNIT CUBE THAT | |
int Y = (int) Math.floor(y) & 255; // CONTAINS POINT. | |
int Z = (int) Math.floor(z) & 255; | |
x -= Math.floor(x); // FIND RELATIVE X,Y,Z | |
y -= Math.floor(y); // OF POINT IN CUBE. | |
z -= Math.floor(z); | |
double u = fade(x); // COMPUTE FADE CURVES | |
double v = fade(y); // FOR EACH OF X,Y,Z. | |
double w = fade(z); | |
int A = p[X] + Y; | |
int AA = p[A] + Z; | |
int AB = p[A + 1] + Z; // HASH COORDINATES OF | |
int B = p[X + 1] + Y; | |
int BA = p[B] + Z; | |
int BB = p[B + 1] + Z; // THE 8 CUBE CORNERS, | |
return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z ), // AND ADD | |
grad(p[BA], x - 1, y, z )), // BLENDED | |
lerp(u, grad(p[AB], x, y - 1, z ), // RESULTS | |
grad(p[BB], x - 1, y - 1, z ))),// FROM 8 | |
lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1 ), // CORNERS | |
grad(p[BA + 1], x - 1, y, z - 1 )), // OF CUBE | |
lerp(u, grad(p[AB + 1], x, y - 1, z - 1 ), | |
grad(p[BB + 1], x - 1, y - 1, z - 1 )))); | |
} | |
private double fade(double t) { | |
return t * t * t * (t * (t * 6 - 15) + 10); | |
} | |
private double lerp(double t, double a, double b) { | |
return a + t * (b - a); | |
} | |
private double grad(int hash, double x, double y, double z) { | |
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE | |
double u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. | |
v = h < 4 ? y : h == 12 || h == 14 ? x : z; | |
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); | |
} | |
} |
Very nice implementation!
I second @GregMarshall999 's recommendation. After running the 2d noise function a few thousand times I get -1.0242812726442605
and 1.1233964215787382
as the minimum and maximum values respectively, so it isn't clear what the bounds on the function are.
Also, what is the license for this code?
@alksily Can I use this noise generator in my code?
@srideep-banerjee Yes, sure
@alksily On line number 116 did you intend to write 'z+=' ?
@srideep-banerjee most likely there is a typo .. rather old code.
Great noise! I've used it for my 2D voxel game.
Can I use this for my game?
@bmo316 yes, you can
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks man, very helpful