TGC Codebase Backup



Noise Library Part 1: NoiseGen.dba by The Sab

31st Oct 2010 9:53
Summary

A noise generating library written by Jason Bevins and Keith Davies for C++. Translated for use with Dark Basic Pro.



Description

1.1 Changes:
-Minor fixes. Added some Get functions that were overlooked.

NoiseGen Instructions:

NoiseGen_Setup() must be called by your main program to initialize some arrays and variables

Creating noise modules:

variable = Create_Module(module_type)

Generator Module Types with corrisponding parameters:

MOD_BILLOW Clumpy, cloud-like noise
parameters: frequency, lacunarity, octaveCount, persistence, noiseQuality, seed
MOD_CHECKERBOARD Repeating, alternating squares
parameters: none
MOD_CONST Single value over entire noisemap
parameters: constValue
MOD_CYLINDERS Concentric cylinders. Hard to explain, and even harder to visualize without a 3d modeler
parameters: frequency
MOD_PERLIN The Mother of All Noise.
parameters: frequency, lacunarity, octaveCount, persistence, noiseQuality, seed
MOD_RIDGEDMULTI Creates mountain-like ridges
parameters: frequency, lacunarity, octaveCount, noiseQuality, seed
MOD_SPHERES Concentric spheres.
parameters: frequency
MOD_VORONOI Odd, plateau-like groupings of values
parameters: frequency, seed, displacement, enableDistance

Modifier Modules:

MOD_ABS Gets the absolute value of the source module
parameters: source0
MOD_CLAMP Forces all source values between the lower and upper bounds provided
parameters: source0, lowerBound, upperBound
MOD_CURVE Adjusts all source values to fit along a defined curve
parameters: source0, 4x ControlPoints (see detailed description below)
MOD_EXPONENT Raises all source values by a provided exponent
parameters: source0, exponent
MOD_INVERT Makes all positive source values negative and vice versa
parameters: source0
MOD_SCALEBIAS Scales all source values by an amount provided, and also lowers or raises all values by a specified amount
parameters: source0, scale, bias
MOD_TERRACE Adjusts all source values to fit a defiend terracing curve
parameters: source0, invertTerrace, 2x ControlPoints (see detailed description below)

Combiner Modules:

MOD_ADD Adds the values of both sources together
parameters: source0, source1
MOD_MAX Compares each value of both sources, and returns the highest
parameters: source0, source1
MOD_MIN Compares each value of both sources, and returns the lowest
parameters: source0, source1
MOD_MULTIPLY Multiplies the values of both sources together
parameters: source0, source1
MOD_POWER Raises each value of source0 by the corrisponding value of source1
parameters: source0, source1

Selector Modules:

MOD_BLEND Mixes the two sources using the control as an alpha channel (low control values mean more of source0 shows, higher control values means more of source1 shows)
parameters: source0, source1, control
MOD_SELECT Selects one source or the other depending on the control value range (any control value within the specified range will use source1 values, otherwise source0 values will be used)
parameters: source0, source1, control, lowerbound, upperbound, falloff

Transformer Modules:

MOD_DISPLACE Shifts all values from source0. The x-axis is shifted by source1, y-axis by source2, z-axis by source3
parameters: source0, source1, source2, source3
MOD_ROTATEPOINT Rotates the entire source along the provided angles.
parameters: source0, XYZAngles (see detailed description below)
MOD_SCALEPOINT Stretches or compresses source values along provided x, y, and z amounts
parameters: source0, XYZScale (see detailed description below)
MOD_TRANSLATEPOINT Shifts all values from source0 by the specified x, y, z amounts
parameters: source0, XYZTranslation (see detailed description below)
MOD_TURBULANCE Swirls up all the values from source0 using an internal perlin noise function for each axis
parameters: source0, power, roughness, frequency, seed

Parameters and how to set them:

source0 Set_Source0(main_module, source_module)
source1 Set_Source1(main_module, source_module)
source2 Set_Source2(main_module, source_module)
source3 Set_Source3(main_module, source_module)
control Set_Control(main_module, control_module)
All sources and controls default to -1, which will produce an error, so if a module requires a source, you must set it.

frequency Set_Frequency(main_module, float value) Default 1.0
Frequency is how often a wave completes a cycle in a give interval: higher frequency equals more but smaller artifacts

lacunarity Set_Lacunarity(main_module, float value) Default 2.0
Lacunarity is how much the frequency changes between octaves: 2.0 means the frequency doubles every octave.

