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 }