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