001package squidpony.squidmath;
002
003import static squidpony.squidmath.Noise.cerp;
004import static squidpony.squidmath.Noise.fastFloor;
005import static squidpony.squidmath.SeededNoise.phiGrad2;
006import static squidpony.squidmath.SeededNoise.gradient6DLUT;
007import static squidpony.squidmath.SeededNoise.grad3d;
008import static squidpony.squidmath.SeededNoise.grad4d;
009
010/**
011 * "Classic Perlin" noise with jitter applied to the grid it operates on. Not to be confused with the Simplex Noise also
012 * created by Ken Perlin (which is in {@link SeededNoise}), or with the non-jittered but similar {@link ClassicNoise}.
013 * This noise can in theory be scaled up to arbitrary dimensions, but in practice uses unreasonably hefty amounts of
014 * memory when dimensionality exceeds 10 or so, since it needs to hash {@code Math.pow(2, dimensionality)} points per
015 * sample of noise, which involves over a thousand points in 10 dimensions and over a million points in 20 dimensions.
016 * For that reason, it's limited to 6D noise here, and also implements 2D, 3D, and 4D. Its performance is similar to
017 * {@link SeededNoise} in 2D, and slows down further on 3D, 4D, and especially 6D. However, due to the grid jitter,
018 * its quality is improved substantially over vanilla Simplex Noise, and it appears more detailed with one octave than
019 * Simplex does. This uses different gradient vectors than what was recommended in the "Improved
020 * Perlin Noise" paper, since the ones this uses avoid 45-degree angular artifacts in all dimensions implemented.
021 * <br>
022 * ClassicNoise is recommended for most usage in {@link squidpony.squidgrid.mapping.WorldMapGenerator} that needs a
023 * Noise3D implementation, and it tends to about as fast as {@link SeededNoise} in 3D with less artifacts. JitterNoise
024 * is a fair amount slower than ClassicNoise, but it has much better quality in 2D and may have somewhat-better quality
025 * in higher dimensions as well. There's probably no reason to prefer JitterNoise over ClassicNoise for 6D output,
026 * because they're practically indistinguishable other than ClassicNoise being much faster.
027 */
028public class JitterNoise implements Noise.Noise2D, Noise.Noise3D, Noise.Noise4D, Noise.Noise6D {
029    public static final JitterNoise instance = new JitterNoise();
030    public long seed;
031    public JitterNoise() {
032        this(0x1337BEEFCAFEL);
033    }
034
035    public JitterNoise(final long seed) {
036        this.seed = seed;
037    }
038    protected static double gradCoord2D(long seed, int x, int y,
039                                              double xd, double yd) {
040        final int hash = ((int)(((seed ^= 0xB4C4D * x ^ 0xEE2C3 * y) ^ seed >>> 13) * (seed))) >>> 24;
041        //final int hash = (int)((((seed = (((seed * (0x632BE59BD9B4E019L + (x << 23))) ^ 0x9E3779B97F4A7C15L) * (0xC6BC279692B5CC83L + (y << 23)))) ^ seed >>> 27 ^ x + y) * 0xAEF17502108EF2D9L) >>> 56);
042        final double[] grad = phiGrad2[hash], jitter = phiGrad2[255 - hash];
043        return (xd + jitter[0] * 0.5) * grad[0] + (yd + jitter[1] * 0.5) * grad[1];
044    }
045    protected static double gradCoord3D(long seed, int x, int y, int z, double xd, double yd, double zd) {
046        final int idx = ((int)(((seed ^= 0xB4C4D * x ^ 0xEE2C1 * y ^ 0xA7E07 * z) ^ seed >>> 13) * (seed)) >>> 27) * 3,
047                jitter = 93 - idx;
048        return ((xd+grad3d[jitter]*0.25) * grad3d[idx]
049                + (yd+grad3d[jitter+1]*0.25) * grad3d[idx + 1]
050                + (zd+grad3d[jitter+2]*0.25) * grad3d[idx + 2]);
051    }
052    protected static double gradCoord4D(long seed, int x, int y, int z, int w,
053                                        double xd, double yd, double zd, double wd) {
054        final int hash =
055                (int)(((seed ^= 0xB4C4D * x ^ 0xEE2C1 * y ^ 0xA7E07 * z ^ 0xCD5E9 * w) ^ seed >>> 13) * (seed)),
056                        idx = (hash >>> 24) & 0xFC, jitter = 0xFC - idx;
057        return ((xd+ grad4d[jitter]*0.25) * grad4d[idx]
058                + (yd+ grad4d[jitter + 1]*0.25) * grad4d[idx + 1]
059                + (zd+ grad4d[jitter + 2]*0.25) * grad4d[idx + 2]
060                + (wd+ grad4d[jitter + 3]*0.25) * grad4d[idx + 3]);
061    }
062    protected static double gradCoord6D(long seed, int x, int y, int z, int w, int u, int v,
063                                        double xd, double yd, double zd, double wd, double ud, double vd) {
064        final int idx = ((int)(((seed ^= 0xB4C4D * x ^ 0xEE2C1 * y ^ 0xA7E07 * z ^ 0xCD5E9 * w ^ 0x94B5B * u ^ 0xD2385 * v)
065                        ^ seed >>> 13) * (seed)) >>> 24) * 6, jitter = 1530 - idx;
066        return (  (xd+gradient6DLUT[jitter]*0.5) * gradient6DLUT[idx]
067                + (yd+gradient6DLUT[jitter+1]*0.5) * gradient6DLUT[idx+1]
068                + (zd+gradient6DLUT[jitter+2]*0.5) * gradient6DLUT[idx+2]
069                + (wd+gradient6DLUT[jitter+3]*0.5) * gradient6DLUT[idx+3]
070                + (ud+gradient6DLUT[jitter+4]*0.5) * gradient6DLUT[idx+4]
071                + (vd+gradient6DLUT[jitter+5]*0.5) * gradient6DLUT[idx+5]);
072    }
073
074    @Override
075    public double getNoise(final double x, final double y) {
076        return getNoiseWithSeed(x, y, seed);
077    }
078
079    @Override
080    public double getNoiseWithSeed(double x, double y, final long seed) {
081        x *= 2.0;
082        y *= 2.0;
083        final int
084                x0 = fastFloor(x),
085                y0 = fastFloor(y);         
086        return Noise.emphasizeSigned(
087                cerp(cerp(gradCoord2D(seed, x0, y0, x - x0, y - y0), gradCoord2D(seed, x0+1, y0, x - x0 - 1, y - y0), x - x0),
088                                cerp(gradCoord2D(seed, x0, y0+1, x - x0, y - y0-1), gradCoord2D(seed, x0+1, y0+1, x - x0 - 1, y - y0 - 1), x - x0),
089                                y - y0) * 0.875);// * 1.4142;
090    }
091
092    @Override
093    public double getNoise(final double x, final double y, final double z) {
094        return getNoiseWithSeed(x, y, z, seed);
095    }
096
097    @Override
098    public double getNoiseWithSeed(double x, double y, double z, final long seed) {
099        x *= 2.0;
100        y *= 2.0;
101        z *= 2.0;
102        final int
103                x0 = fastFloor(x),
104                y0 = fastFloor(y),
105                z0 = fastFloor(z);
106         return Noise.emphasizeSigned(
107                 cerp(cerp(cerp(gradCoord3D(seed, x0, y0, z0, x - x0, y - y0, z - z0), gradCoord3D(seed, x0+1, y0, z0, x - x0 - 1, y - y0, z - z0), x - x0),
108                cerp(gradCoord3D(seed, x0, y0+1, z0, x - x0, y - y0-1, z - z0), gradCoord3D(seed, x0+1, y0+1, z0, x - x0 - 1, y - y0 - 1, z - z0), x - x0),
109                y - y0),
110                cerp(cerp(gradCoord3D(seed, x0, y0, z0+1, x - x0, y - y0, z - z0-1), gradCoord3D(seed, x0+1, y0, z0+1, x - x0 - 1, y - y0, z - z0-1), x - x0),
111                        cerp(gradCoord3D(seed, x0, y0+1, z0+1, x - x0, y - y0-1, z - z0-1), gradCoord3D(seed, x0+1, y0+1, z0+1, x - x0 - 1, y - y0 - 1, z - z0-1), x - x0),
112                        y - y0), z - z0) * 0.666);//1.0625;
113    }
114
115    @Override
116    public double getNoise(final double x, final double y, final double z, final double w) {
117        return getNoiseWithSeed(x, y, z, w, seed);
118    }
119
120    @Override
121    public double getNoiseWithSeed(double x, double y, double z, double w, final long seed) {
122        x *= 2.0;
123        y *= 2.0;
124        z *= 2.0;
125        w *= 2.0;
126        final int
127                x0 = fastFloor(x),
128                y0 = fastFloor(y),
129                z0 = fastFloor(z),
130                w0 = fastFloor(w);
131        return 
132                Noise.emphasizeSigned(cerp(cerp(cerp(cerp(gradCoord4D(seed, x0, y0, z0, w0, x - x0, y - y0, z - z0, w - w0), gradCoord4D(seed, x0+1, y0, z0, w0, x - x0 - 1, y - y0, z - z0, w - w0), x - x0),
133                        cerp(gradCoord4D(seed, x0, y0+1, z0, w0, x - x0, y - y0-1, z - z0, w - w0), gradCoord4D(seed, x0+1, y0+1, z0, w0, x - x0 - 1, y - y0 - 1, z - z0, w - w0), x - x0),
134                        y - y0),
135                        cerp(cerp(gradCoord4D(seed, x0, y0, z0+1, w0, x - x0, y - y0, z - z0-1, w - w0), gradCoord4D(seed, x0+1, y0, z0+1, w0, x - x0 - 1, y - y0, z - z0-1, w - w0), x - x0),
136                                cerp(gradCoord4D(seed, x0, y0+1, z0+1, w0, x - x0, y - y0-1, z - z0-1, w - w0), gradCoord4D(seed, x0+1, y0+1, z0+1, w0, x - x0 - 1, y - y0 - 1, z - z0-1, w - w0), x - x0),
137                                y - y0), 
138                        z - z0),
139                        cerp(cerp(cerp(gradCoord4D(seed, x0, y0, z0, w0+1, x - x0, y - y0, z - z0, w - w0 - 1), gradCoord4D(seed, x0+1, y0, z0, w0+1, x - x0 - 1, y - y0, z - z0, w - w0 - 1), x - x0),
140                                cerp(gradCoord4D(seed, x0, y0+1, z0, w0+1, x - x0, y - y0-1, z - z0, w - w0 - 1), gradCoord4D(seed, x0+1, y0+1, z0, w0+1, x - x0 - 1, y - y0 - 1, z - z0, w - w0 - 1), x - x0),
141                                y - y0),
142                                cerp(cerp(gradCoord4D(seed, x0, y0, z0+1, w0+1, x - x0, y - y0, z - z0-1, w - w0 - 1), gradCoord4D(seed, x0+1, y0, z0+1, w0+1, x - x0 - 1, y - y0, z - z0-1, w - w0 - 1), x - x0),
143                                        cerp(gradCoord4D(seed, x0, y0+1, z0+1, w0+1, x - x0, y - y0-1, z - z0-1, w - w0 - 1), gradCoord4D(seed, x0+1, y0+1, z0+1, w0+1, x - x0 - 1, y - y0 - 1, z - z0-1, w - w0 - 1), x - x0),
144                                        y - y0),
145                                z - z0),
146                        w - w0) * 0.3666);//0.555;
147    }
148
149
150    @Override
151    public double getNoise(final double x, final double y, final double z, final double w, final double u, final double v) {
152        return getNoiseWithSeed(x, y, z, w, u, v, seed);
153    }
154
155    @Override
156    public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
157        x *= 2.0;
158        y *= 2.0;
159        z *= 2.0;
160        w *= 2.0;
161        u *= 2.0;
162        v *= 2.0;
163        final int
164                x0 = fastFloor(x),
165                y0 = fastFloor(y),
166                z0 = fastFloor(z),
167                w0 = fastFloor(w),
168                u0 = fastFloor(u),
169                v0 = fastFloor(v);
170        final double xd = x - x0, yd = y - y0, zd = z - z0, wd = w - w0, ud = u - u0, vd = v - v0; 
171        return Noise.emphasizeSigned(
172                cerp(cerp(cerp(
173                cerp(
174                        cerp(
175                                cerp(gradCoord6D(seed, x0, y0, z0, w0, u0, v0, xd, yd, zd, wd, ud, vd),
176                                        gradCoord6D(seed, x0+1, y0, z0, w0, u0, v0, xd-1, yd, zd, wd, ud, vd), xd),
177                                cerp(gradCoord6D(seed, x0, y0+1, z0, w0, u0, v0, xd, yd-1, zd, wd, ud, vd),
178                                        gradCoord6D(seed, x0+1, y0+1, z0, w0, u0, v0, xd-1, yd-1, zd, wd, ud, vd), xd),
179                                yd),
180                        cerp(
181                                cerp(gradCoord6D(seed, x0, y0, z0+1, w0, u0, v0, xd, yd, zd-1, wd, ud, vd),
182                                        gradCoord6D(seed, x0+1, y0, z0+1, w0, u0, v0, xd-1, yd, zd-1, wd, ud, vd), xd),
183                                cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0, u0, v0, xd, yd-1, zd-1, wd, ud, vd),
184                                        gradCoord6D(seed, x0+1, y0+1, z0+1, w0, u0, v0, xd-1, yd-1, zd-1, wd, ud, vd), xd),
185                                yd),
186                        zd),
187                cerp(
188                        cerp(
189                                cerp(gradCoord6D(seed, x0, y0, z0, w0+1, u0, v0, xd, yd, zd, wd-1, ud, vd),
190                                        gradCoord6D(seed, x0+1, y0, z0, w0+1, u0, v0, xd-1, yd, zd, wd-1, ud, vd), xd),
191                                cerp(gradCoord6D(seed, x0, y0+1, z0, w0+1, u0, v0, xd, yd-1, zd, wd-1, ud, vd),
192                                        gradCoord6D(seed, x0+1, y0+1, z0, w0+1, u0, v0, xd-1, yd-1, zd, wd-1, ud, vd), xd),
193                                yd),
194                        cerp(
195                                cerp(gradCoord6D(seed, x0, y0, z0+1, w0+1, u0, v0, xd, yd, zd-1, wd-1, ud, vd),
196                                        gradCoord6D(seed, x0+1, y0, z0+1, w0+1, u0, v0, xd-1, yd, zd-1, wd-1, ud, vd), xd),
197                                cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0+1, u0, v0, xd, yd-1, zd-1, wd-1, ud, vd),
198                                        gradCoord6D(seed, x0+1, y0+1, z0+1, w0+1, u0, v0, xd-1, yd-1, zd-1, wd-1, ud, vd), xd),
199                                yd),
200                        zd),
201                wd),
202                cerp(
203                        cerp(
204                                cerp(
205                                        cerp(gradCoord6D(seed, x0, y0, z0, w0, u0+1, v0, xd, yd, zd, wd, ud-1, vd),
206                                                gradCoord6D(seed, x0+1, y0, z0, w0, u0+1, v0, xd-1, yd, zd, wd, ud-1, vd), xd),
207                                        cerp(gradCoord6D(seed, x0, y0+1, z0, w0, u0+1, v0, xd, yd-1, zd, wd, ud-1, vd),
208                                                gradCoord6D(seed, x0+1, y0+1, z0, w0, u0+1, v0, xd-1, yd-1, zd, wd, ud-1, vd), xd),
209                                        yd),
210                                cerp(
211                                        cerp(gradCoord6D(seed, x0, y0, z0+1, w0, u0+1, v0, xd, yd, zd-1, wd, ud-1, vd),
212                                                gradCoord6D(seed, x0+1, y0, z0+1, w0, u0+1, v0, xd-1, yd, zd-1, wd, ud-1, vd), xd),
213                                        cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0, u0+1, v0, xd, yd-1, zd-1, wd, ud-1, vd),
214                                                gradCoord6D(seed, x0+1, y0+1, z0+1, w0, u0+1, v0, xd-1, yd-1, zd-1, wd, ud-1, vd), xd),
215                                        yd),
216                                zd),
217                        cerp(
218                                cerp(
219                                        cerp(gradCoord6D(seed, x0, y0, z0, w0+1, u0+1, v0, xd, yd, zd, wd-1, ud-1, vd),
220                                                gradCoord6D(seed, x0+1, y0, z0, w0+1, u0+1, v0, xd-1, yd, zd, wd-1, ud-1, vd), xd),
221                                        cerp(gradCoord6D(seed, x0, y0+1, z0, w0+1, u0+1, v0, xd, yd-1, zd, wd-1, ud-1, vd),
222                                                gradCoord6D(seed, x0+1, y0+1, z0, w0+1, u0+1, v0, xd-1, yd-1, zd, wd-1, ud-1, vd), xd),
223                                        yd),
224                                cerp(
225                                        cerp(gradCoord6D(seed, x0, y0, z0+1, w0+1, u0+1, v0, xd, yd, zd-1, wd-1, ud-1, vd),
226                                                gradCoord6D(seed, x0+1, y0, z0+1, w0+1, u0+1, v0, xd-1, yd, zd-1, wd-1, ud-1, vd), xd),
227                                        cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0+1, u0+1, v0, xd, yd-1, zd-1, wd-1, ud-1, vd),
228                                                gradCoord6D(seed, x0+1, y0+1, z0+1, w0+1, u0+1, v0, xd-1, yd-1, zd-1, wd-1, ud-1, vd), xd),
229                                        yd),
230                                zd),
231                        wd),
232                ud),
233                cerp(
234                        cerp(
235                        cerp(
236                                cerp(
237                                        cerp(gradCoord6D(seed, x0, y0, z0, w0, u0, v0+1, xd, yd, zd, wd, ud, vd-1),
238                                                gradCoord6D(seed, x0+1, y0, z0, w0, u0, v0+1, xd-1, yd, zd, wd, ud, vd-1), xd),
239                                        cerp(gradCoord6D(seed, x0, y0+1, z0, w0, u0, v0+1, xd, yd-1, zd, wd, ud, vd-1),
240                                                gradCoord6D(seed, x0+1, y0+1, z0, w0, u0, v0+1, xd-1, yd-1, zd, wd, ud, vd-1), xd),
241                                        yd),
242                                cerp(
243                                        cerp(gradCoord6D(seed, x0, y0, z0+1, w0, u0, v0+1, xd, yd, zd-1, wd, ud, vd-1),
244                                                gradCoord6D(seed, x0+1, y0, z0+1, w0, u0, v0+1, xd-1, yd, zd-1, wd, ud, vd-1), xd),
245                                        cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0, u0, v0+1, xd, yd-1, zd-1, wd, ud, vd-1),
246                                                gradCoord6D(seed, x0+1, y0+1, z0+1, w0, u0, v0+1, xd-1, yd-1, zd-1, wd, ud, vd-1), xd),
247                                        yd),
248                                zd),
249                        cerp(
250                                cerp(
251                                        cerp(gradCoord6D(seed, x0, y0, z0, w0+1, u0, v0+1, xd, yd, zd, wd-1, ud, vd-1),
252                                                gradCoord6D(seed, x0+1, y0, z0, w0+1, u0, v0+1, xd-1, yd, zd, wd-1, ud, vd-1), xd),
253                                        cerp(gradCoord6D(seed, x0, y0+1, z0, w0+1, u0, v0+1, xd, yd-1, zd, wd-1, ud, vd-1),
254                                                gradCoord6D(seed, x0+1, y0+1, z0, w0+1, u0, v0+1, xd-1, yd-1, zd, wd-1, ud, vd-1), xd),
255                                        yd),
256                                cerp(
257                                        cerp(gradCoord6D(seed, x0, y0, z0+1, w0+1, u0, v0+1, xd, yd, zd-1, wd-1, ud, vd-1),
258                                                gradCoord6D(seed, x0+1, y0, z0+1, w0+1, u0, v0+1, xd-1, yd, zd-1, wd-1, ud, vd-1), xd),
259                                        cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0+1, u0, v0+1, xd, yd-1, zd-1, wd-1, ud, vd-1),
260                                                gradCoord6D(seed, x0+1, y0+1, z0+1, w0+1, u0, v0+1, xd-1, yd-1, zd-1, wd-1, ud, vd-1), xd),
261                                        yd),
262                                zd),
263                        wd),
264                        cerp(
265                                cerp(
266                                        cerp(
267                                                cerp(gradCoord6D(seed, x0, y0, z0, w0, u0+1, v0+1, xd, yd, zd, wd, ud-1, vd-1),
268                                                        gradCoord6D(seed, x0+1, y0, z0, w0, u0+1, v0+1, xd-1, yd, zd, wd, ud-1, vd-1), xd),
269                                                cerp(gradCoord6D(seed, x0, y0+1, z0, w0, u0+1, v0+1, xd, yd-1, zd, wd, ud-1, vd-1),
270                                                        gradCoord6D(seed, x0+1, y0+1, z0, w0, u0+1, v0+1, xd-1, yd-1, zd, wd, ud-1, vd-1), xd),
271                                                yd),
272                                        cerp(
273                                                cerp(gradCoord6D(seed, x0, y0, z0+1, w0, u0+1, v0+1, xd, yd, zd-1, wd, ud-1, vd-1),
274                                                        gradCoord6D(seed, x0+1, y0, z0+1, w0, u0+1, v0+1, xd-1, yd, zd-1, wd, ud-1, vd-1), xd),
275                                                cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0, u0+1, v0+1, xd, yd-1, zd-1, wd, ud-1, vd-1),
276                                                        gradCoord6D(seed, x0+1, y0+1, z0+1, w0, u0+1, v0+1, xd-1, yd-1, zd-1, wd, ud-1, vd-1), xd),
277                                                yd),
278                                        zd),
279                                cerp(
280                                        cerp(
281                                                cerp(gradCoord6D(seed, x0, y0, z0, w0+1, u0+1, v0+1, xd, yd, zd, wd-1, ud-1, vd-1),
282                                                        gradCoord6D(seed, x0+1, y0, z0, w0+1, u0+1, v0+1, xd-1, yd, zd, wd-1, ud-1, vd-1), xd),
283                                                cerp(gradCoord6D(seed, x0, y0+1, z0, w0+1, u0+1, v0+1, xd, yd-1, zd, wd-1, ud-1, vd-1),
284                                                        gradCoord6D(seed, x0+1, y0+1, z0, w0+1, u0+1, v0+1, xd-1, yd-1, zd, wd-1, ud-1, vd-1), xd),
285                                                yd),
286                                        cerp(
287                                                cerp(gradCoord6D(seed, x0, y0, z0+1, w0+1, u0+1, v0+1, xd, yd, zd-1, wd-1, ud-1, vd-1),
288                                                        gradCoord6D(seed, x0+1, y0, z0+1, w0+1, u0+1, v0+1, xd-1, yd, zd-1, wd-1, ud-1, vd-1), xd),
289                                                cerp(gradCoord6D(seed, x0, y0+1, z0+1, w0+1, u0+1, v0+1, xd, yd-1, zd-1, wd-1, ud-1, vd-1),
290                                                        gradCoord6D(seed, x0+1, y0+1, z0+1, w0+1, u0+1, v0+1, xd-1, yd-1, zd-1, wd-1, ud-1, vd-1), xd),
291                                                yd),
292                                        zd),
293                                wd),
294                        ud),
295                vd) * 1.5);//1.875;
296    }
297}