001 package org.bukkit.util.noise; 002 003 import java.util.Random; 004 import org.bukkit.World; 005 006 /** 007 * Generates noise using the "classic" perlin generator 008 * 009 * @see SimplexNoiseGenerator "Improved" and faster version with slighly 010 * different results 011 */ 012 public class PerlinNoiseGenerator extends NoiseGenerator { 013 protected static final int grad3[][] = {{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, 014 {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, 015 {0, 1, 1}, {0, -1, 1}, {0, 1, -1}, {0, -1, -1}}; 016 private static final PerlinNoiseGenerator instance = new PerlinNoiseGenerator(); 017 018 protected PerlinNoiseGenerator() { 019 int p[] = {151, 160, 137, 91, 90, 15, 131, 13, 201, 020 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 021 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 022 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 023 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 024 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 025 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 026 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 027 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 028 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 029 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 030 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 031 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 032 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 033 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 034 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 035 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 036 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180}; 037 038 for (int i = 0; i < 512; i++) { 039 perm[i] = p[i & 255]; 040 } 041 } 042 043 /** 044 * Creates a seeded perlin noise generator for the given world 045 * 046 * @param world World to construct this generator for 047 */ 048 public PerlinNoiseGenerator(World world) { 049 this(new Random(world.getSeed())); 050 } 051 052 /** 053 * Creates a seeded perlin noise generator for the given seed 054 * 055 * @param seed Seed to construct this generator for 056 */ 057 public PerlinNoiseGenerator(long seed) { 058 this(new Random(seed)); 059 } 060 061 /** 062 * Creates a seeded perlin noise generator with the given Random 063 * 064 * @param rand Random to construct with 065 */ 066 public PerlinNoiseGenerator(Random rand) { 067 offsetX = rand.nextDouble() * 256; 068 offsetY = rand.nextDouble() * 256; 069 offsetZ = rand.nextDouble() * 256; 070 071 for (int i = 0; i < 256; i++) { 072 perm[i] = rand.nextInt(256); 073 } 074 075 for (int i = 0; i < 256; i++) { 076 int pos = rand.nextInt(256 - i) + i; 077 int old = perm[i]; 078 079 perm[i] = perm[pos]; 080 perm[pos] = old; 081 perm[i + 256] = perm[i]; 082 } 083 } 084 085 /** 086 * Computes and returns the 1D unseeded perlin noise for the given 087 * coordinates in 1D space 088 * 089 * @param x X coordinate 090 * @return Noise at given location, from range -1 to 1 091 */ 092 public static double getNoise(double x) { 093 return instance.noise(x); 094 } 095 096 /** 097 * Computes and returns the 2D unseeded perlin noise for the given 098 * coordinates in 2D space 099 * 100 * @param x X coordinate 101 * @param y Y coordinate 102 * @return Noise at given location, from range -1 to 1 103 */ 104 public static double getNoise(double x, double y) { 105 return instance.noise(x, y); 106 } 107 108 /** 109 * Computes and returns the 3D unseeded perlin noise for the given 110 * coordinates in 3D space 111 * 112 * @param x X coordinate 113 * @param y Y coordinate 114 * @param z Z coordinate 115 * @return Noise at given location, from range -1 to 1 116 */ 117 public static double getNoise(double x, double y, double z) { 118 return instance.noise(x, y, z); 119 } 120 121 /** 122 * Gets the singleton unseeded instance of this generator 123 * 124 * @return Singleton 125 */ 126 public static PerlinNoiseGenerator getInstance() { 127 return instance; 128 } 129 130 @Override 131 public double noise(double x, double y, double z) { 132 x += offsetX; 133 y += offsetY; 134 z += offsetZ; 135 136 int floorX = floor(x); 137 int floorY = floor(y); 138 int floorZ = floor(z); 139 140 // Find unit cube containing the point 141 int X = floorX & 255; 142 int Y = floorY & 255; 143 int Z = floorZ & 255; 144 145 // Get relative xyz coordinates of the point within the cube 146 x -= floorX; 147 y -= floorY; 148 z -= floorZ; 149 150 // Compute fade curves for xyz 151 double fX = fade(x); 152 double fY = fade(y); 153 double fZ = fade(z); 154 155 // Hash coordinates of the cube corners 156 int A = perm[X] + Y; 157 int AA = perm[A] + Z; 158 int AB = perm[A + 1] + Z; 159 int B = perm[X + 1] + Y; 160 int BA = perm[B] + Z; 161 int BB = perm[B + 1] + Z; 162 163 return lerp(fZ, lerp(fY, lerp(fX, grad(perm[AA], x, y, z), 164 grad(perm[BA], x - 1, y, z)), 165 lerp(fX, grad(perm[AB], x, y - 1, z), 166 grad(perm[BB], x - 1, y - 1, z))), 167 lerp(fY, lerp(fX, grad(perm[AA + 1], x, y, z - 1), 168 grad(perm[BA + 1], x - 1, y, z - 1)), 169 lerp(fX, grad(perm[AB + 1], x, y - 1, z - 1), 170 grad(perm[BB + 1], x - 1, y - 1, z - 1)))); 171 } 172 173 /** 174 * Generates noise for the 1D coordinates using the specified number of 175 * octaves and parameters 176 * 177 * @param x X-coordinate 178 * @param octaves Number of octaves to use 179 * @param frequency How much to alter the frequency by each octave 180 * @param amplitude How much to alter the amplitude by each octave 181 * @return Resulting noise 182 */ 183 public static double getNoise(double x, int octaves, double frequency, double amplitude) { 184 return instance.noise(x, octaves, frequency, amplitude); 185 } 186 187 /** 188 * Generates noise for the 2D coordinates using the specified number of 189 * octaves and parameters 190 * 191 * @param x X-coordinate 192 * @param y Y-coordinate 193 * @param octaves Number of octaves to use 194 * @param frequency How much to alter the frequency by each octave 195 * @param amplitude How much to alter the amplitude by each octave 196 * @return Resulting noise 197 */ 198 public static double getNoise(double x, double y, int octaves, double frequency, double amplitude) { 199 return instance.noise(x, y, octaves, frequency, amplitude); 200 } 201 202 /** 203 * Generates noise for the 3D coordinates using the specified number of 204 * octaves and parameters 205 * 206 * @param x X-coordinate 207 * @param y Y-coordinate 208 * @param z Z-coordinate 209 * @param octaves Number of octaves to use 210 * @param frequency How much to alter the frequency by each octave 211 * @param amplitude How much to alter the amplitude by each octave 212 * @return Resulting noise 213 */ 214 public static double getNoise(double x, double y, double z, int octaves, double frequency, double amplitude) { 215 return instance.noise(x, y, z, octaves, frequency, amplitude); 216 } 217 }