home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl1 / answers / lists.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  20.0 KB  |  815 lines

  1. /*
  2.  * Copyright 1996, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* lists.c - open a window and clear the background.
  19.  *    Set up callbacks to handle keyboard input.
  20.  *      Model some objects.  Use perspective projection.
  21.  *    Use independent modeling transformations to position objects.
  22.  *    Added reshape callback to reset the viewport and viewing volume.
  23.  *    Add depth buffering.
  24.  *    Add a viewing transformation and control it using mouse input.
  25.  *    Add continuous animation and a menu to control it.
  26.  *    Add a local light with distance attenuation, and a spot light.
  27.  *    Add two-sided lighting, and a back face material for one object.
  28.  *    Add 3D text.
  29.  *    Add display lists.
  30.  *
  31.  *    F1 key            - print help information
  32.  *    Right Mouse Button    - popup menu
  33.  *    Left Arrow Key        - move the reference point to the left
  34.  *    Right Arrow Key        - move the reference point to the right
  35.  *    Up Arrow Key        - move the reference point up
  36.  *    Down Arrow Key        - move the reference point down
  37.  *    <b> key            - toggle between bitmap/stroke fonts
  38.  *    <f> key            - toggle front/back face culling
  39.  *    <n> key            - toggle between night/day
  40.  *    <s> key            - toggle smooth/flat shading
  41.  *    SPACE key        - generates a random background color
  42.  *    Escape Key        - exit program
  43.  */
  44. #include <GL/gl.h>
  45. #include <GL/glu.h>
  46. #include <GL/glut.h>
  47.  
  48. #include <stdio.h>
  49. #include <math.h>
  50.  
  51. #include "fonts.h"    /* contains descriptions for 3 sample fonts */
  52.  
  53. /* Function Prototypes */
  54.  
  55. GLvoid initgfx( GLvoid );
  56. GLvoid keyboard( GLubyte, GLint, GLint );
  57. GLvoid specialkeys( GLint, GLint, GLint );
  58. GLvoid reshape( GLsizei, GLsizei );
  59. GLvoid animate( GLvoid );
  60. GLvoid visibility( GLint );
  61. GLvoid drawScene( GLvoid );
  62. GLvoid menuFunc( GLint );
  63.  
  64. void initGround( GLvoid );
  65. GLvoid drawGround( GLvoid );
  66. GLuint  create3DFont( GLfloat font[][1+MAX_STROKES*3] );
  67.  
  68. void checkError( char * );
  69. void printHelp( char * );
  70.  
  71. /* Global Variables */
  72.  
  73. static GLdouble        xRef = 0.0, yRef = 0.0;
  74.  
  75. static GLfloat        sunPosition = 2.5;
  76. static GLboolean    night = GL_FALSE;
  77. static GLboolean    use_bitmap_fonts = GL_FALSE;
  78.  
  79. static GLfloat         green[] = { 0.0, 1.0, 0.0 };
  80. static GLfloat         darkgreen[] = { 0.0, 0.25, 0.0 };
  81. static GLfloat         red[] = { 1.0, 0.0, 0.0 };
  82. static GLfloat         magenta[] = { 1.0, 0.0, 1.0 };
  83. static GLfloat         yellow[] = { 1.0, 1.0, 0.0 };
  84. static GLfloat         blue[] = { 0.0, 0.0, 1.0 };
  85.  
  86. static GLfloat         white[] = { 1.0, 1.0, 1.0, 1.0 };
  87. static GLfloat         black[] = { 0.0, 0.0, 0.0, 0.0 };
  88.  
  89. static void           *fixedFont, *romanFont;
  90.  
  91. static GLuint        groundList;
  92. static GLuint         outlineBase;
  93.  
  94. static char *progname; 
  95.  
  96. /* Global Definitions */
  97.  
  98. #define KEY_ESC    27    /* ascii value for the escape key */
  99.  
  100. /* menu options */
  101. #define MENU_ANIMATE    1    /* animation control option */
  102. #define MENU_EXIT    2    /* exit option */
  103.  
  104. #define GRIDPOINTS    41    /* number of vertices in ground mesh */
  105.  
  106. static GLfloat         groundMesh[GRIDPOINTS][GRIDPOINTS][3] = { 0 };
  107.  
  108. static GLboolean     animateFlag = GL_TRUE;
  109.  
  110. void
  111. main( int argc, char *argv[] )
  112. {
  113.     GLsizei width, height;
  114.  
  115.     glutInit( &argc, argv );
  116.  
  117.     /* create a window that is 1/4 the size of the screen,
  118.      * and position it in the middle of the screen.
  119.      */
  120.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  121.     height = glutGet( GLUT_SCREEN_HEIGHT );
  122.     glutInitWindowPosition( width / 4, height / 4 );
  123.     glutInitWindowSize( width / 2, height / 2 );
  124.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  125.     glutCreateWindow( argv[0] );
  126.  
  127.     initgfx();
  128.  
  129.     glutIdleFunc( animate );
  130.     glutVisibilityFunc( visibility );
  131.     glutReshapeFunc( reshape );
  132.     glutKeyboardFunc( keyboard );
  133.     glutSpecialFunc( specialkeys );
  134.     glutDisplayFunc( drawScene ); 
  135.  
  136.     /* create menu and add menu options */
  137.     glutCreateMenu( menuFunc );
  138.     glutAddMenuEntry( "Stop Animation", MENU_ANIMATE );
  139.     glutAddMenuEntry( "Exit", MENU_EXIT );
  140.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  141.  
  142.     progname = argv[0];
  143.  
  144.     printHelp( progname );
  145.  
  146.     glutMainLoop();
  147. }
  148.  
  149. void
  150. printHelp( char *progname )
  151. {
  152.     fprintf(stdout, 
  153.         "\n%s - create a scene using display lists\n\n"
  154.         "F1 key        - print help information\n"
  155.         "Left Arrow Key        - move reference point to the left\n"
  156.         "Right Arrow Key    - move reference point to the right\n"
  157.         "Up Arrow Key        - move reference point up\n"
  158.         "Down Arrow Key        - move reference point down\n"
  159.         "SPACE Key    - generates a random background color\n"
  160.         "<f> key        - toggle front/back face culling\n"
  161.         "<n> key        - toggle between night/day\n"
  162.         "<s> key        - toggle smooth/flat shading\n"
  163.         "Escape Key    - exit the program\n\n",
  164.         progname);
  165. }
  166.  
  167. GLvoid
  168. initgfx( GLvoid )
  169. {
  170.     GLfloat sunAmbient[4] = { 0.5, 0.5, 0.5, 1.0 };
  171.  
  172.     /* set clear color to blue */
  173.     glClearColor( 0.0, 0.0, 1.0, 1.0 );
  174.  
  175.     /* enable the depth buffer */
  176.     glEnable( GL_DEPTH_TEST );
  177.  
  178.     /* enable the face culling */
  179.     glEnable( GL_CULL_FACE );
  180.  
  181.     initGround();
  182.  
  183.     glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow );
  184.  
  185.     glMaterialfv( GL_FRONT, GL_SPECULAR, white );
  186.     glMaterialf( GL_FRONT, GL_SHININESS, 10.0 );
  187.  
  188.     /* Add a light for the sun */
  189.     glLightfv( GL_LIGHT0, GL_DIFFUSE, white );
  190.     glLightfv( GL_LIGHT0, GL_AMBIENT, sunAmbient );
  191.     glEnable( GL_LIGHT0 );
  192.     glEnable( GL_LIGHTING );
  193.  
  194.     /* have OpenGL automatically normalize the normals,
  195.      * since we have lighting turned on and are scaling
  196.       */
  197.     glEnable( GL_NORMALIZE );
  198.  
  199.     /* Enable fast material changes for diffuse material */
  200.     glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  201.     glEnable( GL_COLOR_MATERIAL );
  202.  
  203.     /* Set up two fonts to use for rendering */
  204.     fixedFont = GLUT_BITMAP_9_BY_15;
  205.     romanFont = GLUT_STROKE_ROMAN;
  206.  
  207.     groundList = glGenLists(1);
  208.     glNewList( groundList, GL_COMPILE );
  209.         drawGround();
  210.     glEndList();
  211.  
  212.     outlineBase = create3DFont( outlineFont );
  213. }
  214.  
  215. GLvoid 
  216. reshape( GLsizei width, GLsizei height )
  217. {
  218.     GLdouble    aspect;
  219.  
  220.     glViewport( 0, 0, width, height );
  221.  
  222.     /* compute aspect ratio */
  223.     aspect = (GLdouble) width / (GLdouble) height;
  224.  
  225.     glMatrixMode( GL_PROJECTION );
  226.  
  227.     /* Reset world coordinates first ... */
  228.     glLoadIdentity();
  229.  
  230.     /* Reset the viewing volume based on the new aspect ratio */
  231.     gluPerspective( 45.0, aspect, 3.0, 7.0 );
  232.  
  233.     glMatrixMode( GL_MODELVIEW );
  234. }
  235.  
  236. void 
  237. checkError( char *label )
  238. {
  239.     GLenum error;
  240.     while ( (error = glGetError()) != GL_NO_ERROR )
  241.         printf( "%s: %s\n", label, gluErrorString(error) );
  242. }
  243.  
  244. GLvoid 
  245. keyboard( GLubyte key, GLint x, GLint y )
  246. {
  247.     static GLboolean flat = GL_FALSE;
  248.     static GLboolean cullFront = GL_FALSE;
  249.  
  250.     switch (key) {
  251.     case ' ':    /* SPACE key */
  252.         /* generate a random background color */
  253.         glClearColor( drand48(), drand48(), drand48(), 1.0 ); 
  254.         glutPostRedisplay();
  255.         break;
  256.     case 'b':    /* b key */
  257.         /* toggle between bitmap and stroke fonts */
  258.         use_bitmap_fonts = !use_bitmap_fonts;
  259.         break;
  260.     case 'f':    /* f key */
  261.         /* toggle between back and front face culling */
  262.         cullFront = !cullFront;
  263.         if (cullFront) {
  264.             glCullFace( GL_FRONT );
  265.             printf("Culling FRONT faces\n");
  266.         } else { 
  267.             glCullFace( GL_BACK );
  268.             printf("Culling BACK faces\n");
  269.         }
  270.         glutPostRedisplay();
  271.         break;
  272.     case 'n':    /* n key */
  273.         /* toggle between night and day */
  274.         night = !night;
  275.         if (night) {
  276.             /* make the light fall off with distance much
  277.              * more quickly when it is night 
  278.              */
  279.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.1 );
  280.         } else { 
  281.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0 );
  282.         }
  283.         glutPostRedisplay();
  284.         break;
  285.     case 's':    /* s key */
  286.         /* toggle between smooth and flat shading */
  287.         flat = !flat;
  288.         if (flat)
  289.             glShadeModel( GL_FLAT );
  290.         else 
  291.             glShadeModel( GL_SMOOTH );
  292.         glutPostRedisplay();
  293.         break;
  294.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  295.         exit(0);
  296.     }
  297. }
  298.  
  299. GLvoid 
  300. specialkeys( GLint key, GLint x, GLint y )
  301. {
  302.     switch (key) {
  303.     case GLUT_KEY_F1:    /* Function key #1 */
  304.         /* print help information */
  305.         printHelp( progname );
  306.         break;
  307.  
  308.     case GLUT_KEY_LEFT:    /* move reference point to the left */
  309.         xRef -= 0.5;
  310.         if (xRef < -4.0) xRef = -4.0;
  311.         glutPostRedisplay();
  312.          break;
  313.  
  314.     case GLUT_KEY_RIGHT:    /* move reference point to the right */
  315.         xRef += 0.5;
  316.         if (xRef > 4.0) xRef = 4.0;
  317.         glutPostRedisplay();
  318.         break;
  319.  
  320.     case GLUT_KEY_UP:    /* move reference point up */
  321.         yRef += 0.5;
  322.         if (yRef > 3.0) yRef = 3.0;
  323.         glutPostRedisplay();
  324.         break;
  325.  
  326.     case GLUT_KEY_DOWN:    /* move reference point down */
  327.         yRef -= 0.5;
  328.         if (yRef < -3.0) yRef = -3.0;
  329.         glutPostRedisplay();
  330.         break;
  331.     }
  332. }
  333.  
  334. GLvoid 
  335. animate( GLvoid )
  336. {
  337.     /* update the position of the sun */
  338.     sunPosition -= 0.01;
  339.     if (sunPosition < -3.0) sunPosition = 2.5;
  340.  
  341.     /* Tell GLUT to redraw the scene */
  342.     glutPostRedisplay();
  343. }
  344.  
  345. GLvoid
  346. visibility( int state ) 
  347. {
  348.     if (state == GLUT_VISIBLE && animateFlag) {
  349.         glutIdleFunc( animate );
  350.     } else {
  351.         glutIdleFunc( NULL );
  352.     }
  353. }
  354.  
  355. GLvoid
  356. menuFunc( int value )
  357. {
  358.     switch (value) {
  359.     case MENU_ANIMATE:
  360.         animateFlag = !animateFlag;
  361.         if (animateFlag) {
  362.             glutIdleFunc( animate );
  363.             glutChangeToMenuEntry( MENU_ANIMATE, "Stop Animation",
  364.                         MENU_ANIMATE );
  365.         } else {
  366.             glutIdleFunc( NULL );
  367.             glutChangeToMenuEntry( MENU_ANIMATE, "Start Animation",
  368.                         MENU_ANIMATE );
  369.         }
  370.         break;
  371.     case MENU_EXIT:
  372.         exit(0);
  373.     }
  374. }
  375.  
  376. void
  377. initGround( void )
  378. {
  379.     int i, j;
  380.     GLfloat     x, y, spacing;
  381.  
  382.     /* Create a flat grid composed of points with the z value = 0 */
  383.     
  384.     /* spacing = distance between adjacent grid points in x and y */
  385.     spacing = 2.0 / (float)(GRIDPOINTS - 1);
  386.  
  387.     /* x and z range from -1.0 to 1.0 by spacing interval */
  388.     for ( x = -1.0, i = 0; i < GRIDPOINTS; x += spacing, i++ ) {
  389.         for ( y = -1.0, j = 0; j < GRIDPOINTS; y += spacing, j++ ) {
  390.             groundMesh[i][j][0] = x;
  391.             groundMesh[i][j][1] = y;
  392.             groundMesh[i][j][2] = 0.0;
  393.         }
  394.     }
  395. }
  396.  
  397. GLvoid
  398. drawGround( GLvoid )
  399. {
  400.     register int i, j;
  401.  
  402.     glNormal3f( 0.0, 0.0, 1.0 );
  403.     
  404.     /* Draw quad strips connecting grid points. 
  405.      * Grid is drawn column by column, 
  406.      * where each column is one quad strip.
  407.      * Every pair of vertices after first two vertices
  408.      * adds a new quad to the strip.
  409.      */
  410.     for ( i = 0; i < (GRIDPOINTS - 1); i++ ) {
  411.         glBegin( GL_QUAD_STRIP );
  412.         for ( j = 0; j < (GRIDPOINTS); j++ ) {
  413.             glColor3f( 0.0, 1.0 - (GLfloat) j/GRIDPOINTS, 0.0 );
  414.             glVertex3fv( &groundMesh[i][j][0] );
  415.             glVertex3fv( &groundMesh[i + 1][j][0] );
  416.         }
  417.         glEnd();
  418.     }
  419. }
  420.  
  421. GLvoid
  422. drawWindow()
  423. {
  424.     /* window */
  425.     static GLfloat v0[] = { 0.0, 0.4 };
  426.     static GLfloat v1[] = { 0.0, 0.0 };
  427.     static GLfloat v2[] = { 0.1, 0.4 };
  428.     static GLfloat v3[] = { 0.1, 0.0 };
  429.     static GLfloat v4[] = { 0.2, 0.4 };
  430.     static GLfloat v5[] = { 0.2, 0.0 };
  431.  
  432.     /* draw 2 quadrilateral strip to make a window */
  433.     glNormal3f( 0.0, 0.0, 1.0 );
  434.     glBegin( GL_QUAD_STRIP );
  435.         glColor3f( 1.0, 0.0, 0.0 );
  436.         glVertex2fv (v0);
  437.         glColor3f( 0.9, 0.0, 1.0 );
  438.         glVertex2fv (v1);
  439.         glColor3f( 0.8, 0.1, 0.0 );
  440.         glVertex2fv (v2);
  441.         glColor3f( 0.7, 0.2, 1.0 );
  442.         glVertex2fv (v3);
  443.         glColor3f( 0.6, 0.3, 0.0 );
  444.         glVertex2fv (v4);
  445.         glColor3f( 0.5, 0.4, 1.0 );
  446.         glVertex2fv (v5);
  447.         glColor3f( 0.4, 0.5, 0.0 );
  448.     glEnd();
  449. }
  450.  
  451. /* draw a "circle" using a triangle fan; set the
  452.  * center of the circle to white, and the outside
  453.  * to the color passed in
  454.  */
  455. GLvoid
  456. drawFan( GLfloat *color )
  457. {
  458.     /* Draw a triangle fan centered at the current coordinate
  459.      * system origin 
  460.      */
  461.     glNormal3f( 0.0, 0.0, 1.0 );
  462.     glBegin( GL_TRIANGLE_FAN );
  463.         glColor3f( 1.0, 1.0, 1.0 );
  464.         glVertex2f( 0.0, 0.0 );
  465.         glColor3fv( color );
  466.         glVertex2f( 0.0, -0.2 );
  467.         glVertex2f( 0.2, -0.1 );
  468.         glVertex2f( 0.2, 0.1 );
  469.         glVertex2f( 0.0, 0.2 );
  470.         glVertex2f( -0.2, 0.1 );
  471.         glVertex2f( -0.2, -0.1 );
  472.         glVertex2f( 0.0, -0.2 );
  473.     glEnd();
  474. }
  475.  
  476. /* draw a flower with the base of the stem 
  477.  * at the current location 
  478.  */
  479. GLvoid
  480. drawFlower( GLfloat *color )
  481. {
  482.     /* draw the stem with 2 leaves */
  483.     glColor3fv( darkgreen );
  484.     glNormal3f( 0.0, 0.0, 1.0 );
  485.     glBegin( GL_LINES );
  486.         glVertex2f( 0.0, 0.0 );         /* stem */
  487.         glVertex2f( 0.0, 0.25 );
  488.         glVertex2f( 0.0, 0.1 );         /* leaf */
  489.         glVertex2f( 0.05, 0.15 ); 
  490.         glVertex2f( 0.0, 0.05 );     /* leaf */
  491.         glVertex2f( -0.05, 0.2 );
  492.     glEnd();
  493.  
  494.     glPushMatrix();
  495.         /* move to the top of the stem */
  496.         glTranslatef( 0.0, 0.25, 0.0 );
  497.  
  498.         /* use a scaled triangle fan for the flower head */
  499.         glScalef( 0.1, 0.1, 1.0 );
  500.         drawFan( color );  
  501.     glPopMatrix();
  502. }
  503.  
  504. /* draw a house centered at the current origin;
  505.  * the bounding box for the house is 1.0 x 2.0 units
  506.  */
  507. GLvoid
  508. drawHouse()
  509. {
  510.     /* draw a 3D house */
  511.     glColor3f( 1.0, 1.0, 1.0 ); /* white */
  512.     SolidBox( 1.0, 1.5, 1.0 );
  513.  
  514.     glPushMatrix();
  515.         /* move to the peak of the roof */
  516.         glTranslatef( 0.0, 1.25, 0.0 );
  517.  
  518.         /* draw a triangle fan for the roof */
  519.         glColor3f( 0.0, 0.0, 0.0 ); /* black */
  520.         glNormal3f( 0.0, 1.0, 1.0 );
  521.         glBegin( GL_TRIANGLE_FAN );
  522.             glVertex3f( 0.0, 0.0, 0.0 ); /* peak */
  523.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  524.             glVertex3f( 0.5, -0.5, 0.5 ); /* front right */
  525.             glVertex3f( 0.5, -0.5, -0.5 ); /* back right */
  526.             glVertex3f( -0.5, -0.5, -0.5 ); /* back left */
  527.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  528.         glEnd();
  529.     glPopMatrix();
  530.  
  531.     glPushMatrix();
  532.         /* move to just in front of the house */
  533.         glTranslatef( 0.0, 0.0, 0.50001 );
  534.  
  535.         /* draw the door */
  536.         glColor3f( 0.5, 0.2, 0.1 ); /* brown */
  537.         glNormal3f( 0.0, 0.0, 1.0 );
  538.         glRectf( -0.2, -0.75, 0.2, 0.0 );
  539.  
  540.         glPushMatrix();
  541.             /* move to the location for the left window */
  542.             glTranslatef( -0.4, 0.2, 0.0 );
  543.             drawWindow();
  544.         glPopMatrix();
  545.  
  546.         glPushMatrix();
  547.             /* move to the location for the right window */
  548.             glTranslatef( 0.2, 0.2, 0.0 );
  549.             drawWindow();
  550.         glPopMatrix();
  551.     glPopMatrix();
  552. }
  553.  
  554. /* draw a lamp post centered at the current origin;
  555.  * the bounding box for the lamp is 0.5 x 3.0 units
  556.  */
  557. GLvoid
  558. drawLamp( GLint light )
  559. {
  560.     GLfloat spot_color[] = { 1.0, 1.0, 0.0, 1.0 };
  561.  
  562.     GLfloat spot_dir[] = { 0.0, 0.0, -1.0 };
  563.     GLfloat spot_cutoff = 30.0;
  564.     GLfloat spot_exp = 20.0;
  565.  
  566.     /* Note that a spotlight is a local light */
  567.     GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
  568.  
  569.     /* draw lamp post */
  570.     glColor3f( 0.0, 0.0, 0.0 );
  571.     SolidCylinder( 0.05, 3.0 );
  572.  
  573.     glPushMatrix();
  574.         glTranslatef( 0.0, 1.5, 0.0 );
  575.         glRotatef( -90, 0.0, 0.0, 1.0 );
  576.         glTranslatef( 0.0, 0.25, 0.0 );
  577.         SolidCylinder( 0.02, 0.5 );
  578.  
  579.         glTranslatef( 0.0, 0.2, 0.0 );
  580.         glRotatef( -90.0, 0.0, 1.0, 0.0 );
  581.         glTranslatef( 0.0, 0.0, -0.1 );
  582.         glutSolidCone( 0.05, 0.1, 15, 15 );
  583.  
  584.         if ( night ) { /* turn on the lamp */
  585.             glLightfv( light, GL_DIFFUSE, spot_color );
  586.             glLightfv( light, GL_SPECULAR, spot_color );
  587.             glLightfv( light, GL_SPOT_DIRECTION, spot_dir );
  588.             glLightf( light, GL_SPOT_CUTOFF, spot_cutoff );
  589.             glLightf( light, GL_SPOT_EXPONENT, spot_exp );
  590.             glLightfv( light, GL_POSITION, light_position );
  591.  
  592.             glEnable( light );
  593.         } else
  594.             glDisable( light );
  595.     glPopMatrix();
  596.  
  597. }
  598.  
  599. GLvoid
  600. renderBitmapString( void *font, char *string )
  601. {
  602.         int i;
  603.         int len = (int) strlen(string);
  604.         for (i = 0; i < len; i++) {
  605.                 glutBitmapCharacter(font, string[i]);
  606.         }
  607. }
  608.  
  609. GLvoid
  610. renderStrokeString( void *font, char *string )
  611. {
  612.         int i;
  613.         int len = (int) strlen(string);
  614.         for (i = 0; i < len; i++) {
  615.                 glutStrokeCharacter(font, string[i]);
  616.         }
  617. }
  618.  
  619. GLvoid
  620. render3DString( GLuint fontBase, char *string )
  621. {
  622.     glPushAttrib(GL_LIST_BIT);
  623.         glListBase( fontBase );
  624.         glCallLists( strlen(string), GL_UNSIGNED_BYTE, 
  625.                 (unsigned char *) string );
  626.     glPopAttrib();
  627. }
  628.  
  629. /* Create a display list for each letter in the font description
  630.  * passed in.
  631.  */
  632. GLuint 
  633. create3DFont( GLfloat font[][1+MAX_STROKES*3] )
  634. {
  635.     GLint mode, i, j;
  636.     GLuint fontBase;
  637.     GLfloat fontScale;
  638.  
  639.     fontBase = glGenLists( 256 );
  640.     for (i = 0; font[i][0] != END_OF_LIST; i++) {
  641.         glNewList( fontBase+(GLuint)font[i][0], GL_COMPILE );
  642.         for (j = 1; mode = font[i][j]; j += 3) {
  643.             if (mode == FONT_BEGIN) {
  644.                 fontScale = font[i][j+2];
  645.                 glBegin( (GLint) font[i][j+1] );
  646.             } else if (mode == FONT_NEXT) {
  647.                 glVertex2f( font[i][j+1]*fontScale, 
  648.                         font[i][j+2]*fontScale );
  649.             } else if (mode == FONT_END) {
  650.                 glVertex2f( font[i][j+1]*fontScale, 
  651.                         font[i][j+2]*fontScale );
  652.                 glEnd();
  653.             } else if (mode == FONT_ADVANCE) {
  654.                 glTranslatef( font[i][j+1]*fontScale, 
  655.                           font[i][j+2]*fontScale, 0.0 );
  656.             }
  657.         }
  658.         glEndList();
  659.     }
  660.     return fontBase;
  661. }
  662.  
  663. void
  664. drawSign( GLvoid )
  665. {
  666.     /* draw sign post */
  667.     glColor3f( 0.0, 0.0, 0.0 );
  668.     SolidCylinder( 0.01, 0.5 );
  669.  
  670.     /* draw sign */
  671.     glPushMatrix();
  672.         glTranslatef( 0.0, 0.25, 0.01 );
  673.         glColor3f( 1.0, 1.0, 1.0 );
  674.         glRectf( -0.11, -0.11, 0.11, 0.11 );
  675.  
  676.         glColor3f( 0.0, 0.0, 0.0 );
  677.         if (use_bitmap_fonts) {
  678.             glRasterPos3f( -0.1, 0.04, 0.01 );
  679.             renderBitmapString( fixedFont, "Beware" );
  680.             glRasterPos3f( -0.03, -0.02, 0.01 );
  681.             renderBitmapString( fixedFont, "of" );
  682.             glRasterPos3f( -0.06, -0.08, 0.01 );
  683.             renderBitmapString( fixedFont, "Dog" );
  684.         } else {
  685.             glPushMatrix();
  686.                 glTranslatef( -0.1, 0.04, 0.01 );
  687.                 glScalef( 0.0005, 0.0005, 0.0005 );
  688.                 renderStrokeString( romanFont, "Beware" );
  689.             glPopMatrix();
  690.             glPushMatrix();
  691.                 glTranslatef( -0.03, -0.02, 0.01 );
  692.                 glScalef( 0.0005, 0.0005, 0.0005 );
  693.                 renderStrokeString( romanFont, "of" );
  694.             glPopMatrix();
  695.             glPushMatrix();
  696.                 glTranslatef( -0.06, -0.08, 0.01 );
  697.                 glScalef( 0.0005, 0.0005, 0.0005 );
  698.                 renderStrokeString( romanFont, "Dog" );
  699.             glPopMatrix();
  700.         }
  701.     glPopMatrix();
  702. }
  703.  
  704. GLvoid
  705. drawScene( GLvoid )
  706. {
  707.     /* local light */
  708.     GLfloat   lightPosition[] = { 0.0, 0.0, 0.0, 1.0 };
  709.  
  710.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  711.  
  712.     glPushMatrix();
  713.  
  714.         /* Move the reference point */
  715.         gluLookAt( 0.0, 0.0, 4.0, xRef, yRef, 0.0, 0.0, 1.0, 0.0 );
  716.  
  717.         /* draw the sun */
  718.         glPushMatrix();
  719.             /* move to the location of the sun */
  720.             glTranslatef( sunPosition, 2.0, -1.5 );
  721.  
  722.             /* use a local light for the sun */
  723.             glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
  724.  
  725.             if ( night ) {
  726.                 glColor3fv( white );
  727.                 glMaterialfv( GL_FRONT, GL_EMISSION, white );
  728.             } else {
  729.                 glColor3fv( yellow );
  730.             }
  731.             glutSolidSphere( 0.2, 8, 15 );
  732.             if ( night ) 
  733.                 glMaterialfv( GL_FRONT, GL_EMISSION, black );
  734.         glPopMatrix();
  735.  
  736.         glPushMatrix();
  737.             glTranslatef( -1.5, 0.0, 0.5 );
  738.             glScalef( 0.7, 0.7, 0.7 );
  739.             drawLamp( GL_LIGHT1 );
  740.         glPopMatrix();
  741.  
  742.         /* draw the ground as a quad mesh so that it will
  743.          * be lit properly
  744.          */
  745.         glPushMatrix();
  746.             glTranslatef( 0.0, -1.0, 0.0 );
  747.             glRotatef( -45.0, 1.0, 0.0, 0.0 );
  748.             glScalef( 3.0, 1.0, 1.0 );
  749.             glCallList( groundList );
  750.         glPopMatrix();
  751.  
  752.         /* draw a sign in the foreground */
  753.         glPushMatrix();
  754.             glTranslatef( -1.5, -1.0, 0.9 );
  755.             glScalef( 0.5, 0.5, 1.0 );
  756.             drawSign();
  757.         glPopMatrix();
  758.  
  759.         /* draw a sign in the background */
  760.         glPushMatrix();
  761.             glTranslatef( 1.0, -1.0, 0.0 );
  762.             drawSign();
  763.         glPopMatrix();
  764.  
  765.         /* draw the house */
  766.         glPushMatrix();
  767.             /* move to where the center of the house should be */
  768.             glTranslatef( -0.5, 0.0, 0.0 );
  769.  
  770.             /* shrink the house slightly */
  771.             glScalef( 0.7, 0.7, 0.7 );
  772.             drawHouse();
  773.  
  774.             /* draw a knocked over trash can next to the house */
  775.             glDisable( GL_CULL_FACE );
  776.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 1.0 ); 
  777.  
  778.             glTranslatef( 0.7, -0.75, 0.5 );
  779.             glRotatef( 90.0, 1.0, 0.0, 0.0 );
  780.             glRotatef( 45.0, 0.0, 0.0, 1.0 );
  781.             glColor3f( 0.0, 0.0, 0.5 ); /* blue */
  782.             SolidCylinder( 0.15, 0.4 );
  783.  
  784.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 0.0 ); 
  785.             glEnable( GL_CULL_FACE );
  786.  
  787.             /* put a label on it */
  788.             glTranslatef( 0.16, 0.2, 0.05 );
  789.             glRotatef( 90.0, 0.0, 1.0, 0.0 );
  790.             glRotatef( -90.0, 0.0, 0.0, 1.0 );
  791.             glScalef( 0.006, 0.006, 0.006 );
  792.             glColor3f( 1.0, 1.0, 1.0 ); /* white */
  793.             render3DString( outlineBase, "Trash" );
  794.         glPopMatrix();
  795.  
  796.         /* draw several tulips in the foreground */
  797.         glPushMatrix();
  798.             glTranslatef( 1.0, -1.0, 1.0 );
  799.             drawFlower( red );
  800.             glTranslatef( 0.0, 0.0, -0.5 );
  801.             drawFlower( yellow );
  802.         glPopMatrix();
  803.         glPushMatrix();
  804.             glTranslatef( -1.0, -1.0, 1.0 );
  805.             drawFlower( blue );
  806.             glTranslatef( 0.0, 0.0, -0.5 );
  807.             drawFlower( magenta );
  808.         glPopMatrix();
  809.  
  810.     glPopMatrix();
  811.  
  812.     checkError( "drawScene" );
  813.     glutSwapBuffers();
  814. }
  815.