octaveCount Set_OctaveCount(main_module, integer value) Default 6
Number of octaves to run the noise formula through: more octaves = more detail, but longer processing

persistence Set_Persistence(main_module, float value) Default 0.5
Persistence is how much the amplitude changes between octaves: 0.5 means the amplitude is halved each octave

noiseQuality Set_NoiseQuality(main_module, quality value) Default QUALITY_STD
NoiseQuality comes in three flavors: QUALITY_FAST, QUALITY_STD, and QUALITY_BEST, which use linear, quadratic, and quintic interpolation respectively. Better equals slower.

seed Set_Seed(main_module, integer value) Default 0
If the seed stays the same, then the pattern produced will also be the same every time the program is run. Controlable pseudo-random noise at its best.

amplitude - This is not an adjustable parameter, as all noise modules create values between -1.0 and 1.0
*NOTE* Due to the way Perlin Noise works, if you have more than one octave, you will probably get some values beyond the -1.0..1.0 range. If this is undesirable,
than a Clamp or ScaleBias module should be used to adjust it

constValue Set_ConstValue(main_module, float value) Default 0.0
MOD_CONST only. This is the value that will fill the whole noise map

displacement Set_Displacement(main_module, float value) Default 1.0
enableDistance Set_EnableDistance(main_module, boolean) Default falso
MOD_VORONOI only. Displacement is a multiplier applied to the formula. Setting enableDistance to True causes circular patterns to appear in the mix. I don't know if that is the
intentional outcome, or if I just screwed up the formula.

lowerBound Set_LowerBound(main_module, float value) Default -1.0
upperBound Set_UpperBound(main_module, float value) Default 1.0
These are the bounds by which MOD_CLAMP restrains its values and MOD_SELECT determines which source module gets drawn where.

exponent Set_Exponent(main_module, float value) Default 1.0
MOD_EXPONENT only. The value that the source is raised to.

scale Set_Scale(main_module, float value) Default 1.0
bias Set_Bias(main_module, float value) Default 0.0
MOD_SCALEBIAS only. Scale resizes the entire source module; 0.5 would halve all values in the source, while bias raises or lowers it.

edgeFallOff Set_EdgeFallOff(main_module, float value) Default 0.0
MOD_SELECT only. This value smooths the transition between the borders of the two sources.

power Set_Power(main_module, float value) Default 1.0
roughness *Not set-up yet* Technical issues Default 3
MOD_TURBULENCE only. Power is simply how strong the turbulence is. Roughness is the octaveCount for the 3 built in Perlin functions, which is why I haven't come up with a
good way to set them without causing a crash.

xAngle Set_AnglesXYZ(main_module, float value x, float value y, float value z) Default 0.0 on all of them
yAngle These are the angles that the source image will be rotated around. Angles are in degrees. *
zAngle I am thinking about combining all of these with Scale and Translate, so as just to have an X, Y, Z. I was worried it would be too confusing though, so left it for the time being

xScale Set_ScaleXYZ(main_module, float value x, float value y, float value z) Default 1.0 on all of them
yScale These are what the source module will be scaled by.
zScale

xTranslation Set_TranslationXYZ(main_module, float value x, float value y, float value z) Default 0.0 on all of them
yTranslation These are what the source module will be shifted by
zTranslation

* For those who are familiar with C++ also, and are digging through the code, keep in mind that C++ calculates in radians by default, while DBPro uses degrees by default.

