123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- # Copyright (c) 2008, Casey Duncan (casey dot duncan at gmail dot com)
- # see LICENSE.txt for details
- """Noise functions for procedural generation of content
- Contains native code implementations of Perlin improved noise (with
- fBm capabilities) and Perlin simplex noise. Also contains a fast
- "fake noise" implementation in GLSL for execution in shaders.
- Copyright (c) 2008, Casey Duncan (casey dot duncan at gmail dot com)
- """
- __version__ = "1.2.1"
- from math import floor, fmod, sqrt
- from random import randint
- # 3D Gradient vectors
- _GRAD3 = ((1, 1, 0), (-1, 1, 0), (1, -1, 0), (-1, -1, 0),
- (1, 0, 1), (-1, 0, 1), (1, 0, -1), (-1, 0, -1),
- (0, 1, 1), (0, -1, 1), (0, 1, -1), (0, -1, -1),
- (1, 1, 0), (0, -1, 1), (-1, 1, 0), (0, -1, -1),
- )
- # 4D Gradient vectors
- _GRAD4 = ((0, 1, 1, 1), (0, 1, 1, -1), (0, 1, -1, 1), (0, 1, -1, -1),
- (0, -1, 1, 1), (0, -1, 1, -1), (0, -1, -1, 1), (0, -1, -1, -1),
- (1, 0, 1, 1), (1, 0, 1, -1), (1, 0, -1, 1), (1, 0, -1, -1),
- (-1, 0, 1, 1), (-1, 0, 1, -1), (-1, 0, -1, 1), (-1, 0, -1, -1),
- (1, 1, 0, 1), (1, 1, 0, -1), (1, -1, 0, 1), (1, -1, 0, -1),
- (-1, 1, 0, 1), (-1, 1, 0, -1), (-1, -1, 0, 1), (-1, -1, 0, -1),
- (1, 1, 1, 0), (1, 1, -1, 0), (1, -1, 1, 0), (1, -1, -1, 0),
- (-1, 1, 1, 0), (-1, 1, -1, 0), (-1, -1, 1, 0), (-1, -1, -1, 0))
- # A lookup table to traverse the simplex around a given point in 4D.
- # Details can be found where this table is used, in the 4D noise method.
- _SIMPLEX = (
- (0, 1, 2, 3), (0, 1, 3, 2), (0, 0, 0, 0), (0, 2, 3, 1), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (1, 2, 3, 0),
- (0, 2, 1, 3), (0, 0, 0, 0), (0, 3, 1, 2), (0, 3, 2, 1), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (1, 3, 2, 0),
- (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0),
- (1, 2, 0, 3), (0, 0, 0, 0), (1, 3, 0, 2), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (2, 3, 0, 1), (2, 3, 1, 0),
- (1, 0, 2, 3), (1, 0, 3, 2), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (2, 0, 3, 1), (0, 0, 0, 0), (2, 1, 3, 0),
- (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0),
- (2, 0, 1, 3), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (3, 0, 1, 2), (3, 0, 2, 1), (0, 0, 0, 0), (3, 1, 2, 0),
- (2, 1, 0, 3), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (3, 1, 0, 2), (0, 0, 0, 0), (3, 2, 0, 1), (3, 2, 1, 0))
- # Simplex skew constants
- _F2 = 0.5 * (sqrt(3.0) - 1.0)
- _G2 = (3.0 - sqrt(3.0)) / 6.0
- _F3 = 1.0 / 3.0
- _G3 = 1.0 / 6.0
- class BaseNoise:
- """Noise abstract base class"""
- permutation = (151, 160, 137, 91, 90, 15,
- 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
- 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
- 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
- 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
- 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
- 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
- 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
- 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
- 129, 22, 39, 253, 9, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
- 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
- 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
- 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180)
- period = len(permutation)
- # Double permutation array so we don't need to wrap
- permutation = permutation * 2
- def __init__(self, period=None, permutation_table=None):
- """Initialize the noise generator. With no arguments, the default
- period and permutation table are used (256). The default permutation
- table generates the exact same noise pattern each time.
- An integer period can be specified, to generate a random permutation
- table with period elements. The period determines the (integer)
- interval that the noise repeats, which is useful for creating tiled
- textures. period should be a power-of-two, though this is not
- enforced. Note that the speed of the noise algorithm is independent of
- the period size, though larger periods mean a larger table, which
- consume more memory.
- A permutation table consisting of an iterable sequence of whole
- numbers can be specified directly. This should have a power-of-two
- length. Typical permutation tables are a sequnce of unique integers in
- the range [0,period) in random order, though other arrangements could
- prove useful, they will not be "pure" simplex noise. The largest
- element in the sequence must be no larger than period-1.
- period and permutation_table may not be specified together.
- """
- if period is not None and permutation_table is not None:
- raise ValueError(
- 'Can specify either period or permutation_table, not both')
- if period is not None:
- self.randomize(period)
- elif permutation_table is not None:
- self.permutation = tuple(permutation_table) * 2
- self.period = len(permutation_table)
- def randomize(self, period=None):
- """Randomize the permutation table used by the noise functions. This
- makes them generate a different noise pattern for the same inputs.
- """
- if period is not None:
- self.period = period
- perm = list(range(self.period))
- perm_right = self.period - 1
- for i in list(perm):
- j = randint(0, perm_right)
- perm[i], perm[j] = perm[j], perm[i]
- self.permutation = tuple(perm) * 2
- class SimplexNoise(BaseNoise):
- """Perlin simplex noise generator
- Adapted from Stefan Gustavson's Java implementation described here:
- http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
- To summarize:
- "In 2001, Ken Perlin presented 'simplex noise', a replacement for his classic
- noise algorithm. Classic 'Perlin noise' won him an academy award and has
- become an ubiquitous procedural primitive for computer graphics over the
- years, but in hindsight it has quite a few limitations. Ken Perlin himself
- designed simplex noise specifically to overcome those limitations, and he
- spent a lot of good thinking on it. Therefore, it is a better idea than his
- original algorithm. A few of the more prominent advantages are:
- * Simplex noise has a lower computational complexity and requires fewer
- multiplications.
- * Simplex noise scales to higher dimensions (4D, 5D and up) with much less
- computational cost, the complexity is O(N) for N dimensions instead of
- the O(2^N) of classic Noise.
- * Simplex noise has no noticeable directional artifacts. Simplex noise has
- a well-defined and continuous gradient everywhere that can be computed
- quite cheaply.
- * Simplex noise is easy to implement in hardware."
- """
- def noise2(self, x, y):
- """2D Perlin simplex noise.
- Return a floating point value from -1 to 1 for the given x, y coordinate.
- The same value is always returned for a given x, y pair unless the
- permutation table changes (see randomize above).
- """
- # Skew input space to determine which simplex (triangle) we are in
- s = (x + y) * _F2
- i = floor(x + s)
- j = floor(y + s)
- t = (i + j) * _G2
- x0 = x - (i - t) # "Unskewed" distances from cell origin
- y0 = y - (j - t)
- if x0 > y0:
- i1 = 1
- j1 = 0 # Lower triangle, XY order: (0,0)->(1,0)->(1,1)
- else:
- i1 = 0
- j1 = 1 # Upper triangle, YX order: (0,0)->(0,1)->(1,1)
- x1 = x0 - i1 + _G2 # Offsets for middle corner in (x,y) unskewed coords
- y1 = y0 - j1 + _G2
- x2 = x0 + _G2 * 2.0 - 1.0 # Offsets for last corner in (x,y) unskewed coords
- y2 = y0 + _G2 * 2.0 - 1.0
- # Determine hashed gradient indices of the three simplex corners
- perm = self.permutation
- ii = int(i) % self.period
- jj = int(j) % self.period
- gi0 = perm[ii + perm[jj]] % 12
- gi1 = perm[ii + i1 + perm[jj + j1]] % 12
- gi2 = perm[ii + 1 + perm[jj + 1]] % 12
- # Calculate the contribution from the three corners
- tt = 0.5 - x0 ** 2 - y0 ** 2
- if tt > 0:
- g = _GRAD3[gi0]
- noise = tt ** 4 * (g[0] * x0 + g[1] * y0)
- else:
- noise = 0.0
- tt = 0.5 - x1 ** 2 - y1 ** 2
- if tt > 0:
- g = _GRAD3[gi1]
- noise += tt ** 4 * (g[0] * x1 + g[1] * y1)
- tt = 0.5 - x2 ** 2 - y2 ** 2
- if tt > 0:
- g = _GRAD3[gi2]
- noise += tt ** 4 * (g[0] * x2 + g[1] * y2)
- return noise * 70.0 # scale noise to [-1, 1]
- def noise3(self, x, y, z):
- """3D Perlin simplex noise.
- Return a floating point value from -1 to 1 for the given x, y, z coordinate.
- The same value is always returned for a given x, y, z pair unless the
- permutation table changes (see randomize above).
- """
- # Skew the input space to determine which simplex cell we're in
- s = (x + y + z) * _F3
- i = floor(x + s)
- j = floor(y + s)
- k = floor(z + s)
- t = (i + j + k) * _G3
- x0 = x - (i - t) # "Unskewed" distances from cell origin
- y0 = y - (j - t)
- z0 = z - (k - t)
- # For the 3D case, the simplex shape is a slightly irregular tetrahedron.
- # Determine which simplex we are in.
- if x0 >= y0:
- if y0 >= z0:
- i1 = 1
- j1 = 0
- k1 = 0
- i2 = 1
- j2 = 1
- k2 = 0
- elif x0 >= z0:
- i1 = 1
- j1 = 0
- k1 = 0
- i2 = 1
- j2 = 0
- k2 = 1
- else:
- i1 = 0
- j1 = 0
- k1 = 1
- i2 = 1
- j2 = 0
- k2 = 1
- else: # x0 < y0
- if y0 < z0:
- i1 = 0
- j1 = 0
- k1 = 1
- i2 = 0
- j2 = 1
- k2 = 1
- elif x0 < z0:
- i1 = 0
- j1 = 1
- k1 = 0
- i2 = 0
- j2 = 1
- k2 = 1
- else:
- i1 = 0
- j1 = 1
- k1 = 0
- i2 = 1
- j2 = 1
- k2 = 0
- # Offsets for remaining corners
- x1 = x0 - i1 + _G3
- y1 = y0 - j1 + _G3
- z1 = z0 - k1 + _G3
- x2 = x0 - i2 + 2.0 * _G3
- y2 = y0 - j2 + 2.0 * _G3
- z2 = z0 - k2 + 2.0 * _G3
- x3 = x0 - 1.0 + 3.0 * _G3
- y3 = y0 - 1.0 + 3.0 * _G3
- z3 = z0 - 1.0 + 3.0 * _G3
- # Calculate the hashed gradient indices of the four simplex corners
- perm = self.permutation
- ii = int(i) % self.period
- jj = int(j) % self.period
- kk = int(k) % self.period
- gi0 = perm[ii + perm[jj + perm[kk]]] % 12
- gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12
- gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12
- gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12
- # Calculate the contribution from the four corners
- noise = 0.0
- tt = 0.6 - x0 ** 2 - y0 ** 2 - z0 ** 2
- if tt > 0:
- g = _GRAD3[gi0]
- noise = tt ** 4 * (g[0] * x0 + g[1] * y0 + g[2] * z0)
- else:
- noise = 0.0
- tt = 0.6 - x1 ** 2 - y1 ** 2 - z1 ** 2
- if tt > 0:
- g = _GRAD3[gi1]
- noise += tt ** 4 * (g[0] * x1 + g[1] * y1 + g[2] * z1)
- tt = 0.6 - x2 ** 2 - y2 ** 2 - z2 ** 2
- if tt > 0:
- g = _GRAD3[gi2]
- noise += tt ** 4 * (g[0] * x2 + g[1] * y2 + g[2] * z2)
- tt = 0.6 - x3 ** 2 - y3 ** 2 - z3 ** 2
- if tt > 0:
- g = _GRAD3[gi3]
- noise += tt ** 4 * (g[0] * x3 + g[1] * y3 + g[2] * z3)
- return noise * 32.0
- def lerp(t, a, b):
- return a + t * (b - a)
- def grad3(hash, x, y, z):
- g = _GRAD3[hash % 16]
- return x * g[0] + y * g[1] + z * g[2]
- class TileableNoise(BaseNoise):
- """Tileable implementation of Perlin "improved" noise. This
- is based on the reference implementation published here:
- http://mrl.nyu.edu/~perlin/noise/
- """
- def noise3(self, x, y, z, repeat, base=0.0):
- """Tileable 3D noise.
- repeat specifies the integer interval in each dimension
- when the noise pattern repeats.
- base allows a different texture to be generated for
- the same repeat interval.
- """
- i = int(fmod(floor(x), repeat))
- j = int(fmod(floor(y), repeat))
- k = int(fmod(floor(z), repeat))
- ii = (i + 1) % repeat
- jj = (j + 1) % repeat
- kk = (k + 1) % repeat
- if base:
- i += base
- j += base
- k += base
- ii += base
- jj += base
- kk += base
- x -= floor(x)
- y -= floor(y)
- z -= floor(z)
- fx = x ** 3 * (x * (x * 6 - 15) + 10)
- fy = y ** 3 * (y * (y * 6 - 15) + 10)
- fz = z ** 3 * (z * (z * 6 - 15) + 10)
- perm = self.permutation
- A = perm[i]
- AA = perm[A + j]
- AB = perm[A + jj]
- B = perm[ii]
- BA = perm[B + j]
- BB = perm[B + jj]
- return lerp(fz, lerp(fy, lerp(fx, grad3(perm[AA + k], x, y, z),
- grad3(perm[BA + k], x - 1, y, z)),
- lerp(fx, grad3(perm[AB + k], x, y - 1, z),
- grad3(perm[BB + k], x - 1, y - 1, z))),
- lerp(fy, lerp(fx, grad3(perm[AA + kk], x, y, z - 1),
- grad3(perm[BA + kk], x - 1, y, z - 1)),
- lerp(fx, grad3(perm[AB + kk], x, y - 1, z - 1),
- grad3(perm[BB + kk], x - 1, y - 1, z - 1))))
- _simplex = SimplexNoise()
- snoise2 = _simplex.noise2
- snoise3 = _simplex.noise3
- _tileable = TileableNoise()
- tnoise3 = _tileable.noise3
|