home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 2000 April & May / AMIGA_2000_04.iso / amiga-magazin / cybergl-workshop / fractal.c < prev    next >
C/C++ Source or Header  |  1997-04-28  |  24KB  |  602 lines

  1. /*
  2. **    $VER: fractal.c 1.0 (20.04.1997)
  3. **
  4. **    This is an example program for CyberGL
  5. **
  6. **      Written by Frank Gerberding
  7. **
  8. **    Copyright © 1996-1997 by phase5 digital products
  9. **      All Rights reserved.
  10. **
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <clib/exec_protos.h>
  17. #include <dos/dos.h>
  18. #include <dos/dosasl.h>
  19. #include <clib/dos_protos.h>
  20. #include <string.h>
  21. #define CYBERGLNAME             "cybergl.library"
  22. #define CYBERGLVERSION          39L
  23. #define SHARED                  /* we use the cybergl shared library */
  24. #define GL_APICOMPATIBLE        /* we use stubs from cybergl.lib */
  25. #include "cybergl.h"
  26. #include "cybergl_protos.h"
  27. #include "cybergl_display.h"
  28. #ifdef SHARED
  29. LONG __oslibversion   = 39L;
  30. LONG __CGLlibversion = CYBERGLVERSION;
  31. #include "cybergl_pragmas.h"
  32. extern  struct  Library *CyberGLBase;
  33. #endif
  34.  
  35.  
  36. #define MAX_STEPS    8                  /* maximum number of genesis steps */
  37.                                         /* 2^(2*MAX_STEPS)*6*sizeof(float) mem needed */
  38. #define GRID_SIZE    (1 << MAX_STEPS)   /* fractal grid size */
  39.  
  40. #define WIDTH       0                   /* width parameter array index */
  41. #define HEIGHT      1                   /* height parameter array index */
  42. #define STEPS       2                   /* steps parameter array index */
  43. #define MAX_HEIGHT  3                   /* max height parameter array index */
  44. #define ROCK_REPEAT 4                   /* rock repeat parameter array index */
  45. #define WAVE_REPEAT 5                   /* wave repeat parameter array index */
  46. #define SIZE        6                   /* fractal size parameter array index */
  47. #define SEA_LEVEL   7                   /* sea level parameter array index */
  48. #define SEED        8                   /* random seed parameter array index */
  49. #define FOG         9                   /* fog enable parameter array index */
  50. #define TEXTURE    10                   /* texture enable parameter array index */
  51.  
  52.  
  53. /* this sets the default values for all parameters: */
  54. /* width:       initial window width */
  55. /* height:      initial window height */
  56. /* steps:       genesis step number (1..MAX_STEPS) */
  57. /* maxHeight:   maximum fractal mountain height */
  58. /* rockRepeat:  rock texture repeat count */
  59. /* waveRepeat:  wave texture repeat count */
  60. /* size:        fractal mountain x/z size */
  61. /* seaLevel:    height of sea level */
  62. /* seed:        random seed */
  63. /* fog:         fog enable/disable */
  64. /* texture:     texture enable/disable */
  65. /*              width  height steps maxHeight rockRepeat waveRepeat size seaLevel seed fog texture */
  66. int params [] = {320,   240,    6,     5,         3,         3,      20,    -1,   100,  0,    0};
  67.  
  68.  
  69.  
  70. typedef struct {
  71.   GLfloat x;   /* point  x coordinate */
  72.   GLfloat y;   /* point  y coordinate */
  73.   GLfloat z;   /* point  z coordinate */
  74.   GLfloat nx;  /* normal x coordinate */
  75.   GLfloat ny;  /* normal y coordinate */
  76.   GLfloat nz;  /* normal z coordinate */
  77. } point;       /* grid point structure */
  78.  
  79.  
  80.  
  81. far point grid [GRID_SIZE + 1][GRID_SIZE + 1];   /* global fractal grid */
  82.  
  83.  
  84.  
  85.  
  86. /************************************************************************/
  87. /* texture minification routine. This function computes a texture of    */
  88. /* half the original size using a simple box filter and returns a       */
  89. /* pointer to a new allocated texture.                                  */
  90. /* parameters:                                                          */
  91. /* texture: pointer to original texture                                 */
  92. /* size:    size of original texture                                    */
  93. /* result:  new minified texture (or NULL for failure)                  */
  94. /************************************************************************/
  95. GLubyte *minifyTexture (GLubyte *texture, GLint size)
  96. {
  97.   GLubyte *newTexture = NULL;   /* pointer to minified texture */
  98.   GLint    newSize;             /* minified texture size */
  99.   GLint    x, y;                /* x and y texture coordinates */
  100.  
  101.   newSize = size / 2;
  102.   if (newTexture = malloc (newSize * newSize * 3))
  103.   {
  104.     for (x = 0; x < newSize; x++)      /* for all rows */
  105.     {
  106.       for (y = 0; y < newSize; y++)    /* for all columns */
  107.       {
  108.         newTexture [(x + y * newSize) * 3 + 0] =
  109.           (texture [(x + x +     (y + y)     * size) * 3 + 0] +
  110.            texture [(x + x + 1 + (y + y)     * size) * 3 + 0] +
  111.            texture [(x + x +     (y + y + 1) * size) * 3 + 0] +
  112.            texture [(x + x + 1 + (y + y + 1) * size) * 3 + 0]) / 4; /* red pixel value */
  113.         newTexture [(x + y * newSize) * 3 + 1] =
  114.           (texture [(x + x +     (y + y)     * size) * 3 + 1] +
  115.            texture [(x + x + 1 + (y + y)     * size) * 3 + 1] +
  116.            texture [(x + x +     (y + y + 1) * size) * 3 + 1] +
  117.            texture [(x + x + 1 + (y + y + 1) * size) * 3 + 1]) / 4; /* green pixel value */
  118.         newTexture [(x + y * newSize) * 3 + 2] =
  119.           (texture [(x + x +     (y + y)     * size) * 3 + 2] +
  120.            texture [(x + x + 1 + (y + y)     * size) * 3 + 2] +
  121.            texture [(x + x +     (y + y + 1) * size) * 3 + 2] +
  122.            texture [(x + x + 1 + (y + y + 1) * size) * 3 + 2]) / 4; /* blue pixel value */
  123.       }
  124.     }
  125.   }
  126.   return newTexture;   /* return new texture */
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133. /************************************************************************/
  134. /* load a simple texture map from disk. The texture has to be organized */
  135. /* as RGBRGBRGBRGB... and has to be of square size. The size has to be  */
  136. /* a power of two. All mip mapping texture sizes are computed           */
  137. /* automatically.                                                       */
  138. /* parameters:                                                          */
  139. /* name: full file name                                                 */
  140. /* size: texture width/height in pixels, so file size is: size*size*3   */
  141. /************************************************************************/
  142. void loadTexMipMap (char *name, GLint size)
  143. {
  144.   FILE    *file;                 /* file pointer */
  145.   GLubyte *texture    = NULL;    /* texture map pointer */
  146.   GLubyte *newTexture = NULL;    /* new texture (for mip map sizes */
  147.   int      level = 0;            /* actual mip mapping texture level */
  148.  
  149.   if (texture = malloc (size * size * 3))     /* alloc texture map */
  150.   {
  151.     if (file = fopen (name, "r"))             /* open texture file */
  152.     {
  153.       fread (texture, size * size * 3, 1, file);
  154.       glTexImage2D (GL_TEXTURE_2D, level++, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
  155.       fclose (file);
  156.       while (size > 1)                        /* mip map sizes remaining ? */
  157.       {
  158.         if (newTexture = minifyTexture (texture, size))   /* compute next mip map */
  159.         {
  160.           free (texture);                                 /* free old texture */
  161.           texture = newTexture;
  162.         }
  163.         glTexImage2D (GL_TEXTURE_2D, level++, 3, size / 2, size / 2, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
  164.         size /= 2;                                        /* next size is half original */
  165.       }
  166.     }
  167.     free (texture);
  168.   }
  169. }
  170.  
  171.  
  172.  
  173.  
  174.  
  175. /************************************************************************/
  176. /* compute a random height within -range..range.                        */
  177. /* parameters:                                                          */
  178. /* range:  range to compute a random value within                       */
  179. /* result: random height within -range..range                           */
  180. /************************************************************************/
  181. GLfloat randomHeight (GLfloat range)
  182. {
  183.   return (GLfloat) (range * ((GLfloat) (2.0 * rand () / RAND_MAX) - 1.0));
  184. }
  185.  
  186.  
  187.  
  188.  
  189.  
  190. /************************************************************************/
  191. /* normalize a single vector.                                           */
  192. /* parameters:                                                          */
  193. /* point: pointer to point structure to normalize                       */
  194. /************************************************************************/
  195. void normalize (point *p)
  196. {
  197.   GLfloat length = p->nx * p->nx + p->ny * p->ny + p->nz * p->nz;
  198.  
  199.   if (length != 0.0)
  200.   {
  201.     length = 1.0 / sqrt (length);
  202.     p->nx *= length;
  203.     p->ny *= length;
  204.     p->nz *= length;
  205.   }
  206. }
  207.  
  208.  
  209.  
  210.  
  211.  
  212. /************************************************************************/
  213. /* calc vertex normals for all fractal mountain grid positions. This is */
  214. /* done by computing all fractal patch normals and then averaging all   */
  215. /* adjacent patch normals.                                              */
  216. /* parameters:                                                          */
  217. /* steps: number of fractal genesis steps                               */
  218. /* size:  x/z size of fractal mountain                                  */
  219. /************************************************************************/
  220. void calcNormals (int steps, GLfloat size)
  221. {
  222.   int     gridStep = 1 << (MAX_STEPS - steps);  /* grid point index distance */
  223.   int     x, z;                                 /* x/z index */
  224.   GLfloat diff = size / (1 << steps);           /* x/z grid distance */
  225.   GLfloat nx, ny, nz;                           /* actual normal coordinates */
  226.   GLfloat y1, y2;                               /* actual y coordinates */
  227.  
  228.   for (x = 0; x < GRID_SIZE; x += gridStep)     /* for all rows */
  229.   {
  230.     for (z = 0; z < GRID_SIZE; z += gridStep)   /* for all columns */
  231.     {
  232.       grid [x][z].nx = 0.0;   /* init normal x coordinate */
  233.       grid [x][z].ny = 0.0;   /* init normal y coordinate */
  234.       grid [x][z].nz = 0.0;   /* init normal z coordinate */
  235.     }
  236.   }
  237.   for (x = 0; x < GRID_SIZE; x += gridStep)    /* for all rows */
  238.   {
  239.     for (z = 0; z < GRID_SIZE; z += gridStep)  /* for all columns */
  240.     {
  241.       y1 = grid [x + gridStep][z].y - grid[x][z].y;   /* edge vector y1 */
  242.       y2 = grid [x][z + gridStep].y - grid[x][z].y;   /* edge vector y2 */
  243.  
  244.       nx = y2   * 0.0  - diff * y1;                   /* normal computation */
  245.       ny = diff * diff - 0.0  * 0.0;                  /* using edge vector */
  246.       nz = 0.0  * y1   - y2   * diff;                 /* cross product */
  247.  
  248.       grid [x           ][z           ].nx += nx;     /* add actual normal */
  249.       grid [x           ][z           ].ny += ny;
  250.       grid [x           ][z           ].nz += nz;
  251.  
  252.       grid [x           ][z + gridStep].nx += nx;     /* add actual normal */
  253.       grid [x           ][z + gridStep].ny += ny;
  254.       grid [x           ][z + gridStep].nz += nz;
  255.  
  256.       grid [x + gridStep][z           ].nx += nx;     /* add actual normal */
  257.       grid [x + gridStep][z           ].ny += ny;
  258.       grid [x + gridStep][z           ].nz += nz;
  259.  
  260.       grid [x + gridStep][z + gridStep].nx += nx;     /* add actual normal */
  261.       grid [x + gridStep][z + gridStep].ny += ny;
  262.       grid [x + gridStep][z + gridStep].nz += nz;
  263.     }
  264.   }
  265.   for (x = 0; x <= GRID_SIZE; x += gridStep)    /* for all rows */
  266.   {
  267.     for (z = 0; z <= GRID_SIZE; z += gridStep)  /* for all columns */
  268.     {
  269.       normalize (&(grid [x][z]));               /* normalize all vectors */
  270.     }
  271.   }
  272. }
  273.  
  274.  
  275.  
  276.  
  277.  
  278. /************************************************************************/
  279. /* fractal mountain genesis. This is done by the popular fractal        */
  280. /* mountain generation algorithm.                                       */
  281. /* parameters:                                                          */
  282. /* seed:      random seed                                               */
  283. /* steps:     number of generation steps (1..MAX_STEPS)                 */
  284. /* maxHeight: maximum mountain height                                   */
  285. /* size:      mountain x/z size                                         */
  286. /************************************************************************/
  287. void genesis (int seed, int steps, GLfloat maxHeight, GLfloat size)
  288. {
  289.   int x, z;       /* x/z index */
  290.   int gridStep;   /* actual grid index distance */
  291.   int step;       /* actual generation step */
  292.  
  293.   srand (seed);
  294.   grid [        0][        0].y = randomHeight (maxHeight);  /* corner height */
  295.   grid [GRID_SIZE][        0].y = randomHeight (maxHeight);  /* corner height */
  296.   grid [        0][GRID_SIZE].y = randomHeight (maxHeight);  /* corner height */
  297.   grid [GRID_SIZE][GRID_SIZE].y = randomHeight (maxHeight);  /* corner height */
  298.  
  299.   gridStep = GRID_SIZE / 2;          /* init grid step */
  300.  
  301.   for (step = 1; step <= steps; step++)   /* for all generation steps */
  302.   {
  303.     maxHeight /= 2.0;                     /* new max height */
  304.  
  305.     for (x = gridStep / 2; x < GRID_SIZE; x += gridStep)   /* for all rows */
  306.     {
  307.       int xl = x - gridStep / 2;                    /* x neighbour index left */
  308.       int xr = x + gridStep / 2;                    /* x neighbour index right */
  309.  
  310.       for (z = gridStep / 2; z < GRID_SIZE; z += gridStep)  /* for all columns */
  311.       {
  312.         int zl = z - gridStep / 2;                  /* z neighbour index left */
  313.         int zr = z + gridStep / 2;                  /* z neighbour index right */
  314.  
  315.         grid [x][z].y = (grid [xl][zl].y +
  316.                          grid [xl][zr].y +
  317.                          grid [xr][zl].y +
  318.                          grid [xr][zr].y) / 4.0 + randomHeight (maxHeight);
  319.         grid [xl][z].y = (grid [xl][zl].y +
  320.                           grid [xl][zr].y) / 2.0 + randomHeight (maxHeight);
  321.         grid [x][zl].y = (grid [xl][zl].y +
  322.                           grid [xr][zl].y) / 2.0 + randomHeight (maxHeight);
  323.       }
  324.       grid [x][GRID_SIZE].y = (grid [xl][GRID_SIZE].y +
  325.                                grid [xr][GRID_SIZE].y) / 2.0 + randomHeight (maxHeight);
  326.  
  327.     }
  328.     for (z = gridStep / 2; z < GRID_SIZE; z += gridStep)    /* right border */
  329.     {
  330.       grid [GRID_SIZE][z].y = (grid [GRID_SIZE][z - gridStep / 2].y +
  331.                                grid [GRID_SIZE][z + gridStep / 2].y) / 2.0 + randomHeight (maxHeight);
  332.     }
  333.     gridStep /= 2;             /* next grid index distance */
  334.   }
  335.   {
  336.     GLfloat offset = - size / 2.0;           /* offset for x/z coordinate computation */
  337.     GLfloat factor = size / GRID_SIZE;       /* factor for x/z coordinate computation */
  338.  
  339.     gridStep = 1 << (MAX_STEPS - steps);     /* grid index step size */
  340.  
  341.     for (x = 0; x <= GRID_SIZE; x += gridStep)   /* for all rows */
  342.     {
  343.       for (z = 0; z <= GRID_SIZE; z += gridStep) /* for all columns */
  344.       {
  345.         grid [x][z].x = factor * x + offset;     /* x coordinate computation */
  346.         grid [x][z].z = factor * z + offset;     /* z coordinate computation */
  347.       }
  348.     }
  349.   }
  350.   calcNormals (steps, size);                     /* calc all vertex normals */
  351. }
  352.  
  353.  
  354.  
  355.  
  356.  
  357. /************************************************************************/
  358. /* draw the fractal mountain. This is done by drawing several adjacent  */
  359. /* triangle strips.                                                     */
  360. /* parameters:                                                          */
  361. /* step:      number of generation steps performed before               */
  362. /* texRepeat: rock texture repeat count                                 */
  363. /************************************************************************/
  364. void drawFractal (int step, GLfloat texRepeat)
  365. {
  366.   GLint    x, z;                            /* x/z index */
  367.   GLint    gridStep;                        /* grid index distance */
  368.   GLfloat  rock [] = {1.0, 0.8, 0.6, 1.0};  /* rock color */
  369.   GLdouble texScale;                        /* texture coordinate factor */
  370.  
  371.   gridStep = 1 << (MAX_STEPS - step);
  372.   texScale = texRepeat / GRID_SIZE;
  373.  
  374.   glMaterialfv  (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rock);
  375.   
  376.   if (params [TEXTURE])
  377.   {
  378.     loadTexMipMap ("rock", 256);
  379.   }
  380.   for (z = 0; z < GRID_SIZE; z += gridStep)   /* for all rows */
  381.   {
  382.     glBegin (GL_TRIANGLE_STRIP);                   /* draw a triangle strip */
  383.       for (x = 0; x <= GRID_SIZE; x += gridStep)   /* for all columns */
  384.       {
  385.         glNormal3f   (grid [x][z].nx, grid [x][z].ny, grid [x][z].nz);
  386.         glTexCoord2d (x * texScale, z * texScale);
  387.         glVertex3f   (grid [x][z].x,  grid [x][z].y,  grid [x][z].z);
  388.  
  389.         glNormal3f   (grid [x][z + gridStep].nx, grid [x][z + gridStep].ny, grid [x][z + gridStep].nz);
  390.         glTexCoord2d (x * texScale, (z + gridStep) * texScale);
  391.         glVertex3f   (grid [x][z + gridStep].x,  grid [x][z + gridStep].y,  grid [x][z + gridStep].z);
  392.       }
  393.     glEnd ();
  394.   }
  395. }
  396.  
  397.  
  398.  
  399.  
  400.  
  401. /************************************************************************/
  402. /* draw thesea level as one big polygon.                                */
  403. /* parameters:                                                          */
  404. /* level:     sea level                                                 */
  405. /* size:      size of fractal mountain in x/z direction                 */
  406. /* texRepeat: sea texture repeat count                                  */
  407. /************************************************************************/
  408. void drawSea (GLfloat level, GLfloat size, GLfloat texRepeat)
  409. {
  410.   GLfloat  water [] = {0.2, 0.5, 1.0, 1.0};   /* water colr */
  411.  
  412.   glMaterialfv  (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, water);
  413.  
  414.   if (params [TEXTURE])
  415.   {
  416.     loadTexMipMap ("waves", 256);
  417.   }
  418.   glBegin (GL_POLYGON);              /* draw one big polygon */
  419.     glNormal3d   (0.0, 1.0, 0.0);
  420.  
  421.     glTexCoord2f (0.0F, 0.0F);
  422.     glVertex3d   (-size / 2, level,  size / 2);
  423.  
  424.     glTexCoord2f (texRepeat, 0.0F);
  425.     glVertex3d   ( size / 2, level,  size / 2);
  426.  
  427.     glTexCoord2f (texRepeat, texRepeat);
  428.     glVertex3d   ( size / 2, level, -size / 2);
  429.  
  430.     glTexCoord2f (0.0F, texRepeat);
  431.     glVertex3d   (-size / 2, level, -size / 2);
  432.   glEnd ();
  433. }
  434.  
  435.  
  436.  
  437.  
  438.  
  439. /************************************************************************/
  440. /* handle all window events for the given window.                       */
  441. /* parameters:                                                          */
  442. /* win: pointer to CyberGL window                                       */
  443. /************************************************************************/
  444. void handle_window_events (void *win)
  445. {
  446.   struct IntuiMessage *msg;        /* intuition message */
  447.   int                  done = 0;   /* all done ? */
  448.   struct        Window *window;    /* Intuition window pointer */
  449.  
  450.   window = getWindow (win);        /* get Intuition window */
  451.  
  452.   while (!done)                    /* whilenot done */
  453.   {
  454.     Wait (1L << window->UserPort->mp_SigBit);
  455.     while ((!done) && (msg = (struct IntuiMessage *) GetMsg (window->UserPort)))
  456.     {
  457.       switch (msg->Class)
  458.       {
  459.         case IDCMP_CLOSEWINDOW:
  460.           done = 1;                 /* all done */
  461.           break;
  462.         case IDCMP_NEWSIZE:
  463.           resizeGLWindow   (win, window->GZZWidth, window->GZZHeight);
  464.           glClear          (GL_COLOR_BUFFER_BIT);
  465.           drawFractal      (params [STEPS], (GLfloat) params [ROCK_REPEAT]);
  466.           drawSea          ((GLfloat) params [SEA_LEVEL], (GLfloat) params [SIZE],
  467.                             (GLfloat) params [WAVE_REPEAT]);
  468.           break;
  469.       }
  470.       ReplyMsg ((struct Message *) msg);
  471.     }
  472.   }
  473. }
  474.  
  475.  
  476.  
  477.  
  478. /************************************************************************/
  479. /* set up a directional light source with direction xyz and color rgb.  */
  480. /* parameters:                                                          */
  481. /* x:     x coordinate of light direction                               */
  482. /* y:     y coordinate of light direction                               */
  483. /* z:     z coordinate of light direction                               */
  484. /* r:     red color component of light color                            */
  485. /* g:     green color component of light color                          */
  486. /* b:     blue color component of light color                           */
  487. /* light: symbolic light name (GL_LIGHT0..GL_LIGHT7)                    */
  488. /************************************************************************/
  489. void dirLight (GLdouble x, GLdouble y, GLdouble z,
  490.                GLdouble r, GLdouble g, GLdouble b, GLenum light)
  491. {
  492.   GLfloat pos   [4];    /* virtual light position */
  493.   GLfloat color [4];    /* light color */
  494.  
  495.   pos   [0] = (GLfloat) x;
  496.   pos   [1] = (GLfloat) y;
  497.   pos   [2] = (GLfloat) z;
  498.   pos   [3] = (GLfloat) 0.0;
  499.   color [0] = (GLfloat) r;
  500.   color [1] = (GLfloat) g;
  501.   color [2] = (GLfloat) b;
  502.   color [3] = (GLfloat) 0.0;
  503.  
  504.   glEnable  (GL_LIGHTING);                /* enable lighting */
  505.   glEnable  (light);                      /* enable light */
  506.   glLightfv (light, GL_POSITION, pos);    /* set position */
  507.   glLightfv (light, GL_DIFFUSE,  color);  /* set diffuse color */
  508.   glLightfv (light, GL_SPECULAR, color);  /* set specular color */
  509. }
  510.  
  511.  
  512.  
  513.  
  514.  
  515. void main (void)
  516. {
  517.   void              *window;                          /* CyberGL window */
  518.   GLfloat            fog [] = {1.0, 1.0, 1.0, 1.0};   /* fog color */
  519.   struct RDArgs     *args;
  520.   char               template [] = "W=WIDTH/K/N,H=HEIGHT/K/N,S=STEPS/K/N,M=MAXHEIGHT/K/N,ROCK/K/N,WAVE/K/N,SIZE/K/N,L=SEALEVEL/K/N,R=RANDOM/K/N,F=FOG/K/S,T=TEXTURE/K/S";
  521.   long              *arglist [11] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  522.   int                count;
  523.  
  524.   if (args = ReadArgs (template, (long *) arglist, NULL))
  525.   {
  526.     for (count = 0; count < 9; count++)
  527.     {
  528.       if (arglist [count])
  529.       {
  530.         params [count] = *(arglist [count]);
  531.       }
  532.     }
  533.     params [FOG]     = (int) arglist [FOG];
  534.     params [TEXTURE] = (int) arglist [TEXTURE];
  535.     FreeArgs (args);
  536.   }
  537.   window  = openGLWindowTags (params [WIDTH], params [HEIGHT],
  538.     GLWA_Title, "Fractal",
  539.     GLWA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
  540.     GLWA_CloseGadget, TRUE,
  541.     GLWA_DepthGadget, TRUE,
  542.     GLWA_DragBar,     TRUE,
  543.     GLWA_Activate,    TRUE,
  544.     GLWA_RGBAMode,    GL_TRUE,
  545.     GLWA_SizeGadget,  TRUE,
  546.     GLWA_MinWidth,     320,
  547.     GLWA_MinHeight,    240,
  548.     GLWA_MaxWidth,    1280,
  549.     GLWA_MaxHeight,   1024,
  550.   TAG_DONE);
  551.  
  552.   if (window)
  553.   {
  554.     glEnable         (GL_DITHER);              /* enable dithering */
  555.     glEnable         (GL_CULL_FACE);           /* enable back face culling */
  556.     glShadeModel     (GL_SMOOTH);              /* enable gouraud shading */
  557.     glEnable         (GL_DEPTH_TEST);          /* enable depth testing */
  558.     glLightModeli    (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
  559.     glMatrixMode     (GL_PROJECTION);
  560.     glPerspective    (45.0, 1.333, 0.5, (GLdouble) params [SIZE] + 2.5);    /* projection */
  561.     glMatrixMode     (GL_MODELVIEW);
  562.     glLookAt         (0.0, 10.0, 10.0,   0.0, 0.0, 0.0,   0.0, 1.0, 0.0);   /* camera position */
  563.     glTexParameteri  (GL_TEXTURE_2D,  GL_TEXTURE_MIN_FILTER, GL_LINEAR);    /* minification filter */
  564.     glTexParameteri  (GL_TEXTURE_2D,  GL_TEXTURE_MAG_FILTER, GL_LINEAR);    /* magnification filter */
  565.     glTexParameteri  (GL_TEXTURE_2D,  GL_TEXTURE_WRAP_S, GL_REPEAT);        /* texture repeating */
  566.     glTexParameteri  (GL_TEXTURE_2D,  GL_TEXTURE_WRAP_T, GL_REPEAT);        /* texture repeating */
  567.     glTexEnvi        (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);    /* modulate color */
  568.     glFogi           (GL_FOG_MODE,    GL_LINEAR);                           /* linear fog mode */
  569.     glFogf           (GL_FOG_START,   (GLfloat)  0.0);                      /* fog minimum distance */
  570.     glFogf           (GL_FOG_END,     (GLfloat) 20.0);                      /* fog maximum distance */
  571.     glFogfv          (GL_FOG_COLOR,   fog);                                 /* fog color */
  572.  
  573.     if (params [FOG])
  574.     {
  575.       glClearColor (fog [0], fog [1], fog [2], fog [3]);
  576.       glEnable     (GL_FOG);     /* enable fog */
  577.     }
  578.     else
  579.     {
  580.       glDisable (GL_FOG);        /* enable fog */
  581.     }
  582.     if (params [TEXTURE])
  583.     {
  584.       glEnable  (GL_TEXTURE_2D); /* enable texturing */
  585.     }
  586.     else
  587.     {
  588.       glDisable (GL_TEXTURE_2D); /* disable texturing */
  589.     }
  590.     glClear          (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  591.     dirLight         (1.0, 1.0, 1.0,   1.0, 1.0, 1.0,  GL_LIGHT0);          /* setup light */
  592.  
  593.     genesis          (params [SEED], params [STEPS], (GLfloat) params [MAX_HEIGHT], (GLfloat) params [SIZE]);
  594.     drawFractal      (params [STEPS], (GLfloat) params [ROCK_REPEAT]);
  595.     drawSea          ((GLfloat) params [SEA_LEVEL], (GLfloat) params [SIZE], (GLfloat) params [WAVE_REPEAT]);
  596.  
  597.     handle_window_events (window);
  598.  
  599.     closeGLWindow (window);
  600.   }
  601. }
  602.