controlPoints Both MOD_CURVE and MOD_TERRACE require an array of control points to work. The controlPoints are similiar, and I used a master array to support them both
I have also put a hard cap of 255 control points for each module(which is obscenely high, so don't complain) and a total number of Curve and Terrace modules
also at 255. C++ has the ability to make instanced arrays. DBPro does not, so this is the only workable solution I could come up with.
Curve_ClearAllControlPoints(main_module) Empties the array for the given MOD_CURVE
Curve_AddControlPoint(main_module, input float, output float) Adds a control point. Can be added in any order, the program will sort them. Minimum of 4 required for Curves

Terrace_ClearAllControlPoints(main_module) Empties the array for the given MOD_TERRACE
Terrace_AddControlPoint(main_module, value float) Adds a control point. Can be added in any order, the program will sort them. Minimum of 2 required for Terraces

invertTerraces Set_InvertTerraces(main_module, boolean) Default False
MOD_TERRACE only. Inverts the terraces.

For MOD_CURVE: When a value is passed to a Curve Module, that value is interpolated between the control points in the array. It can be used to create sharper peaks at extreme values, but more
level values around zero. Hard to explain. Wish I could supply a chart

for MOD_TERRACE: When a value is passed to a Terrace Module, that value will be interpolated between the control points in the array. Values close to the control points won't be changed much, but
the values furtherest between control points will favor the lower control point. Unless invertTerraces is set to True. Again, I wish I could supply a chart.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    `This is a Dark Basic Pro adaptation of 'libnoise', a C++
`library for the generation and manipulation of coherent
`noise. The following were instramental in the creation of the
`C++ libnoise, and also help me greatly in gaining enough
`understanding to translate the code in the first place.

`Great thanks to Jason Bevins and Keith Davies for not only
`creating such an awesome library, but also making it open
`source and setting up an entire website to explaining the
`concepts and principles behind the software.
`http://libnoise.sourceforge.net/index.html

`Perlin Noise — Hugo Elias's webpage contains a very good
`description of Perlin noise and describes its many
`applications. I based a lot of my documentation about coherent
`noise from this site. This page gave me the inspiration to
`create libnoise in the first place. Now that I know how to
`generate Perlin noise, I will never again use cheesy
`subdivision algorithms to create terrain height maps (unless
`I absolutely need the speed.)
`http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

`The Noise Machine — From the master, Ken Perlin himself. This
`page contains a presentation that describes Perlin noise and
`some of its variants. He won an Oscar for creating the Perlin
`noise algorithm!
`http://mrl.nyu.edu/~perlin/

`The Perlin noise math FAQ — A good page that describes Perlin
`noise in plain English with only a minor amount of math. During
`development of libnoise, I noticed that my smooth noise function
`generated terrain with some "regularity" to the terrain features.
`This page describes a better noise function called gradient noise.

`F. Kenton "Doc Mojo" Musgrave's texturing page — This page
`contains links to source code that generates ridged multfractal
`noise, among other types of noise. The fractal.c source file
`contains the code I used in my ridged multifractal class. Musgrave
`is the creator of MojoWorld and is also one of the authors of
`Texturing and Modeling: A Procedural Approach (Morgan Kaufmann,
`2002. ISBN 1-55860-848-6.)


`Due to the significant differences between C++ and Dark Basic,
`I had to make a few changes to how functions are called.  This
`is mostly due to the fact that DBPro cannot create Classes. The
`modules here are basically hard coded, so adding more will take
`a little recoding.

#include "math.dba"
#include "modules.dba"
#include "vectorTable.dba"

`Generator ID constants
#constant MOD_BILLOW 1
#constant MOD_CHECKERBOARD 2
#constant MOD_CONST 3
#constant MOD_CYLINDERS 4
#constant MOD_PERLIN 5
#constant MOD_RIDGEDMULTI 6
#constant MOD_SPHERES 7
#constant MOD_VORONOI 8

`Modifier ID constants
#constant MOD_ABS 9
#constant MOD_CLAMP 10
#constant MOD_CURVE 11
#constant MOD_EXPONENT 12
#constant MOD_INVERT 13
#constant MOD_SCALEBIAS 14
#constant MOD_TERRACE 15

`Combiner ID constants
#constant MOD_ADD 16
#constant MOD_MAX 17
#constant MOD_MIN 18
#constant MOD_MULTIPLY 19
#constant MOD_POWER 20

`Combiner ID constants
#constant MOD_BLEND 21
#constant MOD_SELECT 22

`Transformer ID constants
#constant MOD_DISPLACE 23
#constant MOD_ROTATEPOINT 24
#constant MOD_SCALEPOINT 25
#constant MOD_TRANSLATEPOINT 26
#constant MOD_TURBULENCE 27

`Model ID constants
#constant MOD_PLANE 28
#constant MOD_CYLINDER 29
#constant MOD_SPHERE 30

`Interpolation Quaility constants
#constant QUALITY_FAST 0
#constant QUALITY_STD 1
#constant QUALITY_BEST 2

