/* * Copyright (c) 1996-1999 Silicon Graphics, Inc. All rights reserved. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* movingLight.c - Set up a light that moves independent * of the objects in the scene. * * Left Mouse Button - change incidence and azimuth angles * Middle Mousebutton - change the twist angle based on * horizontal mouse movement * Right Mousebutton - zoom in and out based on vertical * mouse movement * key - toggle light animation * key - toggle local/infinite viewer * Escape key - exit the program */ #include /* includes gl.h, glu.h */ #include #include #include "axes.h" /* Function Prototypes */ GLvoid initgfx( GLvoid ); GLvoid animate( GLvoid ); GLvoid visibility( GLint ); GLvoid drawScene( GLvoid ); GLvoid reshape( GLsizei, GLsizei ); GLvoid keyboard( GLubyte, GLint, GLint ); GLvoid mouse( GLint, GLint, GLint, GLint ); GLvoid motion( GLint, GLint ); void resetView( GLvoid ); void polarView( GLfloat, GLfloat, GLfloat, GLfloat ); void printHelp( char * ); /* Global Definitions */ #define KEY_ESC 27 /* ascii value for the escape key */ /* Global Variables */ static GLfloat lightAngle = 0.0f; /* controls light rotation */ static GLboolean animateLight = GL_TRUE; static GLboolean localLight = GL_FALSE; enum actions { MOVE_EYE, TWIST_EYE, ZOOM, MOVE_NONE }; static GLint action; static GLdouble xStart = 0.0, yStart = 0.0; static GLfloat fovy, nearClip, farClip, distance, twistAngle, incAngle, azimAngle; void main( int argc, char *argv[] ) { GLsizei width, height; glutInit( &argc, argv ); width = glutGet( GLUT_SCREEN_WIDTH ); height = glutGet( GLUT_SCREEN_HEIGHT ); glutInitWindowPosition( width / 4, height / 4 ); glutInitWindowSize( (width / 2) - 4, height / 2 ); glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE ); glutCreateWindow( argv[0] ); initgfx(); glutIdleFunc( animate ); glutVisibilityFunc( visibility ); glutMouseFunc( mouse ); glutMotionFunc( motion ); glutKeyboardFunc( keyboard ); glutReshapeFunc( reshape ); glutDisplayFunc( drawScene ); printHelp( argv[0] ); glutMainLoop(); } void printHelp( char *progname ) { fprintf(stdout, "\n%s - demonstrate how to add a moving light\n\n" "Left Mousebutton - move eye position\n" "Middle Mousebutton - change twist angle\n" "Right Mousebutton - move up / down to zoom in / out\n" " Key - toggle light animation\n" " Key - toggle local/infinite viewer\n" "Escape Key - exit the program\n\n", progname); } GLvoid initgfx( GLvoid ) { glClearColor( 0.0, 0.0, 0.0, 1.0 ); glEnable( GL_DEPTH_TEST ); nearClip = 2.0f; /* Near clipping plane location */ farClip = 15.0f; /* Far clipping plane location */ resetView(); /* Turn on a default light */ glEnable( GL_LIGHT0 ); } GLvoid keyboard( GLubyte key, GLint x, GLint y ) { GLfloat infinite[] = {0.0f}; GLfloat local[] = {1.0f}; switch (key) { case 'a': /* toggle light animation */ animateLight = !animateLight; if ( animateLight ) glutIdleFunc(animate); else glutIdleFunc(NULL); glutPostRedisplay(); break; case 'm': /* toggle lighting model */ localLight = !localLight; if ( localLight ) { glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local); printf("local viewer ON\n"); } else { glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, infinite); printf("local viewer OFF\n"); } glutPostRedisplay(); break; case KEY_ESC: /* Exit when the Escape key is pressed */ exit(0); } } GLvoid mouse( GLint button, GLint state, GLint x, GLint y ) { static GLint buttons_down = 0; if (state == GLUT_DOWN) { switch (button) { case GLUT_LEFT_BUTTON: action = MOVE_EYE; break; case GLUT_MIDDLE_BUTTON: action = TWIST_EYE; break; case GLUT_RIGHT_BUTTON: action = ZOOM; break; } /* Update the saved mouse position */ xStart = x; yStart = y; } else { if (--buttons_down == 0) action = MOVE_NONE; } } GLvoid motion( GLint x, GLint y ) { switch (action) { case MOVE_EYE: /* Adjust the eye position based on the mouse position */ azimAngle += (GLdouble) (x - xStart); incAngle -= (GLdouble) (y - yStart); break; case TWIST_EYE: /* Adjust the eye twist based on the mouse position */ twistAngle = fmod(twistAngle+(x - xStart), 360.0); break; case ZOOM: /* Adjust the eye distance based on the mouse position */ distance -= (GLdouble) (y - yStart)/10.0; break; default: printf("unknown action %d\n", action); } /* Update the stored mouse position for later use */ xStart = x; yStart = y; glutPostRedisplay(); } void resetView( GLvoid ) { distance = nearClip + (farClip - nearClip) / 2.0f; twistAngle = 0.0f; /* rotation of viewing volume (camera) */ incAngle = 60.0f; azimAngle = 0.0f; fovy = 60.0f; /* Field of view in Y angle */ } GLvoid reshape( GLsizei width, GLsizei height ) { GLdouble aspect; glViewport( 0, 0, width, height ); aspect = (GLdouble) width / (GLdouble) height; glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( fovy, aspect, nearClip, farClip ); glMatrixMode( GL_MODELVIEW ); } GLvoid animate( GLvoid ) { /* update the rotation of the light for each scene */ lightAngle = fmod( (lightAngle + 2.0), 360.0 ); /* Tell GLUT to redraw the scene */ glutPostRedisplay(); } GLvoid visibility( int state ) { if (state == GLUT_VISIBLE && animateLight) { glutIdleFunc( animate ); } else { glutIdleFunc( NULL ); } } void polarView( GLfloat distance, GLfloat azimuth, GLfloat incidence, GLfloat twist) { glTranslatef( 0.0f, 0.0f, -distance); glRotatef( -twist, 0.0f, 0.0f, 1.0f); glRotatef( -incidence, 1.0f, 0.0f, 0.0f); glRotatef( -azimuth, 0.0f, 0.0f, 1.0f); } GLvoid drawScene( GLvoid ) { /* Define a few materials properties */ GLfloat redAmbient[] = { 0.3f, 0.1f, 0.1f, 1.0f }; GLfloat redDiffuse[] = { 1.0f, 0.0f, 0.0f, 1.0f }; GLfloat blueAmbient[] = { 0.1f, 0.1f, 0.3f, 1.0f }; GLfloat blueDiffuse[] = { 0.0f, 0.0f, 1.0f, 1.0f }; GLfloat defaultEmission[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat whiteSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat greenSpecular[] = { 0.0f, 1.0f, 0.0f, 1.0f }; GLfloat defaultSpecular[] = { 0.0f, 0.0f, 0.0f, 1.0f }; /* local light */ GLfloat lightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); polarView( distance, azimAngle, incAngle, twistAngle ); XYZaxes(); /* Animate the light with its own set of transformations */ glPushMatrix(); glRotatef( lightAngle, 0.0f, 1.0f, 1.0f ); glTranslatef( 2.7f, 0.0f, 0.0f ); /* By giving the light position its own modeling * transformations (due to the glPushMatrix() * and glPopMatrix() calls), the light moves * independently of the objects in the scene. */ glLightfv( GL_LIGHT0, GL_POSITION, lightPosition ); /* draw a small (unlit) white sphere to * represent the light in our scene. */ glColor3f( 1.0f, 1.0f, 1.0f ); glutSolidSphere( 0.07, 4, 7); glPopMatrix(); glEnable( GL_LIGHTING ); glMaterialfv( GL_FRONT, GL_EMISSION, defaultEmission ); /* Set properties for a shiny red material, * with a green highlight */ glMaterialfv( GL_FRONT, GL_AMBIENT, redAmbient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, redDiffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, greenSpecular ); glMaterialf( GL_FRONT, GL_SHININESS, 128.0f ); glPushMatrix(); glTranslatef( -2.0f, 1.5f, 0.0f ); glutSolidSphere( 0.7, 31, 31 ); glPopMatrix(); glPushMatrix(); glTranslatef( 1.0f, 2.0f, 2.0f ); glutSolidSphere( 0.9, 31, 31 ); glPopMatrix(); /* Set properties for a dull blue material with * a small white highlight */ glMaterialfv( GL_FRONT, GL_AMBIENT, blueAmbient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, blueDiffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, whiteSpecular ); glMaterialf( GL_FRONT, GL_SHININESS, 20.0f ); /* not very shiny */ glPushMatrix(); glTranslatef( 2.5f, 0.0f, 0.0f ); glutSolidTorus( 0.25, 0.75, 16, 31 ); glPopMatrix(); glDisable( GL_LIGHTING ); glPopMatrix(); glutSwapBuffers(); }