home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / contrib / fractals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  17.9 KB  |  710 lines

  1. /*
  2.  * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm
  3.  *
  4.  * Usage: fractals
  5.  *
  6.  * Homework 6, Part 2: fractal mountains and fractal trees 
  7.  * (Pretty Late)
  8.  *
  9.  * Draws fractal mountains and trees -- and an island of mountains in water 
  10.  * (I tried having trees on the island but it didn't work too well.)
  11.  *
  12.  * Two viewer modes: polar and flying (both restrained to y>0 for up vector).
  13.  * Keyboard 0->9 and +/- control speed when flying.
  14.  *
  15.  * Only keyboard commands are 0-9 and +/- for speed in flying mode.
  16.  *
  17.  * Fog would make the island look much better, but I couldn't get it to work
  18.  * correctly.  Would line up on -z axis not from eye.
  19.  *
  20.  * Philip Winston - 3/4/95
  21.  * pwinston@hmc.edu
  22.  * http://www.cs.hmc.edu/people/pwinston
  23.  *
  24.  */
  25.  
  26. #include <GL/glut.h>
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <math.h>
  31. #include <limits.h>           /* ULONG_MAX is defined here */
  32. #include <float.h>            /* FLT_MAX is atleast defined here */
  33.  
  34. #include <time.h>  /* for random seed */
  35.  
  36. #include "fracviewer.h"
  37.  
  38.  
  39. typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, 
  40.                MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
  41.                AXES } DisplayLists;
  42.  
  43. #define MAXLEVEL 8
  44.  
  45. int Rebuild = 1,        /* Rebuild display list in next display? */
  46.     Fract   = TREE,     /* What fractal are we building */
  47.     Level   = 4;        /* levels of recursion for fractals */     
  48.  
  49. int DrawAxes = 0;       
  50.  
  51. /***************************************************************/
  52. /************************* VECTOR JUNK *************************/
  53. /***************************************************************/
  54.  
  55.   /* print vertex to stderr */
  56. void printvert(float v[3])
  57. {
  58.   fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]);
  59. }
  60.  
  61.   /* normalizes v */
  62. void normalize(GLfloat v[3])
  63. {
  64.   GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  65.  
  66.   if (d == 0)
  67.     fprintf(stderr, "Zero length vector in normalize\n");
  68.   else
  69.     v[0] /= d; v[1] /= d; v[2] /= d;
  70. }
  71.  
  72.   /* calculates a normalized crossproduct to v1, v2 */
  73. void ncrossprod(float v1[3], float v2[3], float cp[3])
  74. {
  75.   cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
  76.   cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
  77.   cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
  78.   normalize(cp);
  79. }
  80.  
  81.   /* calculates normal to the triangle designated by v1, v2, v3 */
  82. void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3])
  83. {
  84.   float vec1[3], vec2[3];
  85.  
  86.   vec1[0] = v3[0] - v1[0];  vec2[0] = v2[0] - v1[0];
  87.   vec1[1] = v3[1] - v1[1];  vec2[1] = v2[1] - v1[1];
  88.   vec1[2] = v3[2] - v1[2];  vec2[2] = v2[2] - v1[2];
  89.  
  90.   ncrossprod(vec2, vec1, norm);
  91. }
  92.  
  93. float xzlength(float v1[3], float v2[3])
  94. {
  95.   return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) +
  96.               (v1[2] - v2[2])*(v1[2] - v2[2]));
  97. }
  98.  
  99. float xzslope(float v1[3], float v2[3])
  100. {
  101.   return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0]))
  102.                        : FLT_MAX);
  103. }
  104.  
  105.  
  106. /***************************************************************/
  107. /************************ MOUNTAIN STUFF ***********************/
  108. /***************************************************************/
  109.  
  110. GLfloat DispFactor[MAXLEVEL];  /* Array of what to multiply random number
  111.                   by for a given level to get midpoint
  112.                   displacement  */
  113. GLfloat DispBias[MAXLEVEL];  /* Array of what to add to random number
  114.                 before multiplying it by DispFactor */
  115.  
  116. #define NUMRANDS 191
  117. float RandTable[NUMRANDS];  /* hash table of random numbers so we can
  118.                    raise the same midpoints by the same amount */ 
  119.  
  120.          /* The following are for permitting an edge of a moutain to be   */
  121.          /* pegged so it won't be displaced up or down.  This makes it    */
  122.          /* easier to setup scenes and makes a single moutain look better */
  123.  
  124. GLfloat Verts[3][3],    /* Vertices of outside edges of mountain */
  125.         Slopes[3];      /* Slopes between these outside edges */
  126. int     Pegged[3];      /* Is this edge pegged or not */           
  127.  
  128.  /*
  129.   * Comes up with a new table of random numbers [0,1)
  130.   */
  131. void InitRandTable(unsigned int seed)
  132. {
  133.   int i;
  134.  
  135.   srand48(seed);
  136.   for (i = 0; i < NUMRANDS; i++)
  137.     RandTable[i] = drand48() - 0.5;
  138. }
  139.  
  140.   /* calculate midpoint and displace it if required */
  141. void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3],
  142.           int edge, int level)
  143. {
  144.   unsigned hash;
  145.  
  146.   mid[0] = (v1[0] + v2[0]) / 2;
  147.   mid[1] = (v1[1] + v2[1]) / 2;
  148.   mid[2] = (v1[2] + v2[2]) / 2;
  149.   if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) 
  150.                         - Slopes[edge]) > 0.00001)) {
  151.     srand48((int)((v1[0]+v2[0])*23344));
  152.     hash = drand48() * 7334334;
  153.     srand48((int)((v2[2]+v1[2])*43433));
  154.     hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS;
  155.     mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]);
  156.   }
  157. }
  158.  
  159.   /*
  160.    * Recursive moutain drawing routine -- from lecture with addition of 
  161.    * allowing an edge to be pegged.  This function requires the above
  162.    * globals to be set, as well as the Level global for fractal level 
  163.    */
  164. void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level)
  165. {
  166.   if (level == Level) {
  167.     GLfloat norm[3];
  168.  
  169.     triagnormal(v1, v2, v3, norm);
  170.     glNormal3fv(norm);
  171.     glVertex3fv(v1);
  172.     glVertex3fv(v2);
  173.     glVertex3fv(v3);
  174.  
  175.   } else {
  176.     GLfloat m1[3], m2[3], m3[3];
  177.  
  178.     Midpoint(m1, v1, v2, 0, level);
  179.     Midpoint(m2, v2, v3, 1, level);
  180.     Midpoint(m3, v3, v1, 2, level);
  181.  
  182.     FMR(v1, m1, m3, level + 1);
  183.     FMR(m1, v2, m2, level + 1);
  184.     FMR(m3, m2, v3, level + 1);
  185.     FMR(m1, m2, m3, level + 1);
  186.   }
  187. }
  188.  
  189.  /*
  190.   * sets up lookup tables and calls recursive mountain function
  191.   */
  192. void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3],
  193.                      int pegged[3])
  194. {
  195.   GLfloat lengths[MAXLEVEL];
  196.   GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4  };
  197.   GLfloat bias[8]     = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1  };
  198.   int i;
  199.   float avglen = (xzlength(v1, v2) + 
  200.                   xzlength(v2, v3) +
  201.           xzlength(v3, v1) / 3);
  202.  
  203.   for (i = 0; i < 3; i++) {
  204.     Verts[0][i] = v1[i];      /* set mountain vertex globals */
  205.     Verts[1][i] = v2[i];
  206.     Verts[2][i] = v3[i];
  207.     Pegged[i] = pegged[i];
  208.   }
  209.  
  210.   Slopes[0] = xzslope(Verts[0], Verts[1]);   /* set edge slope globals */
  211.   Slopes[1] = xzslope(Verts[1], Verts[2]);
  212.   Slopes[2] = xzslope(Verts[2], Verts[0]);
  213.  
  214.   lengths[0] = avglen;          
  215.   for (i = 1; i < Level; i++) {   
  216.     lengths[i] = lengths[i-1]/2;     /* compute edge length for each level */
  217.   }
  218.  
  219.   for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */      
  220.     DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
  221.     DispBias[i]   = ((i <= 7) ? bias[i] : bias[7]);
  222.   } 
  223.  
  224.   glBegin(GL_TRIANGLES);
  225.     FMR(v1, v2, v3, 0);    /* issues no GL but vertex calls */
  226.   glEnd();
  227. }
  228.  
  229.  /*
  230.   * draw a mountain and build the display list
  231.   */
  232. void CreateMountain(void)
  233. {
  234.   GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 };
  235.   int pegged[3] = { 1, 1, 1 };
  236.  
  237.   glNewList(MOUNTAIN, GL_COMPILE);
  238.   glPushAttrib(GL_LIGHTING_BIT);
  239.     glCallList(MOUNTAIN_MAT);
  240.     FractalMountain(v1, v2, v3, pegged);
  241.   glPopAttrib();
  242.   glEndList();
  243. }
  244.  
  245.   /*
  246.    * new random numbers to make a different moutain
  247.    */
  248. void NewMountain(void)
  249. {
  250.   InitRandTable(time(NULL));
  251. }
  252.  
  253. /***************************************************************/
  254. /***************************** TREE ****************************/
  255. /***************************************************************/
  256.  
  257. unsigned long TreeSeed;   /* for srand48 - remember so we can build "same tree"
  258.                      at a different level */
  259.  
  260.  /*
  261.   * recursive tree drawing thing, fleshed out from class notes pseudocode 
  262.   */
  263. void FractalTree(int level)
  264. {
  265.   unsigned long savedseed;  /* need to save seeds while building tree too */
  266.  
  267.   if (level == Level) {
  268.       glPushMatrix();
  269.         glRotatef(drand48()*180, 0, 1, 0);
  270.         glCallList(STEMANDLEAVES);
  271.       glPopMatrix();
  272.   } else {
  273.     glCallList(STEM);
  274.     glPushMatrix();
  275.     glRotatef(drand48()*180, 0, 1, 0);
  276.     glTranslatef(0, 1, 0);
  277.     glScalef(0.7, 0.7, 0.7);
  278.  
  279.       savedseed = drand48()*ULONG_MAX;    /* recurse on a 3-way branching */
  280.       glPushMatrix();    
  281.         glRotatef(110 + drand48()*40, 0, 1, 0);
  282.         glRotatef(30 + drand48()*20, 0, 0, 1);
  283.         FractalTree(level + 1);
  284.       glPopMatrix();
  285.  
  286.       srand48(savedseed);
  287.       savedseed = drand48()*ULONG_MAX;
  288.       glPushMatrix();
  289.         glRotatef(-130 + drand48()*40, 0, 1, 0);
  290.         glRotatef(30 + drand48()*20, 0, 0, 1);
  291.         FractalTree(level + 1);
  292.       glPopMatrix();
  293.  
  294.       srand48(savedseed);
  295.       glPushMatrix();
  296.         glRotatef(-20 + drand48()*40, 0, 1, 0);
  297.         glRotatef(30 + drand48()*20, 0, 0, 1);
  298.         FractalTree(level + 1);
  299.       glPopMatrix();
  300.  
  301.     glPopMatrix();
  302.   }
  303. }
  304.  
  305.   /*
  306.    * Create display lists for a leaf, a set of leaves, and a stem
  307.    */
  308. void CreateTreeLists(void)
  309. {
  310.   GLUquadricObj *cylquad = gluNewQuadric();
  311.   int i;
  312.  
  313.   glNewList(STEM, GL_COMPILE);
  314.   glPushMatrix();
  315.     glRotatef(-90, 1, 0, 0);
  316.     gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
  317.   glPopMatrix();
  318.   glEndList();
  319.  
  320.   glNewList(LEAF, GL_COMPILE);  /* I think this was jeff allen's leaf idea */
  321.     glBegin(GL_TRIANGLES);
  322.       glNormal3f(-0.1, 0, 0.25);  /* not normalized */
  323.       glVertex3f(0, 0, 0);
  324.       glVertex3f(0.25, 0.25, 0.1);
  325.       glVertex3f(0, 0.5, 0);
  326.  
  327.       glNormal3f(0.1, 0, 0.25);
  328.       glVertex3f(0, 0, 0);
  329.       glVertex3f(0, 0.5, 0);
  330.       glVertex3f(-0.25, 0.25, 0.1);
  331.     glEnd();
  332.   glEndList();
  333.  
  334.   glNewList(STEMANDLEAVES, GL_COMPILE);
  335.   glPushMatrix();
  336.   glPushAttrib(GL_LIGHTING_BIT);
  337.     glCallList(STEM);
  338.     glCallList(LEAF_MAT);
  339.     for(i = 0; i < 3; i++) {
  340.       glTranslatef(0, 0.333, 0);
  341.       glRotatef(90, 0, 1, 0);
  342.       glPushMatrix();
  343.         glRotatef(0, 0, 1, 0);
  344.         glRotatef(50, 1, 0, 0);
  345.         glCallList(LEAF);
  346.       glPopMatrix();
  347.       glPushMatrix();
  348.         glRotatef(180, 0, 1, 0);
  349.         glRotatef(60, 1, 0, 0);
  350.         glCallList(LEAF);
  351.       glPopMatrix();
  352.     }
  353.   glPopAttrib();
  354.   glPopMatrix();
  355.   glEndList();
  356. }
  357.  
  358.  /*
  359.   * draw and build display list for tree
  360.   */
  361. void CreateTree(void)
  362. {
  363.   srand48(TreeSeed);
  364.  
  365.   glNewList(TREE, GL_COMPILE);
  366.     glPushMatrix();
  367.     glPushAttrib(GL_LIGHTING_BIT);
  368.     glCallList(TREE_MAT);
  369.     glTranslatef(0, -1, 0);
  370.     FractalTree(0);
  371.     glPopAttrib();
  372.     glPopMatrix();
  373.   glEndList();  
  374. }
  375.  
  376.  /*
  377.   * new seed for a new tree (groan)
  378.   */
  379. void NewTree(void)
  380. {
  381.   TreeSeed = time(NULL);
  382. }
  383.  
  384. /***************************************************************/
  385. /*********************** FRACTAL PLANET ************************/
  386. /***************************************************************/
  387.  
  388. void CreateIsland(void)
  389. {
  390.   CreateMountain();
  391.   glNewList(ISLAND, GL_COMPILE);
  392.   glPushAttrib(GL_LIGHTING_BIT);
  393.   glMatrixMode(GL_MODELVIEW);
  394.   glPushMatrix();
  395.     glCallList(WATER_MAT);
  396.  
  397.     glBegin(GL_QUADS);
  398.       glNormal3f(0, 1, 0);
  399.       glVertex3f(1000, 0.01, 1000);
  400.       glVertex3f(1000, 0.01, -1000);
  401.       glVertex3f(-1000, 0.01, -1000);
  402.       glVertex3f(-1000, 0.01, 1000);
  403.     glEnd();
  404.  
  405.     glPushMatrix();
  406.     glTranslatef(0, -0.1, 0);
  407.     glCallList(MOUNTAIN);
  408.     glPopMatrix();
  409.  
  410.     glPushMatrix();
  411.     glRotatef(135, 0, 1, 0);
  412.     glTranslatef(0.2, -0.15, -0.4);
  413.     glCallList(MOUNTAIN);
  414.     glPopMatrix();
  415.  
  416.     glPushMatrix();
  417.     glRotatef(-60, 0, 1, 0);
  418.     glTranslatef(0.7, -0.07, 0.5);
  419.     glCallList(MOUNTAIN);
  420.     glPopMatrix();
  421.  
  422.     glPushMatrix();
  423.     glRotatef(-175, 0, 1, 0);
  424.     glTranslatef(-0.7, -0.05, -0.5);
  425.     glCallList(MOUNTAIN);
  426.     glPopMatrix();
  427.  
  428.     glPushMatrix();
  429.     glRotatef(165, 0, 1, 0);
  430.     glTranslatef(-0.9, -0.12, 0.0);
  431.     glCallList(MOUNTAIN);
  432.     glPopMatrix();
  433.  
  434.   glPopMatrix();
  435.   glPopAttrib();
  436.   glEndList();  
  437. }
  438.  
  439.  
  440. void NewFractals(void)
  441. {
  442.   NewMountain();
  443.   NewTree();
  444. }
  445.  
  446. void Create(int fract)
  447. {
  448.   switch(fract) {
  449.     case MOUNTAIN:
  450.       CreateMountain();
  451.       break;
  452.     case TREE:
  453.       CreateTree();
  454.       break;
  455.     case ISLAND:
  456.       CreateIsland();
  457.       break;
  458.   }
  459. }
  460.  
  461.  
  462.  
  463. /***************************************************************/
  464. /**************************** OPENGL ***************************/
  465. /***************************************************************/
  466.  
  467.  
  468. void SetupMaterials(void)
  469. {
  470.   GLfloat mtn_ambuse[] =   { 0.426, 0.256, 0.108, 1.0 };
  471.   GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 };
  472.   GLfloat mtn_shininess[] = { 10 };
  473.  
  474.   GLfloat water_ambuse[] =   { 0.0, 0.1, 0.5, 1.0 };
  475.   GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 };
  476.   GLfloat water_shininess[] = { 10 };
  477.  
  478.   GLfloat tree_ambuse[] =   { 0.4, 0.25, 0.1, 1.0 };
  479.   GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
  480.   GLfloat tree_shininess[] = { 0 };
  481.  
  482.   GLfloat leaf_ambuse[] =   { 0.0, 0.8, 0.0, 1.0 };
  483.   GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
  484.   GLfloat leaf_shininess[] = { 10 };
  485.  
  486.   glNewList(MOUNTAIN_MAT, GL_COMPILE);
  487.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse);
  488.     glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular);
  489.     glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess);
  490.   glEndList();
  491.  
  492.   glNewList(WATER_MAT, GL_COMPILE);
  493.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse);
  494.     glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular);
  495.     glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess);
  496.   glEndList();
  497.  
  498.   glNewList(TREE_MAT, GL_COMPILE);
  499.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
  500.     glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
  501.     glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
  502.   glEndList();
  503.  
  504.   glNewList(LEAF_MAT, GL_COMPILE);
  505.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
  506.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
  507.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
  508.   glEndList();
  509. }
  510.  
  511. void myGLInit(void)
  512. {
  513.   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  514.   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  515.   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  516.   GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 };
  517.  
  518.   GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
  519.  
  520.   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  521.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  522.   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  523.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  524.     
  525.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  526.  
  527.   glEnable(GL_LIGHTING);
  528.   glEnable(GL_LIGHT0);
  529.  
  530.   glDepthFunc(GL_LEQUAL);
  531.   glEnable(GL_DEPTH_TEST);
  532.  
  533.   glEnable(GL_NORMALIZE);
  534. #if 0
  535.   glEnable(GL_CULL_FACE);
  536.   glCullFace(GL_BACK);
  537. #endif
  538.  
  539.   glShadeModel(GL_SMOOTH);
  540. #if 0
  541.   glEnable(GL_BLEND);
  542.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  543. #endif
  544.  
  545.   SetupMaterials();
  546.   CreateTreeLists();
  547.  
  548.   glFlush();
  549.  
  550. /***************************************************************/
  551. /************************ GLUT STUFF ***************************/
  552. /***************************************************************/
  553.  
  554. void reshape(GLsizei w, GLsizei h)
  555. {
  556.   glViewport(0,0,w,h);
  557.   glMatrixMode(GL_PROJECTION);
  558.   glLoadIdentity();
  559.   gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
  560.   glPushMatrix();
  561.   glMatrixMode(GL_MODELVIEW);
  562.   glFlush();
  563. }
  564.  
  565. void display(void)
  566.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  567.   glFlush();
  568.  
  569.   glMatrixMode(GL_PROJECTION);
  570.   glPopMatrix();
  571.   glPushMatrix();  /* clear of last viewing xform, leaving perspective */
  572.  
  573.   agvViewTransform();
  574.  
  575.   glMatrixMode(GL_MODELVIEW);
  576.   glLoadIdentity();
  577.  
  578.   if (Rebuild) {
  579.     Create(Fract);
  580.     Rebuild = 0;
  581.   }
  582.  
  583.   glCallList(Fract);
  584.  
  585.   if (DrawAxes)
  586.     glCallList(AXES);
  587.  
  588.   glutSwapBuffers();
  589.   glFlush();
  590. }
  591.  
  592.  
  593. void visible(int v)
  594. {
  595.   if (v == GLUT_VISIBLE)
  596.     agvSetAllowIdle(1);
  597.   else {
  598.     glutIdleFunc(NULL);
  599.     agvSetAllowIdle(0);
  600.   }
  601. }
  602.  
  603. void menuuse(int v)
  604. {
  605.   if (v == GLUT_MENU_NOT_IN_USE)
  606.     agvSetAllowIdle(1);
  607.   else {
  608.     glutIdleFunc(NULL);
  609.     agvSetAllowIdle(0);
  610.   }
  611. }
  612.  
  613. /***************************************************************/
  614. /******************* MENU SETUP & HANDLING *********************/
  615. /***************************************************************/
  616.  
  617. typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices;
  618.  
  619. void setlevel(int value)
  620. {
  621.   Level = value;
  622.   Rebuild = 1;
  623.   glutPostRedisplay();
  624. }
  625.  
  626. void choosefract(int value)
  627. {
  628.   Fract = value;
  629.   Rebuild = 1;
  630.   glutPostRedisplay();
  631. }
  632.  
  633. void handlemenu(int value)
  634. {
  635.   switch (value) {
  636.     case MENU_QUIT:
  637.       exit(0);
  638.       break;
  639.     case MENU_RAND:
  640.       NewFractals();
  641.       Rebuild = 1;
  642.       glutPostRedisplay();
  643.       break;
  644.     case MENU_AXES:
  645.       DrawAxes = !DrawAxes;
  646.       glutPostRedisplay();
  647.       break;
  648.     }
  649. }
  650.  
  651. void MenuInit(void)
  652. {
  653.   int submenu3, submenu2, submenu1;
  654.  
  655.   submenu1 = glutCreateMenu(setlevel);
  656.   glutAddMenuEntry("0", 0);  glutAddMenuEntry("1", 1);
  657.   glutAddMenuEntry("2", 2);  glutAddMenuEntry("3", 3);
  658.   glutAddMenuEntry("4", 4);  glutAddMenuEntry("5", 5);
  659.   glutAddMenuEntry("6", 6);  glutAddMenuEntry("7", 7);
  660.   glutAddMenuEntry("8", 8);
  661.  
  662.   submenu2 = glutCreateMenu(choosefract);
  663.   glutAddMenuEntry("Moutain", MOUNTAIN);
  664.   glutAddMenuEntry("Tree", TREE);
  665.   glutAddMenuEntry("Island", ISLAND);
  666.  
  667.   submenu3 = glutCreateMenu(agvSwitchMoveMode);
  668.   glutAddMenuEntry("Flying", FLYING);
  669.   glutAddMenuEntry("Polar", POLAR);
  670.  
  671.   glutCreateMenu(handlemenu);
  672.   glutAddSubMenu("Level", submenu1);
  673.   glutAddSubMenu("Fractal", submenu2);
  674.   glutAddSubMenu("Movement", submenu3);
  675.   glutAddMenuEntry("New Fractal",      MENU_RAND);
  676.   glutAddMenuEntry("Toggle Axes", MENU_AXES);
  677.   glutAddMenuEntry("Quit",             MENU_QUIT);
  678.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  679. }
  680.  
  681.  
  682. /***************************************************************/
  683. /**************************** MAIN *****************************/
  684. /***************************************************************/
  685.  
  686. int main(int argc, char** argv)
  687. {
  688.   glutInit(&argc, argv);
  689.   glutInitWindowSize(512, 512);
  690.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
  691.   glutCreateWindow("Fractal Planet?");
  692.  
  693.   agvInit(1); /* 1 cause we don't have our own idle */
  694.  
  695.   glutReshapeFunc(reshape);
  696.   glutDisplayFunc(display);
  697.   glutVisibilityFunc(visible);
  698.   glutMenuStateFunc(menuuse);
  699.  
  700.   NewFractals();
  701.   agvMakeAxesList(AXES);
  702.   myGLInit(); 
  703.   MenuInit();
  704.  
  705.   glutMainLoop();
  706.   return 0;             /* ANSI C requires main to return int. */
  707. }
  708.