`Seed numbers for magic random make work thing
#constant X_NOISE_GEN 1619
#constant Y_NOISE_GEN 31337
#constant Z_NOISE_GEN 6971
#constant SEED_NOISE_GEN 1013
#constant SHIFT_NOISE_GEN 8

`The Module_Set Type has all the variables for all the modules,
`regardless of the fact that some are only used by one module.
`It seems wasteful, but it was the only way I could figure to
`do it.
type Module_Set
   moduleProcedure as integer
   source0 as integer
   source1 as integer
   source2 as integer
   source3 as integer
   control as integer
   frequency as float
   lacunarity as float
   octaveCount as integer
   persistence as float
   noiseQuality as integer
   seed as integer
   constValue as float
   displacement as float
   lowerBound as float
   upperBound as float
   controlPointCount as integer
   exponent as float
   bias as float
   scale as float
   edgeFallOff as float
   pointX as float
   pointY as float
   pointZ as float
   power as float
   enableDistance as boolean
   invertTerraces as boolean
   controlPointsSet as integer
   x1Matrix as float
   y1Matrix as float
   z1Matrix as float
   x2Matrix as float
   y2Matrix as float
   z2Matrix as float
   x3Matrix as float
   y3Matrix as float
   z3Matrix as float
   xAngle as float
   yAngle as float
   zAngle as float
   xScale as float
   yScale as float
   zScale as float
   xTranslation as float
   yTranslation as float
   zTranslation as float
endtype

`A couple of the modules use a Control Point array.  Only one
`of them has an input and output Value, so the Type only gets
`used once.
type typeControlPoint
   inputValue as float
   outputValue as float
endtype

`This function must be called by the parent application to
`set up some basic functionality.
function NoiseGen_Setup()
   `A count of how many modules have been created, so that
   `integers can be assigned.
   global moduleCount as integer
   moduleCount = 0

   `An array of Module Sets.  This is how I simulate the
   `ability to make multiple instances of modules, each
   `with their own set of variables.
   global dim module_sets() as Module_Set

   `Initialize the control point array for Curve and Terrace
   global dim ControlPoints(255, 255) as typeControlPoint
   global ControlPointsSetCount as integer
   ControlPointsSetCount = 0

   `This command will build an array of Vectors.  1024 lines
   `of float values.  That was fun to transcribe.
   Build_Vector_Tables()
endfunction

function GradientCoherentNoise3D(index as integer, x as float, y as float, z as float, seed as integer)
   result as float
   `Create a unit-length cube aligned along an integer boundary.  This cube
   `surrounds the input point.
   if x > 0.0
      x0 = int(x)
   else
      x0 = int(x) - 1
   endif
   x1 = x0 + 1
   if y > 0.0
      y0 = int(y)
   else
      y0 = int(y) - 1
   endif
   y1 = y0 + 1
   if z > 0.0
      z0 = int(z)
   else
      z0 = int(z) - 1
   endif
   z1 = z0 + 1

   `Map the difference between the coordinates of the input value and the
   `coordinates of the cube's outer-lower-left vertex onto an S-curve.
   xs as float
   ys as float
   zs as float
   xs = 0.0
   ys = 0.0
   zs = 0.0
   select module_sets(index).noiseQuality
      case QUALITY_FAST:
         xs = (x - x0)
         ys = (y - y0)
         zs = (z - z0)
      endcase
      case QUALITY_STD:
         xs = SCurve3(x - x0)
         ys = SCurve3(y - y0)
         zs = SCurve3(z - z0)
      endcase
      case QUALITY_BEST:
         xs = SCurve5(x - x0)
         ys = SCurve5(y - y0)
         zs = SCurve5(z - z0)
      endcase
   endselect

   `Now calculate the noise values at each vertex of the cube.  To generate
   `the coherent-noise value at the input point, interpolate these eight
   `noise values using the S-curve value as the interpolant (trilinear
   `interpolation.)
   n0 as float
   n1 as float
   ix0 as float
   ix1 as float
   iy0 as float
   iy1 as float

   n0 = GradientNoise3D(x, y, z, x0, y0, z0, seed)
   n1 = GradientNoise3D(x, y, z, x1, y0, z0, seed)
   ix0 = LinearInterp(n0, n1, xs)
   n0 = GradientNoise3D(x, y, z, x0, y1, z0, seed)
   n1 = GradientNoise3D(x, y, z, x1, y1, z0, seed)
   ix1 = LinearInterp(n0, n1, xs)
   iy0 = LinearInterp(ix0, ix1, ys)
   n0 = GradientNoise3D(x, y, z, x0, y0, z1, seed)
   n1 = GradientNoise3D(x, y, z, x1, y0, z1, seed)
   ix0 = LinearInterp(n0, n1, xs)
   n0 = GradientNoise3D(x, y, z, x0, y1, z1, seed)
   n1 = GradientNoise3D(x, y, z, x1, y1, z1, seed)
   ix1 = LinearInterp(n0, n1, xs)
   iy1 = LinearInterp(ix0, ix1, ys)

   result = LinearInterp(iy0, iy1, zs)
