Package tdl :: Module noise |
[frames] | no frames]

# Source Code for Module tdl.noise

      1  """
      2      This module provides advanced noise generation.
      3
      4      Noise is sometimes used for over-world generation, height-maps, and
      5      cloud/mist/smoke effects among other things.
      6
      7      You can see examples of the available noise algorithms in the libtcod
      8      documentation
      9      U{here<http://doryen.eptalys.net/data/libtcod/doc/1.5.1/html2/noise.html>}.
     10  """
     11
     12
     13  import random
     14  import itertools
     15  import ctypes
     16
     17  import tdl
     18  from tdl.__tcod import _lib
     19
     20  _MERSENNE_TWISTER = 1
     21  _CARRY_WITH_MULTIPLY = 2
     22
     23  _MAX_DIMENSIONS = 4
     24  _MAX_OCTAVES = 128
     25
     26  _NOISE_TYPES = {'PERLIN': 1, 'SIMPLEX': 2, 'WAVELET': 4}
     27  _NOISE_MODES = {'FLAT': _lib.TCOD_noise_get,
     28                  'FBM': _lib.TCOD_noise_get_fbm,
     29                  'TURBULENCE': _lib.TCOD_noise_get_turbulence}
     30
     31 -class Noise(object):
     32      """An advanced noise generator.
     33      """
     34
     35 -    def __init__(self, algorithm='PERLIN', mode='FLAT',
     36                   hurst=0.5, lacunarity=2.0, octaves=4.0, seed=None, dimensions=4):
     37          """Create a new noise generator specifying a noise algorithm and how
     38          it's used.
     39
     40          @type algorithm: string
     41          @param algorithm: The primary noise algorithm to be used.
     42
     43                            Can be one of 'PERLIN', 'SIMPLEX', 'WAVELET'
     44                             - 'PERLIN' -
     45                               A popular noise generator.
     46
     47                             - 'SIMPLEX' -
     48                               In theory this is a slightly faster generator with
     49                               less noticeable directional artifacts.
     50
     51                             - 'WAVELET'
     52                               A noise generator designed to reduce aliasing and
     53                               not lose detail when summed into a fractal
     54                               (as with the 'FBM' and 'TURBULENCE' modes.)
     55
     56                               This works faster at higher dimensions.
     57
     58          @type mode: string
     59          @param mode: A secondary parameter to determine how noise is generated.
     60
     61                       Can be one of 'FLAT', 'FBM', 'TURBULENCE'
     62                        - 'FLAT' -
     63                          Generates the simplest form of noise.
     64                          This mode does not use the hurst, lacunarity,
     65                          and octaves parameters.
     66
     67                        - 'FBM' -
     68                          Generates fractal brownian motion.
     69
     70                        - 'TURBULENCE' -
     71                          Generates detailed noise with smoother and more
     72                          natural transitions.
     73
     74          @type hurst: float
     75          @param hurst: The hurst exponent describes the raggedness of the
     76                        resultant noise, with a higher value leading to a
     77                        smoother noise.
     78                        It should be in the 0.0-1.0 range.
     79
     80                        This is only used in 'FBM' and 'TURBULENCE' modes.
     81
     82          @type lacunarity: float
     83          @param lacunarity: A multiplier that determines how quickly the
     84                             frequency increases for each successive octave.
     85
     86                             The frequency of each successive octave is equal to
     87                             the product of the previous octave's frequency and
     88                             the lacunarity value.
     89
     90                             This is only used in 'FBM' and 'TURBULENCE' modes.
     91
     92          @type octaves: float
     93          @param octaves: Controls the amount of detail in the noise.
     94
     95                          This is only used in 'FBM' and 'TURBULENCE' modes.
     96
     97          @type seed: object
     98          @param seed: You can use any hashable object to be a seed for the
     99                       noise generator.
    100
    101                       If None is used then a random seed will be generated.
    102          """
    103          if algorithm.upper() not in _NOISE_TYPES:
    104              raise tdl.TDLError('No such noise algorithm as %s' % algorithm)
    105          self._algorithm = algorithm.upper()
    106
    107          if mode.upper() not in _NOISE_MODES:
    108              raise tdl.TDLError('No such mode as %s' % mode)
    109          self._mode = mode.upper()
    110
    111          if seed is None:
    112              seed = random.getrandbits(32)
    113          else:
    114              seed = hash(seed)
    115          self._seed = seed
    116          # convert values into ctypes to speed up later functions
    117          self._dimensions = min(_MAX_DIMENSIONS, int(dimensions))
    118          if self._algorithm == 'WAVELET':
    119              self._dimensions = min(self._dimensions, 3) # Wavelet only goes up to 3
    120          self._random = _lib.TCOD_random_new_from_seed(self._seed, _MERSENNE_TWISTER)
    121          self._hurst = ctypes.c_float(hurst)
    122          self._lacunarity = ctypes.c_float(lacunarity)
    123          self._noise = _lib.TCOD_noise_new(self._dimensions, self._hurst,
    124                                            self._lacunarity, self._random)
    125          _lib.TCOD_noise_set_type(self._noise, _NOISE_TYPES[self._algorithm])
    126          self._noiseFunc = _NOISE_MODES[self._mode]
    127          self._octaves = ctypes.c_float(octaves)
    128          self._useOctaves = (self._mode != 'FLAT')
    129          self._cFloatArray = ctypes.c_float * self._dimensions
    130          self._array = self._cFloatArray()
    131
    132 -    def __copy__(self):
    133          # using the pickle method is a convenient way to clone this object
    134          self.__class__(self.__getstate__())
    135
    136 -    def __getstate__(self):
    137          return (self._algorithm, self._mode,
    138                  self._hurst.value, self._lacunarity.value, self._octaves.value,
    139                  self._seed, self._dimensions)
    140
    141 -    def __setstate__(self, state):
    142          self.__init__(*state)
    143
    144 -    def getPoint(self, *position):
    145          """Return the noise value of a specific position.
    146
    147          Example usage: value = noise.getPoint(x, y, z)
    148          @type position: floats
    149          @param position:
    150
    151          @rtype: float
    152          @return: Returns the noise value at position.
    153                   This will be a floating point in the 0.0-1.0 range.
    154          """
    155          #array = self._array
    156          #for d, pos in enumerate(position):
    157          #    array[d] = pos
    158          array = self._cFloatArray(*position)
    159          if self._useOctaves:
    160              return (self._noiseFunc(self._noise, array, self._octaves) + 1) * 0.5
    161          return (self._noiseFunc(self._noise, array) + 1) * 0.5
    162
    163 -    def __del__(self):
    164          _lib.TCOD_random_delete(self._random)
    165          _lib.TCOD_noise_delete(self._noise)
    166
    167  __all__ = ['Noise']
    168