00001
00002
00003
00004
00005 from __future__ import division
00006 from __future__ import with_statement
00007
00008 from random import random
00009 from random import shuffle
00010 from random import randint
00011 from math import floor
00012 from math import cos
00013 from math import pi
00014 from math import sqrt
00015
00016 from enhanced_grid import Grid1D
00017 from enhanced_grid import Grid2D
00018 from enhanced_grid import Grid3D
00019
00020
00021
00022
00023
00024
00025
00026
00027 def make_uniform_noise(width, height):
00028 noise = Grid2D((width, height), 0)
00029
00030 for p in noise.index_iter():
00031 noise[p] = random()
00032
00033 return noise
00034
00035 def make_checker_board_noise(width, height, period=1):
00036 noise = Grid2D((width, height), 0)
00037
00038 for p in noise.index_iter():
00039 i, j = p
00040 noise[p] = (i // period % 2 + j // period % 2) % 2
00041
00042 return noise
00043
00044
00045
00046
00047
00048 class SmoothNoise:
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 def __init__(self, width, height, noise_fn = make_uniform_noise, interpolation='linear'):
00060 self.nois_fn = noise_fn
00061 self.uniform_noise = noise_fn(width, height)
00062
00063 self.width = width
00064 self.height = height
00065
00066 if interpolation == 'linear':
00067 self.interpolation = self.linear_interpolation
00068 elif interpolation == 'cosine':
00069 self.interpolation = self.cosine_interpolation
00070 elif interpolation == 'cubic':
00071 self.interpolation == self.cubic_interpolation
00072 else:
00073 self.interpolation = self.linear_interpolation
00074
00075
00076
00077
00078
00079
00080
00081
00082 def generate(self, k):
00083 return self.linear_interpolation(k)
00084
00085 def linear_interpolation(self, k):
00086 t = 2**k
00087 noise = self.uniform_noise
00088 smooth_noise = Grid2D((self.width, self.height), 0)
00089
00090 for i in range(self.width):
00091 x0, x1, x_alpha = sample_points(i, t, self.width)
00092
00093 for j in range(self.height):
00094 y0, y1, y_alpha = sample_points(j, t, self.height)
00095
00096 a0 = (1 - x_alpha)*noise[x0, y0] +(x_alpha)*noise[x1, y0]
00097 a1 = (1 - x_alpha)*noise[x0, y1] + (x_alpha)*noise[x1, y1]
00098
00099 smooth_noise[i, j] = (1 - y_alpha)*a0 + (y_alpha)*a1
00100 return smooth_noise
00101
00102 def cosine_interpolation(self, k):
00103 t = 2**k
00104 noise = self.uniform_noise
00105 smooth_noise = Grid2D((self.width, self.height), 0)
00106
00107 for i in range(self.width):
00108 x0, x1, x_alpha = sample_points(i, t, self.width)
00109 x_alpha = (1-cos(x_alpha*pi))/2
00110 for j in range(self.height):
00111 y0, y1, y_alpha = sample_points(j, t, self.height)
00112 y_alpha = (1-cos(y_alpha*pi))/2
00113
00114 a0 = (1 - x_alpha)*noise[x0, y0] +(x_alpha)*noise[x1, y0]
00115 a1 = (1 - x_alpha)*noise[x0, y1] + (x_alpha)*noise[x1, y1]
00116
00117 smooth_noise[i, j] = (1 - y_alpha)*a0 + (y_alpha)*a1
00118 return smooth_noise
00119
00120 def cubic_interpolation(self, k):
00121 t = 2**k
00122 noise = self.uniform_noise
00123 smooth_noise = Grid2D((self.width, self.height), 0)
00124
00125 for i in range(self.width):
00126 x0, x1, x2, x3, x_alpha, x_alpha_2, x_alpha_3, x_alpha_i, x_alpha_i2, x_alpha_i3 = sample_points_cubic(i, t, self.width)
00127
00128 for j in range(self.height):
00129 y0, y1, y2, y3, y_alpha, y_alpha_2, y_alpha_3, y_alpha_i, y_alpha_i2, y_alpha_i3 = sample_points_cubic(j, t, self.height)
00130
00131 a0 = x_alpha_i3*noise[x0, y0] + x_alpha_i2*x_alpha*noise[x1, y0] + \
00132 x_alpha_i*x_alpha_2*noise[x2, y0] + x_alpha_3*noise[x3, y0]
00133 a1 = x_alpha_i3*noise[x0, y1] + x_alpha_i2*x_alpha*noise[x1, y1] + \
00134 x_alpha_i*x_alpha_2*noise[x2, y1] + x_alpha_3*noise[x3, y1]
00135 a2 = x_alpha_i3*noise[x0, y2] + x_alpha_i2*x_alpha*noise[x1, y2] + \
00136 x_alpha_i*x_alpha_2*noise[x2, y2] + x_alpha_3*noise[x3, y2]
00137 a3 = x_alpha_i3*noise[x0, y3] + x_alpha_i2*x_alpha*noise[x1, y3] + \
00138 x_alpha_i*x_alpha_2*noise[x2, y3] + x_alpha_3*noise[x3, y3]
00139
00140 smooth_noise[i, j] = y_alpha_i3*a0 + y_alpha_i2*y_alpha*a1 + \
00141 y_alpha_i*y_alpha_2*a2 + y_alpha_3*a3
00142 return smooth_noise
00143
00144
00145
00146
00147
00148 def perlin_noise_from_smoothnoise(width, height, layers, falloff, noise, normalize=True):
00149 perlin_noise = Grid2D((width, height), 0)
00150 r = 1
00151
00152 for k in range(layers):
00153 r *= falloff
00154 s_noise = noise.generate(layers - k - 1)
00155
00156 for p in perlin_noise.index_iter():
00157 perlin_noise[p] += s_noise[p]*r
00158
00159
00160 if normalize:
00161 r = 1
00162 w = 0
00163
00164 for k in range(layers):
00165 r *= falloff
00166 w += r
00167
00168 for p in perlin_noise.index_iter():
00169 perlin_noise[p] /= w
00170
00171 return perlin_noise
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 def perlin_noise(width, height, layers, falloff = 0.5, tiles=1):
00185 noise = SmoothNoise(width, height)
00186 p = [perlin_noise_from_smoothnoise(width, height, layers, falloff, noise)]
00187
00188 for k in xrange(tiles - 1):
00189 noise = SmoothNoise(width, height)
00190 p.append(perlin_noise_from_smoothnoise(width, height, layers, falloff, noise))
00191
00192 return p
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 def perlin_noise_tileable(width, height, layers, falloff = 0.5, tiles=1):
00206 noise = SmoothNoise(width, height)
00207 p = [perlin_noise_from_smoothnoise(width, height, layers, falloff, noise)]
00208
00209 for k in xrange(tiles - 1):
00210 new_noise = SmoothNoise(width, height)
00211 new_noise.uniform_noise[:,0] = noise.uniform_noise[:,0]
00212 new_noise.uniform_noise[0,:] = noise.uniform_noise[0, :]
00213
00214 p.append(perlin_noise_from_smoothnoise(width, height, layers, falloff, new_noise))
00215
00216 return p
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 def int_perlin_noise(width, height, layers, n, tiles=1):
00233 noise_list = perlin_noise(width, height, layers)
00234 int_noise_list = []
00235
00236 for noise in noise_list:
00237 int_noise = Grid2D((width, height))
00238
00239 for p in noise.index_iter():
00240 int_noise[p] = int(floor(noise[p]/(1 / n)))
00241
00242 int_noise_list.append(int_noise)
00243
00244 return int_noise_list
00245
00246
00247 def random_permutation(n):
00248 return shuffle(range(n))
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 def sample_points(x, t, max_x):
00262 x0 = x // t * t
00263 return x0, (x0 + t) % max_x, (x - x0) / t
00264
00265 def sample_points_cubic(x, t, max_x):
00266 x1 = x // t * t
00267 x0 = (x1 - t) % max_x
00268 x2 = (x1 + t) % max_x
00269 x3 = (x1 + 2*t) % max_x
00270 x_alpha = 1 - (x - x1) / t
00271
00272 x_alpha_2 = x_alpha * x_alpha
00273 x_alpha_3 = x_alpha * x_alpha_2
00274
00275 x_alpha_i = 1 - x_alpha
00276 x_alpha_i2 = x_alpha_i*x_alpha_i
00277 x_alpha_i3 = x_alpha_i2 * x_alpha_i
00278
00279 return x0, x1, x2, x3, x_alpha, x_alpha_2, x_alpha_3, x_alpha_i, x_alpha_i2, x_alpha_i3
00280
00281
00282 def uniform_noise_3d(width, height, depth):
00283 noise = Grid3D((width, height, depth), 0)
00284
00285 for p in noise.index_iter():
00286 noise[p] = random()
00287
00288 return noise
00289
00290 def make_uniform_noise_1d(length):
00291 noise = Grid1D((length, ), 0)
00292
00293 for p in noise.index_iter():
00294 noise[p] = random()
00295
00296 return noise
00297
00298
00299
00300
00301
00302 class SmoothNoise1D:
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 def __init__(self, length, noise_fn = make_uniform_noise_1d, interpolation='linear'):
00314 self.nois_fn = noise_fn
00315 self.uniform_noise = noise_fn(length)
00316
00317 self.length = length
00318
00319 if interpolation == 'linear':
00320 self.interpolation = self.linear_interpolation
00321 elif interpolation == 'cosine':
00322 self.interpolation = self.cosine_interpolation
00323 elif interpolation == 'cubic':
00324 self.interpolation == self.cubic_interpolation
00325 else:
00326 self.interpolation = self.linear_interpolation
00327
00328
00329
00330
00331
00332
00333
00334
00335 def generate(self, k):
00336 return self.linear_interpolation(k)
00337
00338 def linear_interpolation(self, k):
00339 t = 2**k
00340 noise = self.uniform_noise
00341 smooth_noise = Grid1D((self.length, ), 0)
00342
00343 for i in range(self.length):
00344 x0, x1, x_alpha = sample_points(i, t, self.length)
00345 smooth_noise[i] = (1 - x_alpha)*noise[x0] +(x_alpha)*noise[x1]
00346 return smooth_noise
00347
00348
00349
00350
00351
00352
00353 def perlin_noise_from_smoothnoise_1d(length, layers, falloff, noise, normalize=True):
00354 perlin_noise = Grid1D((length, ), 0)
00355 r = 1
00356
00357 for k in range(layers):
00358 r *= falloff
00359 s_noise = noise.generate(layers - k - 1)
00360
00361 for p in perlin_noise.index_iter():
00362 perlin_noise[p] += s_noise[p]*r
00363
00364
00365 if normalize:
00366 r = 1
00367 w = 0
00368
00369 for k in range(layers):
00370 r *= falloff
00371 w += r
00372
00373 for p in perlin_noise.index_iter():
00374 perlin_noise[p] /= w
00375
00376 return perlin_noise
00377
00378
00379
00380
00381
00382 class SmoothNoise3D:
00383
00384
00385
00386
00387
00388
00389
00390 def __init__(self, width, height, depth):
00391 self.uniform_noise = uniform_noise_3d(width, height, depth)
00392
00393 self.width = width
00394 self.height = height
00395 self.depth = depth
00396
00397
00398
00399
00400
00401
00402
00403
00404 def generate(self, k):
00405 t = 2**k
00406 noise = self.uniform_noise
00407 smooth_noise = Grid3D((self.width, self.height, self.depth), 0)
00408
00409 for i in range(self.width):
00410 x0, x1, x_alpha = sample_points(i, t, self.width)
00411
00412 for j in range(self.height):
00413 y0, y1, y_alpha = sample_points(j, t, self.height)
00414
00415 for k in range(self.depth):
00416 z0, z1, z_alpha = sample_points(k, t, self.depth)
00417
00418 a0 = (1 - x_alpha)*noise[x0, y0, z0] + x_alpha*noise[x1, y0, z0]
00419 a1 = (1 - x_alpha)*noise[x0, y1, z0] + x_alpha*noise[x1, y1, z0]
00420 c0 = (1 - y_alpha)*a0 + y_alpha*a1
00421
00422 b0 = (1 - x_alpha)*noise[x0, y0, z1] + x_alpha*noise[x1, y0, z1]
00423 b1 = (1 - x_alpha)*noise[x0, y1, z1] + x_alpha*noise[x1, y1, z1]
00424 c1 = (1 - y_alpha)*b0 + y_alpha*b1
00425
00426 smooth_noise[i, j, k] = (1 - z_alpha)*c0 + z_alpha*c1
00427
00428 return smooth_noise
00429
00430
00431
00432 def perlin_noise_from_smoothnoise_3d(width, height, depth, layers, falloff):
00433 perlin_noise = Grid3D((width, height, depth), 0)
00434 noise = SmoothNoise3D(width, height, depth)
00435 r = 1
00436
00437 for kk in range(layers):
00438 r *= falloff
00439 s_noise = noise.generate(layers - kk - 1)
00440
00441 for p in perlin_noise.index_iter():
00442 perlin_noise[p] += s_noise[p]*r
00443
00444 r = 1
00445 w = 0
00446
00447 for kk in xrange(layers):
00448 r *= falloff
00449 w += r
00450
00451 for p in perlin_noise.index_iter():
00452 perlin_noise[p] /= w
00453
00454 return perlin_noise
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 def perlin_noise_3d(width, height, depth, layers, falloff = 0.5, tiles=1):
00473 p = [perlin_noise_from_smoothnoise_3d(width, height, depth, layers, falloff)]
00474
00475 return p
00476