home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / atomart.tar.gz / atomart.tar / noise.c < prev    next >
C/C++ Source or Header  |  1990-06-14  |  4KB  |  211 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include "atomart.h"
  4. #include "macro.h"
  5.  
  6. /*
  7.  * This is an implementation of Ken Perlin's noise function as
  8.  * described in "Hypertexture, Computer Graphics, Vol 23, No.3,
  9.  * July 1989, pp 255-256". Most of the function names are as
  10.  * given in the paper. Also, I think that there may be an error
  11.  * in the paper as the given formular of OMEGA would always
  12.  * produce Zero if the actual point falls on a lattice point.
  13.  * (ie. GAMMA(i, j, k) . (u, v, w) = 0). Anyway, I added in 
  14.  * a psuedo random value for the noise at each lattice point
  15.  * as well as the gradient values (as decribed in his '85 paper
  16.  * and it seems to work (Maybe not so good .... but)
  17.  */
  18.  
  19. typedef    struct {
  20.     float    x;
  21.     float    y;
  22.     float    z;
  23.     float    r;
  24. } vector4;
  25.     
  26.  
  27. static    vector4    *G;
  28. static    int    *P;
  29. extern    float randtable[];
  30.  
  31. #define    ABS(x)    ((x) < 0 ? -(x) : (x))
  32.  
  33. /*
  34.  * Hashing function
  35.  */
  36. #define    phi(i)    P[ABS((i)) % NUMPTS]
  37.  
  38. #define NUMPTS    512
  39.  
  40. /*
  41.  * W
  42.  *
  43.  *    A cubic (Hermite) weighting function.
  44.  */
  45. static float    
  46. W(t)
  47.     float    t;
  48. {    
  49.     float    a = ABS(t);
  50.  
  51.     a = (a < 1.0 ?  a * a * (2.0 * a - 3.0) + 1.0 : 0.0); 
  52.     return(a);
  53. }
  54.  
  55. /*
  56.  * GAMMA
  57.  *
  58.  *    Hashes into the lattice and returns the Gradient vector
  59.  *    (and the noise value G.r) for the lattice point i, j, k.
  60.  */
  61. static vector4 *
  62. GAMMA(i, j, k)
  63.     int    i, j, k;
  64. {
  65.     register int l;
  66.     
  67.     l = j + phi(k);
  68.     l = phi(i + phi(l));
  69.  
  70.     return(&G[l]);
  71. }
  72.  
  73. /*
  74.  * OMEGA
  75.  *
  76.  *    Evaulates the spline knot at the lattice point i, j, k, 
  77.  *    interpolating between it and the actual point u, v, w.
  78.  */
  79. static float
  80. OMEGA(i, j, k, u, v, w)
  81.     int    i, j, k;
  82.     float    u, v, w;
  83. {
  84.     float    a;
  85.     vector4    *V;
  86.  
  87.     V = GAMMA(i, j, k);
  88.     a = V->r + (V->x * u + V->y * v + V->z * w);
  89.     a = a * W(u) * W(v) * W(w);
  90.  
  91.     return(a);
  92. }
  93.     
  94.  
  95. /*
  96.  * noise
  97.  *
  98.  *    Sums up the contibutions from the spline knots (lattice points)
  99.  *    Around the (hashed) value of x, y, z.
  100.  */
  101. float
  102. noise(p)
  103.     vector *p;
  104. {
  105.     float        x, y, z, sum = 0.0;
  106.     register int    fx = floor(p->x);
  107.     register int    fy = floor(p->y);
  108.     register int    fz = floor(p->z);
  109.     register int    i, j, k;
  110.  
  111.     for (i = fx; i <= fx + 1; i++) {
  112.         for (j = fy; j <= fy + 1; j++) {
  113.             for (k = fz; k <= fz + 1; k++) {
  114.                 x = p->x - (float)i;
  115.                 y = p->y - (float)j;
  116.                 z = p->z - (float)k;
  117.                 sum += OMEGA(i, j, k, x, y, z);
  118.             }
  119.         }
  120.     }
  121.  
  122.     return(sum);
  123. }
  124.  
  125. #define OFFSET1    1000.0
  126. #define OFFSET2    2000.0
  127.  
  128. /*
  129.  * Vnoise
  130.  *
  131.  *    A vector valued noise function.
  132.  *     (Again, from the '89 paper pp 259)
  133.  */
  134. void
  135. Vnoise(p, v)
  136.     vector    *p, *v;
  137. {
  138.     vector s;
  139.  
  140.     s.x = p->x - OFFSET1;
  141.     s.y = p->y - OFFSET1;
  142.     s.z = p->z - OFFSET1;
  143.  
  144.     v->x = noise(&s);
  145.  
  146.     v->y = noise(p);
  147.  
  148.     s.x = p->x + OFFSET2;
  149.     s.y = p->y + OFFSET2;
  150.     s.z = p->z + OFFSET2;
  151.  
  152.     v->z = noise(&s);
  153. }
  154.  
  155. /*
  156.  * init_noise
  157.  *
  158.  *    Initialises the psuedo random gradient table G(.x, .y. z) and a
  159.  *    psuedo random value at the lattice points (G.r). Also initialises
  160.  *    the index table P.
  161.  */
  162. init_noise()
  163. {
  164.     vector4    v;
  165.     int    i, n = 0, bonk;
  166.     float    a;
  167.  
  168.     G = (vector4 *)smalloc(NUMPTS * sizeof(vector4));
  169.     P = (int *)smalloc(NUMPTS * sizeof(int));
  170.  
  171.     i = 0;
  172.     while (n < NUMPTS) {
  173.         v.x = 2.0 * randtable[i % NUMPTS] - 1.0;
  174.         v.y = 2.0 * randtable[i++ % NUMPTS] - 1.0;
  175.         v.z = 2.0 * randtable[i++  % NUMPTS] - 1.0;
  176.         v.r = 2.0 * randtable[i++  % NUMPTS] - 1.0;
  177.  
  178.         if (a = dprod(v, v) <= 1.0) {
  179.             /*
  180.              * Normalise (the x, y, z compenents of) v...
  181.              */
  182.             a = sqrt((double)a);
  183.             if (a > 0.0) {
  184.                 v.x /= a;
  185.                 v.y /= a;
  186.                 v.z /= a;
  187.             }
  188.             G[n].x = v.x;
  189.             G[n].y = v.y;
  190.             G[n].z = v.z;
  191.             G[n].r = v.r;
  192.             n++;
  193.         }
  194.     }
  195.  
  196.  
  197.     /*
  198.      * Set a random permutation of the first NUMPTS integers
  199.      */
  200.     for (n = 0; n < NUMPTS; n++)
  201.         P[n] = n;
  202.  
  203.     for (n = 0; n < NUMPTS; n++) {
  204.         i = (int)(randtable[n] * (NUMPTS - 1));
  205.         bonk = P[n];
  206.         P[n] = P[i];
  207.         P[i] = bonk;
  208.     }
  209. }
  210.  
  211.