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}