fractals.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:19k
源码类别:

GIS编程

开发平台:

Visual C++

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