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 / hanoi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  8.7 KB  |  470 lines

  1.  
  2. /* hanoi.c - written by Greg Humphreys while an intern at SGI */
  3.  
  4. #include <GL/glut.h>
  5. #include <malloc.h>
  6. #include <stdio.h>
  7.  
  8. /* Hopefully, getopt comes from one of these two places. */
  9. #include <stdlib.h>
  10. #include <unistd.h>   /* POSIX.2 getopt location. */
  11.  
  12. double WIDTH = 800;
  13. double HEIGHT = 800;
  14.  
  15. GLboolean motion = GL_TRUE;
  16. GLboolean back_wall = GL_FALSE;
  17. GLint xangle = 0, yangle = 0;
  18. GLint xlangle = 0, ylangle = 0;
  19.  
  20. #define other(i,j) (6-(i+j))
  21. #define wallz -(WIDTH/2)
  22. #define DISK_HEIGHT 20
  23. int NUM_DISKS = 11;
  24. #define CONE NUM_DISKS+1
  25. #define WALL CONE + 1
  26. #define HANOI_SOLVE 0
  27. #define HANOI_QUIT 1
  28. #define HANOI_LIGHTING 2
  29. #define HANOI_WALL 3
  30. #define HANOI_FOG 4
  31.  
  32. GLfloat lightOneDirection[] =
  33. {0, 0, -1};
  34. GLfloat lightOnePosition[] =
  35. {200, 100, 300, 1};
  36. GLfloat lightOneColor[] =
  37. {1.0, 1.0, 0.5, 1.0};
  38.  
  39. GLfloat lightTwoDirection[] =
  40. {0, 0, -1};
  41. GLfloat lightTwoPosition[] =
  42. {600, 100, 300, 1};
  43. GLfloat lightTwoColor[] =
  44. {1.0, 0.0, 0.3, 1.0};
  45.  
  46. GLfloat lightZeroPosition[] =
  47. {400, 200, 300, 1};
  48. GLfloat lightZeroColor[] =
  49. {.3, .3, .3, .3};
  50.  
  51. GLfloat diskColor[] =
  52. {1.0, 1.0, 1.0, .8}, poleColor[] =
  53. {1.0, 0.2, 0.2, .8};
  54.  
  55. typedef struct stack_node {
  56.   int size;
  57.   struct stack_node *next;
  58. } stack_node;
  59.  
  60. typedef struct stack {
  61.   struct stack_node *head;
  62.   int depth;
  63. } stack;
  64.  
  65. stack poles[4];
  66.  
  67. void 
  68. push(int which, int size)
  69. {
  70.   stack_node *new = malloc(sizeof(stack_node));
  71.   if (!new) {
  72.     fprintf(stderr, "out of memory!\n");
  73.     exit(-1);
  74.   }
  75.   new->size = size;
  76.   new->next = poles[which].head;
  77.   poles[which].head = new;
  78.   poles[which].depth++;
  79. }
  80.  
  81. int 
  82. pop(int which)
  83. {
  84.   int retval = poles[which].head->size;
  85.   stack_node *temp = poles[which].head;
  86.   poles[which].head = poles[which].head->next;
  87.   poles[which].depth--;
  88.   free(temp);
  89.   return retval;
  90. }
  91.  
  92. typedef struct move_node {
  93.   int t, f;
  94.   struct move_node *next;
  95.   struct move_node *prev;
  96. } move_node;
  97.  
  98. typedef struct move_stack {
  99.   int depth;
  100.   struct move_node *head, *tail;
  101. } move_stack;
  102.  
  103. move_stack moves;
  104.  
  105. void 
  106. init(void)
  107. {
  108.   int i;
  109.   for (i = 0; i < 4; i++) {
  110.     poles[i].head = NULL;
  111.     poles[i].depth = 0;
  112.   }
  113.   moves.head = NULL;
  114.   moves.tail = NULL;
  115.   moves.depth = 0;
  116.  
  117.   for (i = 1; i <= NUM_DISKS; i++) {
  118.     glNewList(i, GL_COMPILE);
  119.     {
  120.       glutSolidTorus(DISK_HEIGHT / 2, 5 * i, 15, 15);
  121.     }
  122.     glEndList();
  123.   }
  124.   glNewList(CONE, GL_COMPILE);
  125.   {
  126.     glutSolidCone(10, (NUM_DISKS + 1) * DISK_HEIGHT, 20, 20);
  127.   }
  128.   glEndList();
  129. }
  130.  
  131. void 
  132. mpop(void)
  133. {
  134.   move_node *temp = moves.head;
  135.   moves.head = moves.head->next;
  136.   free(temp);
  137.   moves.depth--;
  138. }
  139.  
  140. void 
  141. mpush(int t, int f)
  142. {
  143.   move_node *new = malloc(sizeof(move_node));
  144.   if (!new) {
  145.     fprintf(stderr, "Out of memory!\n");
  146.     exit(-1);
  147.   }
  148.   new->t = t;
  149.   new->f = f;
  150.   new->next = NULL;
  151.   new->prev = moves.tail;
  152.   if (moves.tail)
  153.     moves.tail->next = new;
  154.   moves.tail = new;
  155.   if (!moves.head)
  156.     moves.head = moves.tail;
  157.   moves.depth++;
  158. }
  159.  
  160. void 
  161. keyboard(unsigned char key, int x, int y)
  162. {
  163.   switch (key) {
  164.   case 27:             /* ESC */
  165.   case 'q':
  166.   case 'Q':
  167.     exit(0);
  168.   }
  169. }
  170.  
  171. void 
  172. update(void)
  173. {
  174.   glutPostRedisplay();
  175. }
  176.  
  177. void 
  178. DrawPost(int xcenter)
  179. {
  180.   glPushMatrix();
  181.   {
  182.     glTranslatef(xcenter, 0, 0);
  183.     glRotatef(90, -1, 0, 0);
  184.     glCallList(CONE);
  185.   } glPopMatrix();
  186. }
  187.  
  188. void 
  189. DrawPosts(void)
  190. {
  191.   glColor3fv(poleColor);
  192.   glLineWidth(10);
  193.   glMaterialfv(GL_FRONT, GL_DIFFUSE, poleColor);
  194.   DrawPost(WIDTH / 4);
  195.   DrawPost(2 * WIDTH / 4);
  196.   DrawPost(3 * WIDTH / 4);
  197. }
  198.  
  199. void 
  200. DrawDisk(int xcenter, int ycenter, int size)
  201. {
  202.   glPushMatrix();
  203.   {
  204.     glTranslatef(xcenter, ycenter, 0);
  205.     glRotatef(90, 1, 0, 0);
  206.     glCallList(size);
  207.   } glPopMatrix();
  208. }
  209.  
  210. void 
  211. DrawDooDads(void)
  212. {
  213.   int i;
  214.   stack_node *temp;
  215.   int xcenter, ycenter;
  216.   glColor3fv(diskColor);
  217.   glMaterialfv(GL_FRONT, GL_DIFFUSE, diskColor);
  218.   for (i = 1; i <= 3; i++) {
  219.     xcenter = i * WIDTH / 4;
  220.     for (temp = poles[i].head, ycenter = DISK_HEIGHT * poles[i].depth - DISK_HEIGHT / 2; temp; temp = temp->next, ycenter -= DISK_HEIGHT) {
  221.       DrawDisk(xcenter, ycenter, temp->size);
  222.     }
  223.   }
  224. }
  225.  
  226. #define MOVE(t,f) mpush((t),(f))
  227.  
  228. static void
  229. mov(int n, int f, int t)
  230. {
  231.   int o;
  232.  
  233.   if (n == 1) {
  234.     MOVE(t, f);
  235.     return;
  236.   }
  237.   o = other(f, t);
  238.   mov(n - 1, f, o);
  239.   mov(1, f, t);
  240.   mov(n - 1, o, t);
  241. }
  242.  
  243. GLfloat wallcolor[] =
  244. {0, .3, 1, 1};
  245.  
  246. void 
  247. DrawWall(void)
  248. {
  249.   int i;
  250.   int j;
  251.   glColor3fv(wallcolor);
  252.   for (i = 0; i < WIDTH; i += 10) {
  253.     for (j = 0; j < HEIGHT; j += 10) {
  254.       glBegin(GL_POLYGON);
  255.       {
  256.         glNormal3f(0, 0, 1);
  257.         glVertex3f(i + 10, j, wallz);
  258.         glVertex3f(i + 10, j + 10, wallz);
  259.         glVertex3f(i, j + 10, wallz);
  260.         glVertex3f(i, j, wallz);
  261.       }
  262.       glEnd();
  263.     }
  264.   }
  265. }
  266.  
  267. void 
  268. draw(void)
  269. {
  270.   int t, f;
  271.  
  272.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  273.  
  274.   if (back_wall) {
  275.     glMaterialfv(GL_FRONT, GL_DIFFUSE, wallcolor);
  276.     DrawWall();
  277.   }
  278.   glPushMatrix();
  279.   {
  280.     glTranslatef(WIDTH / 2, HEIGHT / 2, 0);
  281.     glRotatef(xlangle, 0, 1, 0);
  282.     glRotatef(ylangle, 1, 0, 0);
  283.     glTranslatef(-WIDTH / 2, -HEIGHT / 2, 0);
  284.     glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  285.   }
  286.   glPopMatrix();
  287.  
  288.   glPushMatrix();
  289.   {
  290.     glTranslatef(WIDTH / 2, HEIGHT / 2, 0);
  291.     glRotatef(xangle, 0, 1, 0);
  292.     glRotatef(yangle, 1, 0, 0);
  293.     glTranslatef(-WIDTH / 2, -HEIGHT / 2, 0);
  294.     DrawPosts();
  295.     DrawDooDads();
  296.   }
  297.   glPopMatrix();
  298.   if (motion && moves.depth) {
  299.     t = moves.head->t;
  300.     f = moves.head->f;
  301.     push(t, pop(f));
  302.     mpop();
  303.   }
  304.   glutSwapBuffers();
  305. }
  306.  
  307. void 
  308. hanoi_menu(int value)
  309. {
  310.   switch (value) {
  311.   case HANOI_SOLVE:
  312.     motion = !motion;
  313.     if(motion) {
  314.       glutIdleFunc(update);
  315.     } else {
  316.       glutIdleFunc(NULL);
  317.     }
  318.     break;
  319.   case HANOI_LIGHTING:
  320.     if (glIsEnabled(GL_LIGHTING))
  321.       glDisable(GL_LIGHTING);
  322.     else
  323.       glEnable(GL_LIGHTING);
  324.     break;
  325.   case HANOI_WALL:
  326.     back_wall = !back_wall;
  327.     break;
  328.   case HANOI_FOG:
  329.     if (glIsEnabled(GL_FOG))
  330.       glDisable(GL_FOG);
  331.     else {
  332.       glEnable(GL_FOG);
  333.       glFogi(GL_FOG_MODE, GL_EXP);
  334.       glFogf(GL_FOG_DENSITY, .01);
  335.     }
  336.     break;
  337.   case HANOI_QUIT:
  338.     exit(0);
  339.     break;
  340.   }
  341.   glutPostRedisplay();
  342. }
  343.  
  344. int oldx, oldy;
  345.  
  346. GLboolean leftb = GL_FALSE, middleb = GL_FALSE;
  347.  
  348. void 
  349. hanoi_mouse(int button, int state, int x, int y)
  350. {
  351.   if (button == GLUT_LEFT_BUTTON) {
  352.     oldx = x;
  353.     oldy = y;
  354.     if (state == GLUT_DOWN)
  355.       leftb = GL_TRUE;
  356.     else
  357.       leftb = GL_FALSE;
  358.   }
  359.   if (button == GLUT_MIDDLE_BUTTON) {
  360.     oldx = x;
  361.     oldy = y;
  362.     if (state == GLUT_DOWN)
  363.       middleb = GL_TRUE;
  364.     else
  365.       middleb = GL_FALSE;
  366.   }
  367. }
  368.  
  369. void 
  370. hanoi_visibility(int state)
  371. {
  372.   if (state == GLUT_VISIBLE && motion) {
  373.     glutIdleFunc(update);
  374.   } else {
  375.     glutIdleFunc(NULL);
  376.   }
  377. }
  378.  
  379. void 
  380. hanoi_motion(int x, int y)
  381. {
  382.   if (leftb) {
  383.     xangle -= (x - oldx);
  384.     yangle -= (y - oldy);
  385.   }
  386.   if (middleb) {
  387.     xlangle -= (x - oldx);
  388.     ylangle -= (y - oldy);
  389.   }
  390.   oldx = x;
  391.   oldy = y;
  392.   glutPostRedisplay();
  393. }
  394.  
  395. int 
  396. main(int argc, char *argv[])
  397. {
  398.   int i;
  399.   int c;
  400.  
  401.   while ((c = getopt(argc, argv, "n:")) != EOF) {
  402.     switch (c) {
  403.     case 'n':
  404.       NUM_DISKS = atoi(optarg);
  405.       break;
  406.     }
  407.   }
  408.  
  409.   glutInit(&argc, argv);
  410.   glutInitWindowSize(WIDTH, HEIGHT);
  411.   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  412.  
  413.   glutCreateWindow("Hanoi");
  414.  
  415.   glutDisplayFunc(draw);
  416.   glutKeyboardFunc(keyboard);
  417.  
  418.   glViewport(0, 0, WIDTH, HEIGHT);
  419.   glMatrixMode(GL_PROJECTION);
  420.   glLoadIdentity();
  421.   glOrtho(0, WIDTH, 0, HEIGHT, -10000, 10000);
  422.   glMatrixMode(GL_MODELVIEW);
  423.   glLoadIdentity();
  424.   glClearColor(0, 0, 0, 0);
  425.   glClearDepth(1.0);
  426.  
  427.   glEnable(GL_CULL_FACE);
  428.   glEnable(GL_DEPTH_TEST);
  429.  
  430. /*  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);  */
  431.  
  432.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  433.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  434.   glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 10);
  435.   glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, lightOneDirection);
  436.   glEnable(GL_LIGHT1);
  437.  
  438.   glLightfv(GL_LIGHT2, GL_POSITION, lightTwoPosition);
  439.   glLightfv(GL_LIGHT2, GL_DIFFUSE, lightTwoColor);
  440. /*  glLightf(GL_LIGHT2,GL_LINEAR_ATTENUATION,.005); */
  441.   glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 10);
  442.   glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, lightTwoDirection);
  443.   glEnable(GL_LIGHT2);
  444.  
  445.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  446.   glEnable(GL_LIGHT0);
  447.  
  448.   glEnable(GL_LIGHTING);
  449.  
  450.   glutMouseFunc(hanoi_mouse);
  451.   glutMotionFunc(hanoi_motion);
  452.   glutVisibilityFunc(hanoi_visibility);
  453.  
  454.   glutCreateMenu(hanoi_menu);
  455.   glutAddMenuEntry("Solve", HANOI_SOLVE);
  456.   glutAddMenuEntry("Lighting", HANOI_LIGHTING);
  457.   glutAddMenuEntry("Back Wall", HANOI_WALL);
  458.   glutAddMenuEntry("Fog", HANOI_FOG);
  459.   glutAddMenuEntry("Quit", HANOI_QUIT);
  460.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  461.   init();
  462.  
  463.   for (i = 0; i < NUM_DISKS; i++)
  464.     push(1, NUM_DISKS - i);
  465.   mov(NUM_DISKS, 1, 3);
  466.  
  467.   glutMainLoop();
  468.   return 0;             /* ANSI C requires main to return int. */
  469. }
  470.