endfunction result

function GradientNoise3D(fx as float, fy as float, fz as float, ix as integer, iy as integer, iz as integer, seed as integer)
   result as float
   `Randomly generate a gradient vector given the integer coordinates of the
   `input value.  This implementation generates a random number and uses it
   `as an index into a normalized-vector lookup table.
   vectorIndex = (X_NOISE_GEN * ix + Y_NOISE_GEN * iy + Z_NOISE_GEN * iz + SEED_NOISE_GEN * seed) && 0xffffffff
   vectorIndex = vectorIndex ~~ (vectorIndex >> SHIFT_NOISE_GEN)
   vectorIndex = vectorIndex && 0xff

   xvGradient as float
   yvGradient as float
   zvGradient as float

   xvGradient = vector_table(vectorIndex << 2)
   yvGradient = vector_table((vectorIndex << 2) + 1)
   zvGradient = vector_table((vectorIndex << 2) + 2)

   `Set up us another vector equal to the distance between the two vectors
   `passed to this function.
   xvPoint as float
   yvPoint as float
   zvPoint as float

   xvPoint = (fx - ix)
   yvPoint = (fy - iy)
   zvPoint = (fz - iz)

   `Now compute the dot product of the gradient vector with the distance
   `vector.  The resulting value is gradient noise.  Apply a scaling value
   `so that this noise value ranges from -1.0 to 1.0.
   result = ((xvGradient * xvPoint) + (yvGradient * yvPoint) + (zvGradient * zvPoint)) * 2.12
endfunction result

function IntValueNoise3D(x as integer, y as integer, z as integer, seed as integer)
   result as integer
   `All constants are primes and must remain prime in order for this noise
   `function to work correctly.
   n = (X_NOISE_GEN * x + Y_NOISE_GEN * y + Z_NOISE_GEN * z + SEED_NOISE_GEN * seed) && 0x7fffffff
   n = (n >> 13) ~~ n
   result = (n * (n * n * 60493 + 19990303) + 1376312589) && 0x7fffffff
endfunction result

function ValueCoherentNoise3D(index as integer, x as float, y as float, z as float, seed as integer)
   result as float
   `Create a unit-length cube aligned along an ingeger boundary.  This cube
   `surrounds the input point.
   if x > 0.0
      x0 = int(x)
   else
      x0 = int(x) - 1
   endif
   x1 = x0 + 1
   if y > 0.0
      y0 = int(y)
   else
      y0 = int(y) - 1
   endif
   y1 = y0 + 1
   if z > 0.0
      z0 = int(z)
   else
      z0 = int(z) - 1
   endif
   z1 = z0 + 1

   `Map the difference between the coordinates of the input value and the
   `coordinates of the cube's outer-lower-left vertex onto an S-curve.
   xs as float
   ys as float
   zs as float
   xs = 0.0
   ys = 0.0
   zs = 0.0
   select module_sets(index).noiseQuality
      case QUALITY_FAST:
         xs = (x - x0)
         ys = (y - y0)
         zs = (z - z0)
      endcase
      case QUALITY_STD:
         xs = SCurve3(x - x0)
         ys = SCurve3(y - y0)
         zs = SCurve3(z - z0)
      endcase
      case QUALITY_BEST:
         xs = SCurve5(x - x0)
         ys = SCurve5(y - y0)
         zs = SCurve5(z - z0)
      endcase
   endselect

   `Now calculate the noise values at each vertex of the cube.  To generate
   `the coherent-noise value at the input point, interpolate these eight
   `noise values using the S-curve value as the interpolant (trilinear
   `interpolation.)
   n0 as float
   n1 as float
   ix0 as float
   ix1 as float
   iy0 as float
   iy1 as float

   n0 = ValueNoise3D(x0, y0, z0, seed)
   n1 = ValueNoise3D(x1, y0, z0, seed)
   ix0 = LinearInterp(n0, n1, xs)
   n0 = ValueNoise3D(x0, y1, z0, seed)
   n1 = ValueNoise3D(x1, y1, z0, seed)
   ix1 = LinearInterp(n0, n1, xs)
   iy0 = LinearInterp(ix0, ix1, ys)
   n0 = ValueNoise3D(x0, y0, z1, seed)
   n1 = ValueNoise3D(x1, y0, z1, seed)
   ix0 = LinearInterp(n0, n1, xs)
   n0 = ValueNoise3D(x0, y1, z1, seed)
   n1 = ValueNoise3D(x1, y1, z1, seed)
   ix1 = LinearInterp(n0, n1, xs)
   iy1 = LinearInterp(ix0, ix1, ys)

   result = LinearInterp (iy0, iy1, zs)
