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