home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / p / ply15dat.zip / ISLGEN.C < prev    next >
C/C++ Source or Header  |  1992-03-29  |  5KB  |  198 lines

  1. /* Test file to create Targa height fields for POVRay -- Alexander Enzmann */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <float.h>
  6. #include <string.h>
  7.  
  8. /* Noise generator variables */
  9. #define LARGE 100000.0
  10. #define HASH_SIZE 78737
  11. #define spline(x) ((3 - 2 * (x)) * (x) * (x))
  12. static int mult_table_size = 5;
  13. static unsigned long mult_table[] = { 99137, 113713, 55237, 994472, 441973 };
  14.  
  15. static float **height_buffer;
  16. static FILE *TargaFile;
  17. static int TargaBits = 24;
  18.  
  19. static void
  20. TargaOpen(char *filename, int x, int y)
  21. {
  22.    unsigned char tgaheader[18];
  23.    if ((TargaFile = fopen(filename, "wb")) == NULL) {
  24.       printf("Failed to open Targa file: %s\n", filename);
  25.       exit(1);
  26.       }
  27.    memset(tgaheader, 0, 18);
  28.    tgaheader[2] = 2;
  29.    tgaheader[12] = (unsigned char)(x & 0xFF);
  30.    tgaheader[13] = (unsigned char)((x >> 8) & 0xFF);
  31.    tgaheader[14] = (unsigned char)(y & 0xFF);
  32.    tgaheader[15] = (unsigned char)((y >> 8) & 0xFF);
  33.    tgaheader[16] = TargaBits;
  34.    tgaheader[17] = 0x20;
  35.    fwrite(tgaheader, 18, 1, TargaFile);
  36. }
  37.  
  38. static void
  39. TargaWrite(unsigned char r, unsigned char g, unsigned char b)
  40. {
  41.    if (TargaBits == 16) {
  42.       fputc(g, TargaFile);
  43.       fputc(r, TargaFile);
  44.       }
  45.    else if (TargaBits == 24) {
  46.       fputc(b, TargaFile);
  47.       fputc(g, TargaFile);
  48.       fputc(r, TargaFile);
  49.       }
  50.    else {
  51.       fprintf(stderr, "Wrong # of bits/pixel for Targa file: %d\n",
  52.               TargaBits);
  53.       exit(1);
  54.       }
  55. }
  56.  
  57. static void
  58. TargaClose()
  59. {
  60.    fclose(TargaFile);
  61. }
  62.  
  63. static float
  64. hash3d(unsigned long x, unsigned long y, unsigned long z)
  65. {
  66.    int i;
  67.    unsigned long K, Kt, P;
  68.    float result;
  69.    K = ((x & 0x03ffL) << 20) |
  70.        ((y & 0x03ffL) << 10) |
  71.         (z & 0x03ffL);
  72.    Kt = 0;
  73.    for (i=0;i<mult_table_size;i++)
  74.       Kt = ((Kt + K) * mult_table[i]) % HASH_SIZE;
  75.    result = (float)Kt / (float)(HASH_SIZE - 1);
  76.    return result;
  77. }
  78.  
  79. static float
  80. flt_noise(float x, float y, float z)
  81. {
  82.    unsigned long ix, iy, iz, jx, jy, jz;
  83.    float sx0, sy0, sz0, sx1, sy1, sz1;
  84.    float result;
  85.  
  86.    x += LARGE;   y += LARGE;  z += LARGE;
  87.    ix = x;      iy = y;      iz = z;
  88.    jx = ix + 1; jy = iy + 1; jz = iz + 1;
  89.    
  90.    /* Compute cubic interpolated influences of surrounding
  91.       lattice points */
  92.    sx0 = spline(x - ix);
  93.    sy0 = spline(y - iy);
  94.    sz0 = spline(z - iz);
  95.    sx1 = 1.0 - sx0; sy1 = 1.0 - sy0; sz1 = 1.0 - sz0;
  96.  
  97.    result  = hash3d(ix, iy, iz) * sx1 * sy1 * sz1;
  98.    result += hash3d(ix, iy, jz) * sx1 * sy1 * sz0;
  99.    result += hash3d(ix, jy, iz) * sx1 * sy0 * sz1;
  100.    result += hash3d(ix, jy, jz) * sx1 * sy0 * sz0;
  101.    result += hash3d(jx, iy, iz) * sx0 * sy1 * sz1;
  102.    result += hash3d(jx, iy, jz) * sx0 * sy1 * sz0;
  103.    result += hash3d(jx, jy, iz) * sx0 * sy0 * sz1;
  104.    result += hash3d(jx, jy, jz) * sx0 * sy0 * sz0;
  105.    return result;
  106. }
  107.  
  108. static float
  109. noise3d(float x, float y, float z,
  110.         float recursion_scale, int count)
  111. {
  112.    float x1, y1, z1;
  113.    float result = 0.0;
  114.    float scale  = 1.0;
  115.    float iscale = 1.0 / recursion_scale;
  116.    float magnitude = 0.0;
  117.    int i;
  118.  
  119.    x1 = x;
  120.    y1 = y;
  121.    z1 = z;
  122.    for (i=0;i<count;i++) {
  123.      result += scale * flt_noise(x1, y1, z1);
  124.      magnitude += scale;
  125.      if (i < count-1) {
  126.         x1 *= 2.0;
  127.         y1 *= 2.0;
  128.         z1 *= 2.0;
  129.         scale *= recursion_scale;
  130.         }
  131.      }
  132.    result /= magnitude;
  133.    return result;
  134. }
  135.  
  136. static write_height(float y)
  137. {
  138.    unsigned char r, g, b;
  139.    if (y < -127.0) y = -127.0;
  140.    if (y > 127.0) y = 127.0;
  141.    y += 128.0;
  142.    r = (unsigned char)y;
  143.    y -= (float)r;
  144.    g = (unsigned char)(256.0 * y);
  145.    b = 0;
  146.    TargaWrite(r, g, b);
  147. }
  148.  
  149. static void
  150. make_noise_field(int width, int height,
  151.                  float xlow, float xhigh,
  152.                  float zlow, float zhigh,
  153.                  float seed,
  154.                  float recursion_scale, int octaves)
  155. {
  156.    float x, xdelta;
  157.    float y;
  158.    float z, zdelta;
  159.    int i, j;
  160.  
  161.    xdelta = (xhigh - xlow) / ((float)(width-1));
  162.    zdelta = (zhigh - zlow) / ((float)(height-1));
  163.  
  164.    /* Loop through all possible values of z and x, generating
  165.       altitudes as we go. */
  166.    for (i=0,z=zlow;i<height;i++,z+=zdelta)
  167.       for (j=0,x=xlow;j<width;j++,x+=xdelta) {
  168.          /* Calculate the altitude */
  169.          y = noise3d(x, seed, z, recursion_scale, octaves);
  170.          
  171.          /* Scale it to fit into -128 -> 128 */
  172.          y = 256.0 * (y - 0.5);
  173.          
  174.          /* Write out the altitude */
  175.          write_height(y);
  176.          }
  177. }
  178.  
  179. void
  180. main(argc, argv)
  181.  int argc;
  182.  char **argv;
  183. {
  184.    int h = 256;       /* height of resulting height field */
  185.    int w = 256;       /* width of resulting height field */
  186.    int oct = 3;       /* # of octaves of noise to use */
  187.    float x0 = -8.0;   /* Low x to interpolate noise over */
  188.    float x1 =  8.0;   /* High x to interpolate noise over */
  189.    float z0 = -8.0;   /* Low z to interpolate noise over */
  190.    float z1 =  8.0;   /* High z to interpolate noise over */
  191.    float seed = 1.11; /* Seed to change resulting pattern */
  192.    float sc =  0.25;  /* Contribution of each octave of noise */
  193.  
  194.    TargaOpen("fracthf.tga", h, w);
  195.    make_noise_field(h, w, x0, x1, z0, z1, seed, sc, oct);
  196.    TargaClose();
  197. }
  198.