home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FAQSYS18.ZIP / FAQS.DAT / MUSGRAVE.C < prev    next >
C/C++ Source or Header  |  1996-02-23  |  12KB  |  363 lines

  1. #include <math.h>
  2. #define TRUE    1
  3. #define FALSE   0
  4.  
  5. typedef struct {
  6.         double x;
  7.         double y;
  8.         double z;
  9.         } Vector;
  10.  
  11. /*
  12.  * Procedural fBm evaluated at "point"; returns value stored in "value".
  13.  *
  14.  * Copyright 1994 F. Kenton Musgrave 
  15.  * 
  16.  * Parameters:
  17.  *    ``H''  is the fractal increment parameter
  18.  *    ``lacunarity''  is the gap between successive frequencies
  19.  *    ``octaves''  is the number of frequencies in the fBm
  20.  */
  21. double
  22. fBm( Vector point, double H, double lacunarity, double octaves )
  23. {
  24.  
  25.       double            value, frequency, remainder, Noise3();
  26.       int               i;
  27.       static int        first = TRUE;
  28.       static double     *exponent_array;
  29.  
  30.       /* precompute and store spectral weights */
  31.       if ( first ) {
  32.             /* seize required memory for exponent_array */
  33.             exponent_array = 
  34.                         (double *)malloc( (octaves+1) * sizeof(double) );
  35.             frequency = 1.0;
  36.             for (i=0; i<=octaves; i++) {
  37.                   /* compute weight for each frequency */
  38.                   exponent_array[i] = pow( frequency, -H );
  39.                   frequency *= lacunarity;
  40.             }
  41.             first = FALSE;
  42.       }
  43.  
  44.       value = 0.0;            /* initialize vars to proper values */
  45.       frequency = 1.0;
  46.  
  47.       /* inner loop of spectral construction */
  48.       for (i=0; i<octaves; i++) {
  49.             value += Noise3( point ) * exponent_array[i];
  50.             point.x *= lacunarity;
  51.             point.y *= lacunarity;
  52.             point.z *= lacunarity;
  53.       } /* for */
  54.  
  55.       remainder = octaves - (int)octaves;
  56.       if ( remainder )      /* add in ``octaves''  remainder */
  57.             /* ``i''  and spatial freq. are preset in loop above */
  58.             value += remainder * Noise3( point ) * exponent_array[i];
  59.  
  60.       return( value );
  61.  
  62. } /* fBm() */
  63.  
  64.  
  65. /*
  66.  * Procedural multifractal evaluated at "point"; 
  67.  * returns value stored in "value".
  68.  *
  69.  * Copyright 1994 F. Kenton Musgrave 
  70.  * 
  71.  * Parameters:
  72.  *    ``H''  determines the highest fractal dimension
  73.  *    ``lacunarity''  is gap between successive frequencies
  74.  *    ``octaves''  is the number of frequencies in the fBm
  75.  *    ``offset''  is the zero offset, which determines multifractality
  76.  */
  77. double
  78. multifractal( Vector point, double H, double lacunarity, 
  79.               double octaves, double offset )
  80. {
  81.       double            value, frequency, remainder, Noise3();
  82.       int               i;
  83.       static int        first = TRUE;
  84.       static double     *exponent_array;
  85.  
  86.       /* precompute and store spectral weights */
  87.       if ( first ) {
  88.             /* seize required memory for exponent_array */
  89.             exponent_array = 
  90.                         (double *)malloc( (octaves+1) * sizeof(double) );
  91.             frequency = 1.0;
  92.             for (i=0; i<=octaves; i++) {
  93.                   /* compute weight for each frequency */
  94.                   exponent_array[i] = pow( frequency, -H );
  95.                   frequency *= lacunarity;
  96.             }
  97.             first = FALSE;
  98.       }
  99.  
  100.       value = 1.0;            /* initialize vars to proper values */
  101.       frequency = 1.0;
  102.  
  103.       /* inner loop of multifractal construction */
  104.       for (i=0; i<octaves; i++) {
  105.             value *= offset * frequency * Noise3( point );
  106.             point.x *= lacunarity;
  107.             point.y *= lacunarity;
  108.             point.z *= lacunarity;
  109.       } /* for */
  110.  
  111.       remainder = octaves - (int)octaves;
  112.       if ( remainder )      /* add in ``octaves''  remainder */
  113.             /* ``i''  and spatial freq. are preset in loop above */
  114.             value += remainder * Noise3( point ) * exponent_array[i];
  115.  
  116.       return value;
  117.  
  118. } /* multifractal() */
  119.  
  120.  
  121. /* "Variable Lacunarity Noise"  -or- VLNoise3()
  122.  * A distorted variety of Perlin noise.
  123.  *
  124.  * Copyright 1994 F. Kenton Musgrave 
  125.  */
  126. double
  127. VLNoise3( Vector point, double distortion )
  128. {
  129.         Vector offset, VecNoise3(), AddVectors();
  130.         double Noise3();
  131.  
  132.         offset.x = point.x +0.5;        /* misregister domain */
  133.         offset.y = point.y +0.5;
  134.         offset.z = point.z +0.5;
  135.  
  136.         offset = VecNoise3( offset );   /* get a random vector */
  137.  
  138.         offset.x *= distortion;         /* scale the randomization */
  139.         offset.y *= distortion;
  140.         offset.z *= distortion;
  141.  
  142.         /* ``point'' is the domain; distort domain by adding ``offset'' */
  143.         point = AddVectors( point, offset );
  144.  
  145.         return Noise3( point );         /* distorted-domain noise */
  146.  
  147. } /* VLNoise3() */
  148.  
  149.  
  150. /*
  151.  * Heterogeneous procedural terrain function: stats by altitude method.
  152.  * Evaluated at "point"; returns value stored in "value".
  153.  *
  154.  * Copyright 1994 F. Kenton Musgrave 
  155.  * 
  156.  * Parameters:
  157.  *       ``H''  determines the fractal dimension of the roughest areas
  158.  *       ``lacunarity''  is the gap between successive frequencies
  159.  *       ``octaves''  is the number of frequencies in the fBm
  160.  *       ``offset''  raises the terrain from `sea level'
  161.  */
  162. double
  163. Hetero_Terrain( Vector point,
  164.             double H, double lacunarity, double octaves, double offset )
  165. {
  166.       double          value, increment, frequency, remainder, Noise3();
  167.       int             i;
  168.       static int      first = TRUE;
  169.       static double   *exponent_array;
  170.  
  171.       /* precompute and store spectral weights, for efficiency */
  172.       if ( first ) {
  173.             /* seize required memory for exponent_array */
  174.             exponent_array = 
  175.                         (double *)malloc( (octaves+1) * sizeof(double) );
  176.             frequency = 1.0;
  177.             for (i=0; i<=octaves; i++) {
  178.                   /* compute weight for each frequency */
  179.                   exponent_array[i] = pow( frequency, -H );
  180.                   frequency *= lacunarity;
  181.             }
  182.             first = FALSE;
  183.       }
  184.  
  185.       /* first unscaled octave of function; later octaves are scaled */
  186.       value = offset + Noise3( point );
  187.       point.x *= lacunarity;
  188.       point.y *= lacunarity;
  189.       point.z *= lacunarity;
  190.  
  191.       /* spectral construction inner loop, where the fractal is built */
  192.       for (i=1; i<octaves; i++) {
  193.             /* obtain displaced noise value */
  194.             increment = Noise3( point ) + offset;
  195.             /* scale amplitude appropriately for this frequency */
  196.             increment *= exponent_array[i];
  197.             /* scale increment by current `altitude' of function */
  198.             increment *= value;
  199.             /* add increment to ``value''  */
  200.             value += increment;
  201.             /* raise spatial frequency */
  202.             point.x *= lacunarity;
  203.             point.y *= lacunarity;
  204.             point.z *= lacunarity;
  205.       } /* for */
  206.  
  207.       /* take care of remainder in ``octaves''  */
  208.       remainder = octaves - (int)octaves;
  209.       if ( remainder ) {
  210.             /* ``i''  and spatial freq. are preset in loop above */
  211.             /* note that the main loop code is made shorter here */
  212.             /* you may want to that loop more like this */
  213.             increment = (Noise3( point ) + offset) * exponent_array[i];
  214.             value += remainder * increment * value;
  215.       }
  216.  
  217.       return( value );
  218.  
  219. } /* Hetero_Terrain() */
  220.  
  221.  
  222. /* Hybrid additive/multiplicative multifractal terrain model.
  223.  *
  224.  * Copyright 1994 F. Kenton Musgrave 
  225.  *
  226.  * Some good parameter values to start with:
  227.  *
  228.  *      H:           0.25
  229.  *      offset:      0.7
  230.  */
  231. double 
  232. HybridMultifractal( Vector point, double H, double lacunarity, 
  233.                     double octaves, double offset )
  234. {
  235.       double          frequency, result, signal, weight, remainder; 
  236.       double          Noise3();
  237.       int             i;
  238.       static int      first = TRUE;
  239.       static double   *exponent_array;
  240.  
  241.       /* precompute and store spectral weights */
  242.       if ( first ) {
  243.             /* seize required memory for exponent_array */
  244.             exponent_array = 
  245.                         (double *)malloc( (octaves+1) * sizeof(double) );
  246.             frequency = 1.0;
  247.             for (i=0; i<=octaves; i++) {
  248.                   /* compute weight for each frequency */
  249.                   exponent_array[i] = pow( frequency, -H);
  250.                   frequency *= lacunarity;
  251.             }
  252.             first = FALSE;
  253.       }
  254.  
  255.       /* get first octave of function */
  256.       result = ( Noise3( point ) + offset ) * exponent_array[0];
  257.       weight = result;
  258.       /* increase frequency */
  259.       point.x *= lacunarity;
  260.       point.y *= lacunarity;
  261.       point.z *= lacunarity;
  262.  
  263.       /* spectral construction inner loop, where the fractal is built */
  264.       for (i=1; i<octaves; i++) {
  265.             /* prevent divergence */
  266.             if ( weight > 1.0 )  weight = 1.0;
  267.  
  268.             /* get next higher frequency */
  269.             signal = ( Noise3( point ) + offset ) * exponent_array[i];
  270.             /* add it in, weighted by previous freq's local value */
  271.             result += weight * signal;
  272.             /* update the (monotonically decreasing) weighting value */
  273.             /* (this is why H must specify a high fractal dimension) */
  274.             weight *= signal;
  275.  
  276.             /* increase frequency */
  277.             point.x *= lacunarity;
  278.             point.y *= lacunarity;
  279.             point.z *= lacunarity;
  280.       } /* for */
  281.  
  282.       /* take care of remainder in ``octaves''  */
  283.       remainder = octaves - (int)octaves;
  284.       if ( remainder )
  285.             /* ``i''  and spatial freq. are preset in loop above */
  286.             result += remainder * Noise3( point ) * exponent_array[i];
  287.  
  288.       return( result );
  289.  
  290. } /* HybridMultifractal() */
  291.  
  292.  
  293. /* Ridged multifractal terrain model.
  294.  *
  295.  * Copyright 1994 F. Kenton Musgrave 
  296.  *
  297.  * Some good parameter values to start with:
  298.  *
  299.  *      H:           1.0
  300.  *      offset:      1.0
  301.  *      gain:        2.0
  302.  */
  303. double 
  304. RidgedMultifractal( Vector point, double H, double lacunarity,
  305.                     double octaves, double offset, double gain )
  306. {
  307.       double           result, frequency, signal, weight, Noise3();
  308.       int              i;
  309.       static int       first = TRUE;
  310.       static double    *exponent_array;
  311.  
  312.       /* precompute and store spectral weights */
  313.       if ( first ) {
  314.             /* seize required memory for exponent_array */
  315.             exponent_array =
  316.                         (double *)malloc( (octaves+1) * sizeof(double) );
  317.             frequency = 1.0;
  318.             for (i=0; i<=octaves; i++) {
  319.                   /* compute weight for each frequency */
  320.                   exponent_array[i] = pow( frequency, -H );
  321.                   frequency *= lacunarity;
  322.             }
  323.             first = FALSE;
  324.       }
  325.  
  326.       /* get first octave */
  327.       signal = Noise3( point );
  328.       /* get absolute value of signal (this creates the ridges) */
  329.       if ( signal < 0.0 ) signal = -signal;
  330.       /* invert and translate (note that "offset" should be ~= 1.0) */
  331.       signal = offset - signal;
  332.       /* square the signal, to increase "sharpness" of ridges */
  333.       signal *= signal;
  334.       /* assign initial values */
  335.       result = signal;
  336.       weight = 1.0;
  337.  
  338.       for( i=1; i<octaves; i++ ) {
  339.             /* increase the frequency */
  340.             point.x *= lacunarity;
  341.             point.y *= lacunarity;
  342.             point.z *= lacunarity;
  343.  
  344.             /* weight successive contributions by previous signal */
  345.             weight = signal * gain;
  346.             if ( weight > 1.0 ) weight = 1.0;
  347.             if ( weight < 0.0 ) weight = 0.0;
  348.             signal = Noise3( point );
  349.             if ( signal < 0.0 ) signal = -signal;
  350.             signal = offset - signal;
  351.             signal *= signal;
  352.             /* weight the contribution */
  353.             signal *= weight;
  354.             result += signal * exponent_array[i];
  355.       }
  356.  
  357.       return( result );
  358.  
  359. } /* RidgedMultifractal() */
  360.  
  361.  
  362.  
  363.