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 / lmodel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  16.2 KB  |  662 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. /* lmodel.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.  *
  29.  *    F1 key            - print help information
  30.  *    Right Mouse Button    - popup menu
  31.  *    Left Arrow Key        - move the reference point to the left
  32.  *    Right Arrow Key        - move the reference point to the right
  33.  *    Up Arrow Key        - move the reference point up
  34.  *    Down Arrow Key        - move the reference point down
  35.  *    <f> key            - toggle front/back face culling
  36.  *    <n> key            - toggle between night/day
  37.  *    <s> key            - toggle smooth/flat shading
  38.  *    SPACE key        - generates a random background color
  39.  *    Escape Key        - exit program
  40.  */
  41. #include <GL/gl.h>
  42. #include <GL/glu.h>
  43. #include <GL/glut.h>
  44.  
  45. #include <stdio.h>
  46. #include <math.h>
  47.  
  48. /* Function Prototypes */
  49.  
  50. GLvoid initgfx( GLvoid );
  51. GLvoid keyboard( GLubyte, GLint, GLint );
  52. GLvoid specialkeys( GLint, GLint, GLint );
  53. GLvoid reshape( GLsizei, GLsizei );
  54. GLvoid animate( GLvoid );
  55. GLvoid visibility( GLint );
  56. GLvoid drawScene( GLvoid );
  57. GLvoid menuFunc( GLint );
  58.  
  59. void initGround( GLvoid );
  60.  
  61. void checkError( char * );
  62. void printHelp( char * );
  63.  
  64. /* Global Variables */
  65.  
  66. static GLdouble        xRef = 0.0, yRef = 0.0;
  67.  
  68. static GLfloat        sunPosition = 2.5;
  69. static GLboolean    night = GL_FALSE;
  70.  
  71. static GLfloat         green[] = { 0.0, 1.0, 0.0 };
  72. static GLfloat         darkgreen[] = { 0.0, 0.25, 0.0 };
  73. static GLfloat         red[] = { 1.0, 0.0, 0.0 };
  74. static GLfloat         magenta[] = { 1.0, 0.0, 1.0 };
  75. static GLfloat         yellow[] = { 1.0, 1.0, 0.0 };
  76. static GLfloat         blue[] = { 0.0, 0.0, 1.0 };
  77.  
  78. static GLfloat         white[] = { 1.0, 1.0, 1.0, 1.0 };
  79. static GLfloat         black[] = { 0.0, 0.0, 0.0, 0.0 };
  80.  
  81. static char *progname; 
  82.  
  83. /* Global Definitions */
  84.  
  85. #define KEY_ESC    27    /* ascii value for the escape key */
  86.  
  87. /* menu options */
  88. #define MENU_ANIMATE    1    /* animation control option */
  89. #define MENU_EXIT    2    /* exit option */
  90.  
  91. #define GRIDPOINTS    41    /* number of vertices in ground mesh */
  92.  
  93. static GLfloat         groundMesh[GRIDPOINTS][GRIDPOINTS][3] = { 0 };
  94.  
  95. static GLboolean     animateFlag = GL_TRUE;
  96.  
  97.  
  98. void
  99. main( int argc, char *argv[] )
  100. {
  101.     GLsizei width, height;
  102.  
  103.     glutInit( &argc, argv );
  104.  
  105.     /* create a window that is 1/4 the size of the screen,
  106.      * and position it in the middle of the screen.
  107.      */
  108.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  109.     height = glutGet( GLUT_SCREEN_HEIGHT );
  110.     glutInitWindowPosition( width / 4, height / 4 );
  111.     glutInitWindowSize( width / 2, height / 2 );
  112.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  113.     glutCreateWindow( argv[0] );
  114.  
  115.     initgfx();
  116.  
  117.     glutIdleFunc( animate );
  118.     glutVisibilityFunc( visibility );
  119.     glutReshapeFunc( reshape );
  120.     glutKeyboardFunc( keyboard );
  121.     glutSpecialFunc( specialkeys );
  122.     glutDisplayFunc( drawScene ); 
  123.  
  124.     /* create menu and add menu options */
  125.     glutCreateMenu( menuFunc );
  126.     glutAddMenuEntry( "Stop Animation", MENU_ANIMATE );
  127.     glutAddMenuEntry( "Exit", MENU_EXIT );
  128.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  129.  
  130.     progname = argv[0];
  131.  
  132.     printHelp( progname );
  133.  
  134.     glutMainLoop();
  135. }
  136.  
  137. void
  138. printHelp( char *progname )
  139. {
  140.     fprintf(stdout, 
  141.         "\n%s - create a scene with a local light and attenuation\n\n"
  142.         "F1 key        - print help information\n"
  143.         "Left Arrow Key        - move reference point to the left\n"
  144.         "Right Arrow Key    - move reference point to the right\n"
  145.         "Up Arrow Key        - move reference point up\n"
  146.         "Down Arrow Key        - move reference point down\n"
  147.         "SPACE Key    - generates a random background color\n"
  148.         "<f> key        - toggle front/back face culling\n"
  149.         "<n> key        - toggle between night/day\n"
  150.         "<s> key        - toggle smooth/flat shading\n"
  151.         "Escape Key    - exit the program\n\n",
  152.         progname);
  153. }
  154.  
  155. GLvoid
  156. initgfx( GLvoid )
  157. {
  158.     GLfloat sunAmbient[4] = { 0.5, 0.5, 0.5, 1.0 };
  159.  
  160.     /* set clear color to blue */
  161.     glClearColor( 0.0, 0.0, 1.0, 1.0 );
  162.  
  163.     /* enable the depth buffer */
  164.     glEnable( GL_DEPTH_TEST );
  165.  
  166.     /* enable the face culling */
  167.     glEnable( GL_CULL_FACE );
  168.  
  169.     initGround();
  170.  
  171.     glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow );
  172.  
  173.     glMaterialfv( GL_FRONT, GL_SPECULAR, white );
  174.     glMaterialf( GL_FRONT, GL_SHININESS, 10.0 );
  175.  
  176.     /* Add a light for the sun */
  177.     glLightfv( GL_LIGHT0, GL_DIFFUSE, white );
  178.     glLightfv( GL_LIGHT0, GL_AMBIENT, sunAmbient );
  179.     glEnable( GL_LIGHT0 );
  180.     glEnable( GL_LIGHTING );
  181.  
  182.     /* have OpenGL automatically normalize the normals,
  183.      * since we have lighting turned on and are scaling
  184.       */
  185.     glEnable( GL_NORMALIZE );
  186.  
  187.     /* Enable fast material changes for diffuse material */
  188.     glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  189.     glEnable( GL_COLOR_MATERIAL );
  190. }
  191.  
  192. GLvoid 
  193. reshape( GLsizei width, GLsizei height )
  194. {
  195.     GLdouble    aspect;
  196.  
  197.     glViewport( 0, 0, width, height );
  198.  
  199.     /* compute aspect ratio */
  200.     aspect = (GLdouble) width / (GLdouble) height;
  201.  
  202.     glMatrixMode( GL_PROJECTION );
  203.  
  204.     /* Reset world coordinates first ... */
  205.     glLoadIdentity();
  206.  
  207.     /* Reset the viewing volume based on the new aspect ratio */
  208.     gluPerspective( 45.0, aspect, 3.0, 7.0 );
  209.  
  210.     glMatrixMode( GL_MODELVIEW );
  211. }
  212.  
  213. void 
  214. checkError( char *label )
  215. {
  216.     GLenum error;
  217.     while ( (error = glGetError()) != GL_NO_ERROR )
  218.         printf( "%s: %s\n", label, gluErrorString(error) );
  219. }
  220.  
  221. GLvoid 
  222. keyboard( GLubyte key, GLint x, GLint y )
  223. {
  224.     static GLboolean flat = GL_FALSE;
  225.     static GLboolean cullFront = GL_FALSE;
  226.  
  227.     switch (key) {
  228.     case ' ':    /* SPACE key */
  229.         /* generate a random background color */
  230.         glClearColor( drand48(), drand48(), drand48(), 1.0 ); 
  231.         glutPostRedisplay();
  232.         break;
  233.     case 'f':    /* f key */
  234.         /* toggle between back and front face culling */
  235.         cullFront = !cullFront;
  236.         if (cullFront) {
  237.             glCullFace( GL_FRONT );
  238.             printf("Culling FRONT faces\n");
  239.         } else { 
  240.             glCullFace( GL_BACK );
  241.             printf("Culling BACK faces\n");
  242.         }
  243.         glutPostRedisplay();
  244.         break;
  245.     case 'n':    /* n key */
  246.         /* toggle between night and day */
  247.         night = !night;
  248.         if (night) {
  249.             /* make the light fall of with distance much
  250.              * more quickly when it is night 
  251.              */
  252.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.1 );
  253.         } else { 
  254.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0 );
  255.         }
  256.         glutPostRedisplay();
  257.         break;
  258.     case 's':    /* s key */
  259.         /* toggle between smooth and flat shading */
  260.         flat = !flat;
  261.         if (flat)
  262.             glShadeModel( GL_FLAT );
  263.         else 
  264.             glShadeModel( GL_SMOOTH );
  265.         glutPostRedisplay();
  266.         break;
  267.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  268.         exit(0);
  269.     }
  270. }
  271.  
  272. GLvoid 
  273. specialkeys( GLint key, GLint x, GLint y )
  274. {
  275.     switch (key) {
  276.     case GLUT_KEY_F1:    /* Function key #1 */
  277.         /* print help information */
  278.         printHelp( progname );
  279.         break;
  280.  
  281.     case GLUT_KEY_LEFT:    /* move reference point to the left */
  282.         xRef -= 0.5;
  283.         if (xRef < -4.0) xRef = -4.0;
  284.         glutPostRedisplay();
  285.          break;
  286.  
  287.     case GLUT_KEY_RIGHT:    /* move reference point to the right */
  288.         xRef += 0.5;
  289.         if (xRef > 4.0) xRef = 4.0;
  290.         glutPostRedisplay();
  291.         break;
  292.  
  293.     case GLUT_KEY_UP:    /* move reference point up */
  294.         yRef += 0.5;
  295.         if (yRef > 3.0) yRef = 3.0;
  296.         glutPostRedisplay();
  297.         break;
  298.  
  299.     case GLUT_KEY_DOWN:    /* move reference point down */
  300.         yRef -= 0.5;
  301.         if (yRef < -3.0) yRef = -3.0;
  302.         glutPostRedisplay();
  303.         break;
  304.     }
  305. }
  306.  
  307. GLvoid 
  308. animate( GLvoid )
  309. {
  310.     /* update the position of the sun */
  311.     sunPosition -= 0.01;
  312.     if (sunPosition < -3.0) sunPosition = 2.5;
  313.  
  314.     /* Tell GLUT to redraw the scene */
  315.     glutPostRedisplay();
  316. }
  317.  
  318. GLvoid
  319. visibility( int state ) 
  320. {
  321.     if (state == GLUT_VISIBLE && animateFlag) {
  322.         glutIdleFunc( animate );
  323.     } else {
  324.         glutIdleFunc( NULL );
  325.     }
  326. }
  327.  
  328. GLvoid
  329. menuFunc( int value )
  330. {
  331.     switch (value) {
  332.     case MENU_ANIMATE:
  333.         animateFlag = !animateFlag;
  334.         if (animateFlag) {
  335.             glutIdleFunc( animate );
  336.             glutChangeToMenuEntry( MENU_ANIMATE, "Stop Animation",
  337.                         MENU_ANIMATE );
  338.         } else {
  339.             glutIdleFunc( NULL );
  340.             glutChangeToMenuEntry( MENU_ANIMATE, "Start Animation",
  341.                         MENU_ANIMATE );
  342.         }
  343.         break;
  344.     case MENU_EXIT:
  345.         exit(0);
  346.     }
  347. }
  348.  
  349. void
  350. initGround( void )
  351. {
  352.     int i, j;
  353.     GLfloat     x, y, spacing;
  354.  
  355.     /* Create a flat grid composed of points with the z value = 0 */
  356.     
  357.     /* spacing = distance between adjacent grid points in x and y */
  358.     spacing = 2.0 / (float)(GRIDPOINTS - 1);
  359.  
  360.     /* x and z range from -1.0 to 1.0 by spacing interval */
  361.     for ( x = -1.0, i = 0; i < GRIDPOINTS; x += spacing, i++ ) {
  362.         for ( y = -1.0, j = 0; j < GRIDPOINTS; y += spacing, j++ ) {
  363.             groundMesh[i][j][0] = x;
  364.             groundMesh[i][j][1] = y;
  365.             groundMesh[i][j][2] = 0.0;
  366.         }
  367.     }
  368. }
  369.  
  370. GLvoid
  371. drawGround( GLvoid )
  372. {
  373.     register int i, j;
  374.  
  375.     glNormal3f( 0.0, 0.0, 1.0 );
  376.     
  377.     /* Draw quad strips connecting grid points. 
  378.      * Grid is drawn column by column, 
  379.      * where each column is one quad strip.
  380.      * Every pair of vertices after first two vertices
  381.      * adds a new quad to the strip.
  382.      */
  383.     for ( i = 0; i < (GRIDPOINTS - 1); i++ ) {
  384.         glBegin( GL_QUAD_STRIP );
  385.         for ( j = 0; j < (GRIDPOINTS); j++ ) {
  386.             glColor3f( 0.0, 1.0 - (GLfloat) j/GRIDPOINTS, 0.0 );
  387.             glVertex3fv( &groundMesh[i][j][0] );
  388.             glVertex3fv( &groundMesh[i + 1][j][0] );
  389.         }
  390.         glEnd();
  391.     }
  392. }
  393.  
  394. GLvoid
  395. drawWindow()
  396. {
  397.     /* window */
  398.     static GLfloat v0[] = { 0.0, 0.4 };
  399.     static GLfloat v1[] = { 0.0, 0.0 };
  400.     static GLfloat v2[] = { 0.1, 0.4 };
  401.     static GLfloat v3[] = { 0.1, 0.0 };
  402.     static GLfloat v4[] = { 0.2, 0.4 };
  403.     static GLfloat v5[] = { 0.2, 0.0 };
  404.  
  405.     /* draw 2 quadrilateral strip to make a window */
  406.     glNormal3f( 0.0, 0.0, 1.0 );
  407.     glBegin( GL_QUAD_STRIP );
  408.         glColor3f( 1.0, 0.0, 0.0 );
  409.         glVertex2fv (v0);
  410.         glColor3f( 0.9, 0.0, 1.0 );
  411.         glVertex2fv (v1);
  412.         glColor3f( 0.8, 0.1, 0.0 );
  413.         glVertex2fv (v2);
  414.         glColor3f( 0.7, 0.2, 1.0 );
  415.         glVertex2fv (v3);
  416.         glColor3f( 0.6, 0.3, 0.0 );
  417.         glVertex2fv (v4);
  418.         glColor3f( 0.5, 0.4, 1.0 );
  419.         glVertex2fv (v5);
  420.         glColor3f( 0.4, 0.5, 0.0 );
  421.     glEnd();
  422. }
  423.  
  424. /* draw a "circle" using a triangle fan; set the
  425.  * center of the circle to white, and the outside
  426.  * to the color passed in
  427.  */
  428. GLvoid
  429. drawFan( GLfloat *color )
  430. {
  431.     /* Draw a triangle fan centered at the current coordinate
  432.      * system origin 
  433.      */
  434.     glNormal3f( 0.0, 0.0, 1.0 );
  435.     glBegin( GL_TRIANGLE_FAN );
  436.         glColor3f( 1.0, 1.0, 1.0 );
  437.         glVertex2f( 0.0, 0.0 );
  438.         glColor3fv( color );
  439.         glVertex2f( 0.0, -0.2 );
  440.         glVertex2f( 0.2, -0.1 );
  441.         glVertex2f( 0.2, 0.1 );
  442.         glVertex2f( 0.0, 0.2 );
  443.         glVertex2f( -0.2, 0.1 );
  444.         glVertex2f( -0.2, -0.1 );
  445.         glVertex2f( 0.0, -0.2 );
  446.     glEnd();
  447. }
  448.  
  449. /* draw a flower with the base of the stem 
  450.  * at the current location 
  451.  */
  452. GLvoid
  453. drawFlower( GLfloat *color )
  454. {
  455.     /* draw the stem with 2 leaves */
  456.     glColor3fv( darkgreen );
  457.     glNormal3f( 0.0, 0.0, 1.0 );
  458.     glBegin( GL_LINES );
  459.         glVertex2f( 0.0, 0.0 );         /* stem */
  460.         glVertex2f( 0.0, 0.25 );
  461.         glVertex2f( 0.0, 0.1 );         /* leaf */
  462.         glVertex2f( 0.05, 0.15 ); 
  463.         glVertex2f( 0.0, 0.05 );     /* leaf */
  464.         glVertex2f( -0.05, 0.2 );
  465.     glEnd();
  466.  
  467.     glPushMatrix();
  468.         /* move to the top of the stem */
  469.         glTranslatef( 0.0, 0.25, 0.0 );
  470.  
  471.         /* use a scaled triangle fan for the flower head */
  472.         glScalef( 0.1, 0.1, 1.0 );
  473.         drawFan( color );  
  474.     glPopMatrix();
  475. }
  476.  
  477. /* draw a house centered at the current origin;
  478.  * the bounding box for the house is 1.0 x 2.0 units
  479.  */
  480. GLvoid
  481. drawHouse()
  482. {
  483.     /* draw a 3D house */
  484.     glColor3f( 1.0, 1.0, 1.0 ); /* white */
  485.     SolidBox( 1.0, 1.5, 1.0 );
  486.  
  487.     glPushMatrix();
  488.         /* move to the peak of the roof */
  489.         glTranslatef( 0.0, 1.25, 0.0 );
  490.  
  491.         /* draw a triangle fan for the roof */
  492.         glColor3f( 0.0, 0.0, 0.0 ); /* black */
  493.         glNormal3f( 0.0, 1.0, 1.0 );
  494.         glBegin( GL_TRIANGLE_FAN );
  495.             glVertex3f( 0.0, 0.0, 0.0 ); /* peak */
  496.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  497.             glVertex3f( 0.5, -0.5, 0.5 ); /* front right */
  498.             glVertex3f( 0.5, -0.5, -0.5 ); /* back right */
  499.             glVertex3f( -0.5, -0.5, -0.5 ); /* back left */
  500.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  501.         glEnd();
  502.     glPopMatrix();
  503.  
  504.     glPushMatrix();
  505.         /* move to just in front of the house */
  506.         glTranslatef( 0.0, 0.0, 0.50001 );
  507.  
  508.         /* draw the door */
  509.         glColor3f( 0.5, 0.2, 0.1 ); /* brown */
  510.         glNormal3f( 0.0, 0.0, 1.0 );
  511.         glRectf( -0.2, -0.75, 0.2, 0.0 );
  512.  
  513.         glPushMatrix();
  514.             /* move to the location for the left window */
  515.             glTranslatef( -0.4, 0.2, 0.0 );
  516.             drawWindow();
  517.         glPopMatrix();
  518.  
  519.         glPushMatrix();
  520.             /* move to the location for the right window */
  521.             glTranslatef( 0.2, 0.2, 0.0 );
  522.             drawWindow();
  523.         glPopMatrix();
  524.     glPopMatrix();
  525. }
  526.  
  527. /* draw a lamp post centered at the current origin;
  528.  * the bounding box for the lamp is 0.5 x 3.0 units
  529.  */
  530. GLvoid
  531. drawLamp( GLint light )
  532. {
  533.     GLfloat spot_color[] = { 1.0, 1.0, 0.0, 1.0 };
  534.  
  535.     GLfloat spot_dir[] = { 0.0, 0.0, -1.0 };
  536.     GLfloat spot_cutoff = 30.0;
  537.     GLfloat spot_exp = 20.0;
  538.  
  539.     /* Note that a spotlight is a local light */
  540.     GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
  541.  
  542.     /* draw lamp post */
  543.     glColor3f( 0.0, 0.0, 0.0 );
  544.     SolidCylinder( 0.05, 3.0 );
  545.  
  546.     glPushMatrix();
  547.         glTranslatef( 0.0, 1.5, 0.0 );
  548.         glRotatef( -90, 0.0, 0.0, 1.0 );
  549.         glTranslatef( 0.0, 0.25, 0.0 );
  550.         SolidCylinder( 0.02, 0.5 );
  551.  
  552.         glTranslatef( 0.0, 0.2, 0.0 );
  553.         glRotatef( -90.0, 0.0, 1.0, 0.0 );
  554.         glTranslatef( 0.0, 0.0, -0.1 );
  555.         glutSolidCone( 0.05, 0.1, 15, 15 );
  556.  
  557.         if ( night ) { /* turn on the lamp */
  558.             glLightfv( light, GL_DIFFUSE, spot_color );
  559.             glLightfv( light, GL_SPECULAR, spot_color );
  560.             glLightfv( light, GL_SPOT_DIRECTION, spot_dir );
  561.             glLightf( light, GL_SPOT_CUTOFF, spot_cutoff );
  562.             glLightf( light, GL_SPOT_EXPONENT, spot_exp );
  563.             glLightfv( light, GL_POSITION, light_position );
  564.  
  565.             glEnable( light );
  566.         } else
  567.             glDisable( light );
  568.     glPopMatrix();
  569.  
  570. }
  571.  
  572. GLvoid
  573. drawScene( GLvoid )
  574. {
  575.     /* local light */
  576.     GLfloat   lightPosition[] = { 0.0, 0.0, 0.0, 1.0 };
  577.  
  578.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  579.  
  580.     glPushMatrix();
  581.  
  582.         /* Move the reference point */
  583.         gluLookAt( 0.0, 0.0, 4.0, xRef, yRef, 0.0, 0.0, 1.0, 0.0 );
  584.  
  585.         /* draw the sun */
  586.         glPushMatrix();
  587.             /* move to the location of the sun */
  588.             glTranslatef( sunPosition, 2.0, -1.5 );
  589.  
  590.             /* use a local light for the sun */
  591.             glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
  592.  
  593.             if ( night ) {
  594.                 glColor3fv( white );
  595.                 glMaterialfv( GL_FRONT, GL_EMISSION, white );
  596.             } else {
  597.                 glColor3fv( yellow );
  598.             }
  599.             glutSolidSphere( 0.2, 8, 15 );
  600.             if ( night ) 
  601.                 glMaterialfv( GL_FRONT, GL_EMISSION, black );
  602.         glPopMatrix();
  603.  
  604.         glPushMatrix();
  605.             glTranslatef( -1.5, 0.0, 0.5 );
  606.             glScalef( 0.7, 0.7, 0.7 );
  607.             drawLamp( GL_LIGHT1 );
  608.         glPopMatrix();
  609.  
  610.         /* draw the ground as a quad mesh so that it will
  611.          * be lit properly
  612.          */
  613.         glPushMatrix();
  614.             glTranslatef( 0.0, -1.0, 0.0 );
  615.             glRotatef( -45.0, 1.0, 0.0, 0.0 );
  616.             glScalef( 3.0, 1.0, 1.0 );
  617.             drawGround();
  618.         glPopMatrix();
  619.  
  620.         /* draw the house */
  621.         glPushMatrix();
  622.             /* move to where the center of the house should be */
  623.             glTranslatef( -0.5, 0.0, 0.0 );
  624.  
  625.             /* shrink the house slightly */
  626.             glScalef( 0.7, 0.7, 0.7 );
  627.             drawHouse();
  628.  
  629.             /* draw a knocked over trash can next to the house */
  630.             glDisable( GL_CULL_FACE );
  631.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 1.0 ); 
  632.  
  633.             glTranslatef( 0.7, -0.75, 0.5 );
  634.             glRotatef( 90.0, 1.0, 0.0, 0.0 );
  635.             glRotatef( 45.0, 0.0, 0.0, 1.0 );
  636.             glColor3f( 0.0, 0.0, 0.5 ); /* blue */
  637.             SolidCylinder( 0.15, 0.4 );
  638.  
  639.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 0.0 ); 
  640.             glEnable( GL_CULL_FACE );
  641.         glPopMatrix();
  642.  
  643.         /* draw several tulips in the foreground */
  644.         glPushMatrix();
  645.             glTranslatef( 1.0, -1.0, 1.0 );
  646.             drawFlower( red );
  647.             glTranslatef( 0.0, 0.0, -0.5 );
  648.             drawFlower( yellow );
  649.         glPopMatrix();
  650.         glPushMatrix();
  651.             glTranslatef( -1.0, -1.0, 1.0 );
  652.             drawFlower( blue );
  653.             glTranslatef( 0.0, 0.0, -0.5 );
  654.             drawFlower( magenta );
  655.         glPopMatrix();
  656.  
  657.     glPopMatrix();
  658.  
  659.     checkError( "drawScene" );
  660.     glutSwapBuffers();
  661. }
  662.