/* * 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. */ /* solar10.c - a simple solar system. * Added a reshape handler to reset the viewport and viewing volume. * Add depth buffering and back face culling. * Add continuous animation and an option to toggle it on and off. * Add a viewing transformation and control it using mouse input. * Enable lighting and give the sun, earth and moon material properties * Add two-sided lighting and a local light. * * F1 key - print help information * Left Mouse Button - change incidence and azimuth angles * Middle Mouse Button - change the twist angle based on * horizontal mouse movement * Right Mouse Button - zoom in and out based on vertical * mouse movement * Key - toggle rotation on / off * Key - reset viewpoint * SPACE Key - toggle between solid/wireframe models * Escape Key - exit program */ #include /* includes gl.h, glu.h */ #include #include #include "checkerror.h" /* Function Prototypes */ GLvoid initgfx( GLvoid ); GLvoid keyboard( GLubyte, GLint, GLint ); GLvoid specialkeys( GLint, GLint, GLint ); GLvoid animate( GLvoid ); GLvoid visibility( GLint ); GLvoid mouse( GLint, GLint, GLint, GLint ); GLvoid motion( GLint, GLint ); GLvoid reshape( GLsizei, GLsizei ); GLvoid drawScene( GLvoid ); void printHelp( char * ); void resetView( GLvoid ); void polarView( GLfloat, GLfloat, GLfloat, GLfloat); /* Global Variables */ static char *progname; static GLboolean filledFlag = GL_TRUE; enum actions { MOVE_EYE, TWIST_EYE, ZOOM, MOVE_NONE }; static GLint action; static GLdouble xStart = 0.0, yStart = 0.0; static GLfloat sunRadius = 0.7f; static GLfloat earthRadius = 0.4f, earthOrbit = 3.5f; static GLfloat moonRadius = 0.2f, moonOrbit = 1.0f; static GLfloat nearClip, farClip, distance, twistAngle, incAngle, azimAngle; static GLfloat year = 45.0f, day = -90.0f; /* Global Definitions */ #define KEY_ESC 27 /* ascii value for the escape key */ void main( int argc, char *argv[] ) { GLsizei width, height; glutInit( &argc, argv ); /* create a window that is 1/4 the size of the screen, * and position it in the middle of the screen. */ width = glutGet( GLUT_SCREEN_WIDTH ); height = glutGet( GLUT_SCREEN_HEIGHT ); glutInitWindowPosition( width / 4, height / 4 ); glutInitWindowSize( width / 2, height / 2 ); glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE ); glutCreateWindow( argv[0] ); initgfx(); glutIdleFunc( animate ); glutVisibilityFunc( visibility ); glutReshapeFunc( reshape ); glutKeyboardFunc( keyboard ); glutSpecialFunc( specialkeys ); glutMouseFunc( mouse ); glutMotionFunc( motion ); glutDisplayFunc( drawScene ); progname = argv[0]; printHelp( progname ); glutMainLoop(); } void printHelp( char *progname ) { fprintf(stdout, "\n%s - model the solar system\n\n" "F1 key - print help information\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 rotation on / off\n" " Key - reset viewpoint\n" "SPACE key - toggle between solid/wireframe mode\n" "Escape Key - exit the program\n\n", progname); } GLvoid initgfx( GLvoid ) { GLfloat maxOrbit; /* Set up properties for the light */ GLfloat sunSpecular[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat two_side = 1.0f; GLfloat lmodelAmbient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; /* set clear color to black */ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); /* enable the depth buffer */ glEnable( GL_DEPTH_TEST ); /* Maximum size of all the objects in your scene */ maxOrbit = earthOrbit + moonOrbit + moonRadius; /* Set up nearClip and farClip so that ( farClip - nearClip ) > maxObjectSize, */ /* and determine the viewing distance (adjust for zooming) */ nearClip = 1.0; farClip = nearClip + 8*maxOrbit; resetView(); /* Set the light properties */ glLightfv( GL_LIGHT0, GL_SPECULAR, sunSpecular ); glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, two_side ); glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodelAmbient ); /* Turn on the default light */ glEnable( GL_LIGHT0 ); /* Enable fast material changes for diffuse material */ glColorMaterial( GL_FRONT, GL_DIFFUSE ); } GLvoid reshape( GLsizei width, GLsizei height ) { GLdouble aspect; glViewport( 0, 0, width, height ); /* compute aspect ratio */ aspect = (GLdouble) width / (GLdouble) height; glMatrixMode( GL_PROJECTION ); /* Reset world coordinates first ... */ glLoadIdentity(); /* Reset the viewing volume based on the new aspect ratio */ gluPerspective( 45.0f, aspect, nearClip, farClip ); glMatrixMode( GL_MODELVIEW ); } GLvoid keyboard( GLubyte key, GLint x, GLint y ) { static GLboolean rotateFlag = GL_TRUE; switch (key) { case 'r': rotateFlag = !rotateFlag; if (rotateFlag) { glutIdleFunc( animate ); } else { glutIdleFunc( NULL ); } glutPostRedisplay(); break; case ' ': /* toggle fill mode */ filledFlag = !filledFlag; glutPostRedisplay(); break; case 'R': resetView(); glutPostRedisplay(); break; case KEY_ESC: /* Exit when the Escape key is pressed */ exit(0); } } GLvoid specialkeys( GLint key, GLint x, GLint y ) { switch (key) { case GLUT_KEY_F1: /* Function key #1 */ /* print help information */ printHelp( progname ); break; } } GLvoid animate( GLvoid ) { /* update the rotation of the earth and moon in their orbits */ year = fmod( (year + 0.5), 360.0f ); day = fmod( (day + 5.0), 360.0f ); /* Tell GLUT to redraw the scene */ glutPostRedisplay(); } GLvoid visibility( int state ) { if (state == GLUT_VISIBLE) { glutIdleFunc( animate ); } else { glutIdleFunc( NULL ); } } GLvoid mouse( GLint button, GLint state, GLint x, GLint y ) { 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 { 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: break; } /* Update the stored mouse position for later use */ xStart = x; yStart = y; glutPostRedisplay(); } void resetView( GLvoid ) { distance = nearClip + (farClip - nearClip) / 2.0; twistAngle = 0.0; /* rotation of viewing volume (camera) */ incAngle = 0.0; azimAngle = 0.0; } void polarView( GLfloat distance, GLfloat azimuth, GLfloat incidence, GLfloat twist) { glTranslatef( 0.0f, 0.0f, -distance); glRotatef( -twist, 0.0f, 0.0f, 1.0); glRotatef( -incidence, 1.0f, 0.0f, 0.0); glRotatef( -azimuth, 0.0f, 0.0f, 1.0); } GLvoid drawScene( GLvoid ) { static GLfloat yellow[] = { 1.0f, 1.0f, 0.0f, 1.0f }; static GLfloat blue[] = { 0.0f, 0.0f, 1.0f, 1.0f }; static GLfloat gray[] = { 0.4f, 0.4f, 0.4f, 1.0f }; static GLfloat moltenRed[] = { 1.0f, 0.1f, 0.05f, 1.0f }; static GLfloat noEmission[] = { 0.0f, 0.0f, 0.0f, 1.0f }; static GLfloat defaultDiffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; /* a local light */ static GLfloat lightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); /* set up viewing transformation */ polarView( distance, azimAngle, incAngle, twistAngle ); glColor3f( 1.0f, 1.0f, 0.0f ); glEnable( GL_LIGHTING ); glEnable( GL_COLOR_MATERIAL ); /* draw sun */ /* position the light at the same location as the sun, * so that the light emanates from it */ glLightfv( GL_LIGHT0, GL_POSITION, lightPosition ); /* Give the sun a yellow glow */ glMaterialfv( GL_FRONT, GL_EMISSION, yellow ); /* Set the inside of the sun to yellow */ glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow ); glPushMatrix(); /* rotate on our own axis */ glRotatef( 90.0f, 1.0f, 0.0f, 0.0f ); if (filledFlag) glutSolidSphere( sunRadius, 15, 15 ); else glutWireSphere( sunRadius, 15, 15 ); glPopMatrix(); /* turn emission off while drawing planets */ glMaterialfv( GL_FRONT, GL_EMISSION, noEmission ); /* set diffuse material for the earth */ glColor4fv( blue ); /* set material for the core */ glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, moltenRed ); glPushMatrix(); /* draw earth */ /* rotate to the right time of year */ glRotatef( year, 0.0f, 1.0f, 0.0f ); /* translate out to our orbit about the sun */ glTranslatef( earthOrbit, 0.0f, 0.0f ); glPushMatrix(); /* rotate on our own axis */ glRotatef( 90.0f, 1.0f, 0.0f, 0.0f ); if (filledFlag) glutSolidSphere( earthRadius, 15, 15 ); else glutWireSphere( earthRadius, 15, 15 ); glPopMatrix(); /* set diffuse material for the moon */ glColor4fv( gray ); /* set material for the core of the moon */ glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, gray ); /* draw moon */ glPushMatrix(); /* rotate to the right time of day */ glRotatef( day, 0.0f, 1.0f, 0.0f ); /* translate out to our orbit about the earth */ glTranslatef( moonOrbit, 0.0f, 0.0f ); /* rotate on our axis */ glRotatef( 90.0f, 1.0f, 0.0f, 0.0f ); if (filledFlag) glutSolidSphere( moonRadius, 15, 15 ); else glutWireSphere( moonRadius, 15, 15 ); glPopMatrix(); glPopMatrix(); glDisable( GL_COLOR_MATERIAL ); glDisable( GL_LIGHTING ); glPopMatrix(); checkError( "drawScene" ); glutSwapBuffers(); }