endfunction result

function ValueNoise3D(x as integer, y as integer, z as integer, seed as integer)
   result as float
   result = 1.0 - (IntValueNoise3D(x, y, z, seed) / 1073741824.0)
endfunction result

function SCurve3(a as float)
   result as float
   result = (a ^ 2 * (3.0 - 2.0 * a))
endfunction result

function SCurve5(a as float)
   result as float
   a3 as float
   a4 as float
   a5 as float

   a3 = a ^ 3
   a4 = a ^ 4
   a5 = a ^ 5
   result = (6.0 * a5) - (15.0 * a4) + (10.0 * a3)
endfunction result

`Module Creation.  The function takes a procedural ID and
`returns an integer index number, so that you can assign
`it to a variable of your choosing.
`i.e.: samplePerlin = Create_Module(MOD_PERLIN)
function Create_Module(Modproc as integer)
   index as integer
   array insert at bottom module_sets()
   module_sets(moduleCount).moduleProcedure = Modproc
   index = moduleCount
   moduleCount = moduleCount + 1
   module_sets(index).source0 = -1
   module_sets(index).source1 = -1
   module_sets(index).source2 = -1
   module_sets(index).source3 = -1
   module_sets(index).control = -1
   Module_Setup(index)
endfunction index

`This is an internal function that sends the newly created
`module to its appropriate setup.  Even though all modules
`have all the variables, only certain ones are used with
`specific modules.
function Module_Setup(index as integer)
      select module_sets(index).moduleProcedure
         case MOD_BILLOW:
            Billow_Setup(index)
         endcase
         case MOD_CONST:
            Const_Setup(index)
         endcase
         case MOD_CYLINDERS:
            Cylinders_Setup(index)
         endcase
         case MOD_PERLIN:
            Perlin_Setup(index)
         endcase
         case MOD_RIDGEDMULTI:
            RidgedMulti_Setup(index)
         endcase
         case MOD_SPHERES:
            Spheres_Setup(index)
         endcase
         case MOD_VORONOI:
            Voronoi_Setup(index)
         endcase
         case MOD_CLAMP:
            Clamp_Setup(index)
         endcase
         case MOD_CURVE:
            Curve_Setup(index)
         endcase
         case MOD_EXPONENT:
            Exponent_Setup(index)
         endcase
         case MOD_SCALEBIAS:
            ScaleBias_Setup(index)
         endcase
         case MOD_TERRACE:
            Terrace_Setup(index)
         endcase
         case MOD_SELECT:
            Select_Setup(index)
         endcase
         case MOD_ROTATEPOINT:
            RotatePoint_Setup(index)
         endcase
         case MOD_SCALEPOINT:
            ScalePoint_Setup(index)
         endcase
         case MOD_TRANSLATEPOINT:
            TranslatePoint_Setup(index)
         endcase
         case MOD_TURBULENCE:
            Turbulence_Setup(index)
         endcase
      endselect
endfunction

`This function allows for a universal GetValue function.  It
`references the specific GetValue for the type procedure
`assigned to the module.
function Module_GetValue(index as integer, x as float, y as float, z as float)
   result as float
      select module_sets(index).moduleProcedure
         case MOD_BILLOW:
            result = Billow_GetValue(index, x, y, z)
         endcase
         case MOD_CHECKERBOARD:
            result = Checkerboard_GetValue(index, x, y, z)
         endcase
         case MOD_CONST:
            result = Const_GetValue(index)
         endcase
         case MOD_CYLINDERS:
            result = Cylinders_GetValue(index, x, y, z)
         endcase
         case MOD_PERLIN:
            result = Perlin_GetValue(index, x, y, z)
         endcase
         case MOD_RIDGEDMULTI:
            result = RidgedMulti_GetValue(index, x, y, z)
         endcase
         case MOD_SPHERES:
            result = Spheres_GetValue(index, x, y, z)
         endcase
         case MOD_VORONOI:
            result = Voronoi_GetValue(index, x, y, z)
         endcase
         case MOD_ABS:
            result = Abs_GetValue(index, x, y, z)
         endcase
         case MOD_CLAMP:
            result = Clamp_GetValue(index, x, y, z)
         endcase
         case MOD_CURVE:
            result = Curve_GetValue(index, x, y, z)
         endcase
         case MOD_EXPONENT:
            result = Exponent_GetValue(index, x, y, z)
         endcase
         case MOD_INVERT:
            result = Invert_GetValue(index, x, y, z)
         endcase
         case MOD_SCALEBIAS:
            result = ScaleBias_GetValue(index, x, y, z)
         endcase
         case MOD_TERRACE:
            result = Terrace_GetValue(index, x, y, z)
         endcase
         case MOD_ADD:
            result = Add_GetValue(index, x, y, z)
         endcase
         case MOD_MAX:
            result = Max_GetValue(index, x, y, z)
         endcase
         case MOD_MIN:
            result = Min_GetValue(index, x, y, z)
         endcase
         case MOD_MULTIPLY:
            result = Multiply_GetValue(index, x, y, z)
         endcase
         case MOD_POWER:
            result = Power_GetValue(index, x, y, z)
         endcase
         case MOD_BLEND:
            result = Blend_GetValue(index, x, y, z)
         endcase
         case MOD_SELECT:
            result = Select_GetValue(index, x, y, z)
         endcase
         case MOD_DISPLACE:
            result = Displace_GetValue(index, x, y, z)
         endcase
         case MOD_ROTATEPOINT:
            result = RotatePoint_GetValue(index, x, y, z)
         endcase
         case MOD_SCALEPOINT:
            result = ScalePoint_GetValue(index, x, y, z)
         endcase
         case MOD_TRANSLATEPOINT:
            result = TranslatePoint_GetValue(index, x, y, z)
         endcase
         case MOD_TURBULENCE:
            result = Turbulence_GetValue(index, x, y, z)
         endcase
      endselect
endfunction result

`All of the Get commands.  They take an index number of the
`module and return the appropriate piece of data.
function Get_Source0(index as integer)
   result as integer
   result = module_sets(index).source0
endfunction result

function Get_Source1(index as integer)
   result as integer
   result = module_sets(index).source1
endfunction result

function Get_Source2(index as integer)
   result as integer
   result = module_sets(index).source2
endfunction result

function Get_Source3(index as integer)
   result as integer
   result = module_sets(index).source3
endfunction result

function Get_Control(index as integer)
   result as integer
   result = module_sets(index).control
endfunction result

function Get_Frequency(index as integer)
   result as float
   result = module_sets(index).frequency
endfunction result

function Get_Lacunarity(index as integer)
   result as float
   result = module_sets(index).lacunarity
endfunction result

function Get_OctaveCount(index as integer)
   result as integer
   result = module_sets(index).octaveCount
endfunction result

function Get_Persistence(index as integer)
   result as float
   result = module_sets(index).persistence
endfunction result

function Get_NoiseQuality(index as integer)
   result as integer
   result = module_sets(index).noiseQuality
endfunction result

function Get_Seed(index as integer)
   result as integer
   result = module_sets(index).seed
endfunction result

function Get_ConstValue(index as integer)
   result as float
   result = module_sets(index).constValue
endfunction result

function Get_Displacement(index as integer)
   result as float
   result = module_sets(index).displacement
endfunction result

function Get_LowerBound(index as integer)
   result as float
   result = module_sets(index).lowerBound
endfunction result

function Get_UpperBound(index as integer)
   result as float
   result = module_sets(index).upperBound
endfunction result

function Get_Exponent(index as integer)
   result as float
   result = module_sets(index).exponent
endfunction result

function Get_Bias(index as integer)
   result as float
   result = module_sets(index).bias
endfunction result

function Get_Scale(index as integer)
   result as float
   result = module_sets(index).scale
endfunction result

function Get_EdgeFallOff(index as integer)
   result as float
   result = module_sets(index).edgeFallOff
endfunction result

function Get_PointX(index as integer)
   result as float
   result = module_sets(index).pointX
endfunction result

function Get_PointY(index as integer)
   result as float
   result = module_sets(index).pointY
endfunction result

function Get_PointZ(index as integer)
   result as float
   result = module_sets(index).pointZ
endfunction result

function Get_Power(index as integer)
   result as float
   result = module_sets(index).power
endfunction result

function Get_EnableDistance(index as integer)
   result as boolean
   result = module_sets(index).enableDistance
endfunction result

function Get_InvertTerraces(index as integer)
   result as boolean
   result = module_sets(index).invertTerraces
endfunction result

`All of the Set commands.  They take the index number of the
`Module and a piece of data to assign to the variable.
function Set_Source0(index as integer, s as integer)
   module_sets(index).source0 = s
endfunction

function Set_Source1(index as integer, s as integer)
   module_sets(index).source1 = s
endfunction

function Set_Source2(index as integer, s as integer)
   module_sets(index).source2 = s
endfunction

function Set_Source3(index as integer, s as integer)
   module_sets(index).source3 = s
endfunction

function Set_Control(index as integer, c as integer)
   module_sets(index).control = c
endfunction

function Set_Frequency(index as integer, freq as float)
   module_sets(index).frequency = freq
endfunction

function Set_Lacunarity(index as integer, lac as float)
   module_sets(index).lacunarity = lac
endfunction

function Set_OctaveCount(index as integer, oct as integer)
   module_sets(index).octaveCount = oct
endfunction

function Set_Persistence(index as integer, per as float)
   module_sets(index).persistence = per
endfunction

function Set_NoiseQuality(index as integer, qual as integer)
   module_sets(index).noiseQuality = qual
endfunction

function Set_Seed(index as integer, seed as integer)
   module_sets(index).seed = seed
endfunction

function Set_ConstValue(index as integer, value as float)
   module_sets(index).constValue = value
endfunction

function Set_Displacement(index as integer, dis as float)
   module_sets(index).displacement = dis
endfunction

function Set_LowerBound(index as integer, lb as float)
   module_sets(index).lowerBound = lb
endfunction

function Set_UpperBound(index as integer, ub as float)
   module_sets(index).upperBound = ub
endfunction

function Set_Bounds(index as integer, lb as float, ub as float)
   module_sets(index).lowerBound = lb
   module_sets(index).upperBound = ub
endfunction

function Set_Exponent(index as integer, ex as float)
   module_sets(index).exponent = ex
endfunction

function Set_Bias(index as integer, bias as float)
   module_sets(index).bias = bias
endfunction

function Set_Scale(index as integer, scale as float)
   module_sets(index).scale = scale
endfunction

function Set_EdgeFallOff(index as integer, fo as float)
   module_sets(index).edgeFallOff = fo
endfunction

function Set_PointX(index as integer, px as float)
   module_sets(index).pointx = px
endfunction

function Set_PointY(index as integer, py as float)
   module_sets(index).pointy = py
endfunction

function Set_PointZ(index as integer, pz as float)
   module_sets(index).pointz = pz
endfunction

function Set_ScaleXYZ(index as integer, x as float, y as float, z as float)
   ScalePoint_SetXYZ(index, x, y, z)
endfunction

function Set_AnglesXYZ(index as integer, x as float, y as float, z as float)
   RotatePoint_SetAngles(index, x, y, z)
endfunction

function Set_TranslateXYZ(index as integer, x as float, y as float, z as float)
   TranslatePoint_SetXYZ(index, x, y, z)
endfunction

function Set_Power(index as integer, pow as float)
   module_sets(index).power = pow
endfunction

function Set_EnableDistance(index as integer, d as boolean)
   module_sets(index).enableDistance = d
endfunction

function Set_InvertTerraces(index as integer, i as boolean)
   module_sets(index).invertTerraces = i
endfunction

function ExceptionInvalidParam(index as integer)
   set current bitmap 0
   cls
   set cursor 0, 0
   print "A parameter in module " + str$(index) + " is not set correctly."
   print "Press any key to exit the program."
   wait key
   end
endfunction

function ExceptionNoModule(index as integer)
   set current bitmap 0
   cls
   set cursor 0, 0
   print "A source or control module is missing in module " + str$(index) + "."
   print "Press any key to exit the program."
   wait key
   end
endfunction

function ExceptionOutOfMemory(index as integer)
   set current bitmap 0
   cls
   set cursor 0, 0
   print "Argh, you have managed to use up all of your computers memory!"
   print "This problem occured while processing module " + str$(index) + "."
   print "Press any key to exit the program."
   wait key
   end
endfunction

function ExceptionUnknown(index as integer)
   set current bitmap 0
   cls
   set cursor 0, 0
   print "Something unexpected happen in module " + str$(index) + "."
   print "no more clues to give you.  Good luck."
   print "Press any key to exit the program."
   wait key
   end
endfunction