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 / solar12.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  13.8 KB  |  585 lines

  1. /*
  2.  * Copyright 1993, 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. /* solar12.c - a simple solar system.  
  19.  *    Added a reshape handler to reset the viewport and viewing volume.
  20.  *    Add depth buffering and back face culling.
  21.  *    Add a viewing transformation and control it using mouse input.
  22.  *    Enable lighting and give the sun, earth and moon material properties
  23.  *     Add continuous animation and a menu to control it.
  24.  *    Add two-sided lighting and a local light.
  25.  *    Add text.
  26.  *
  27.  *    F1 key            - print help information
  28.  *    Left Mouse Button    - change incidence and azimuth angles
  29.  *    Middle Mouse Button    - change the twist angle based on
  30.  *                  horizontal mouse movement
  31.  *    Right Mouse Button    - zoom in and out based on vertical
  32.  *                  mouse movement
  33.  *    <r> Key            - toggle rotation on / off
  34.  *    <R> Key            - reset viewpoint
  35.  *    SPACE Key        - toggle between solid/wireframe models
  36.  *    Escape Key        - exit program
  37.  */
  38. #include <GL/gl.h>
  39. #include <GL/glu.h>
  40. #include <GL/glut.h>
  41.  
  42. #include <stdio.h>
  43. #include <math.h>
  44.  
  45. /* Function Prototypes */
  46.  
  47. GLvoid initgfx( GLvoid );
  48. GLvoid keyboard( GLubyte, GLint, GLint );
  49. GLvoid specialkeys( GLint, GLint, GLint );
  50. GLvoid mouse( GLint, GLint, GLint, GLint );
  51. GLvoid motion( GLint, GLint );
  52. GLvoid animate( GLvoid );
  53. GLvoid visibility( GLint );
  54. GLvoid reshape( GLsizei, GLsizei );
  55. GLvoid drawScene( GLvoid );
  56.  
  57. void checkError( char * );
  58. void printHelp( char * );
  59.  
  60. void resetView( GLvoid );
  61. void polarView( GLfloat, GLfloat, GLfloat, GLfloat);
  62.  
  63. /* Global Variables */
  64.  
  65. static char *progname; 
  66.  
  67. static GLboolean filledFlag = GL_TRUE;
  68.  
  69. static enum        actions { MOVE_EYE, TWIST_EYE, ZOOM, MOVE_NONE };
  70. static GLint        action;
  71.  
  72. static GLdouble        xStart = 0.0, yStart = 0.0;
  73.  
  74. static GLfloat        sunRadius = 0.7;
  75. static GLfloat        earthRadius = 0.4, earthOrbit = 3.5; 
  76. static GLfloat        moonRadius = 0.2, moonOrbit = 1.0;
  77. static GLfloat         near, far, distance, twistAngle, incAngle, azimAngle;
  78.  
  79. static GLfloat        year = 45.0, day = -90.0;
  80.  
  81. static void           *fixedFont, *strokeFont;
  82.  
  83. /* Global Definitions */
  84.  
  85. #define KEY_ESC    27    /* ascii value for the escape key */
  86.  
  87. void
  88. main( int argc, char *argv[] )
  89. {
  90.     GLsizei width, height;
  91.  
  92.     glutInit( &argc, argv );
  93.  
  94.     /* create a window that is 1/4 the size of the screen,
  95.      * and position it in the middle of the screen.
  96.      */
  97.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  98.     height = glutGet( GLUT_SCREEN_HEIGHT );
  99.     glutInitWindowPosition( width / 4, height / 4 );
  100.     glutInitWindowSize( width / 2, height / 2 );
  101.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  102.     glutCreateWindow( argv[0] );
  103.  
  104.     initgfx();
  105.  
  106.     glutIdleFunc( animate );
  107.     glutVisibilityFunc( visibility );
  108.     glutReshapeFunc( reshape );
  109.     glutKeyboardFunc( keyboard );
  110.     glutSpecialFunc( specialkeys );
  111.     glutMouseFunc( mouse );
  112.     glutMotionFunc( motion );
  113.     glutDisplayFunc( drawScene ); 
  114.  
  115.     progname = argv[0];
  116.  
  117.     printHelp( progname );
  118.  
  119.     glutMainLoop();
  120. }
  121.  
  122. void
  123. printHelp( char *progname )
  124. {
  125.     fprintf(stdout, 
  126.         "\n%s - model some objects\n\n"
  127.         "F1 key        - print help information\n"
  128.         "Left Mousebutton    - move eye position\n"
  129.         "Middle Mousebutton    - change twist angle\n"
  130.         "Right Mousebutton    - move up / down to zoom in / out\n"
  131.         "<r> Key        - toggle rotation on / off\n"
  132.         "<R> Key        - reset viewpoint\n"
  133.         "SPACE key    - toggle between solid/wireframe mode\n"
  134.         "Escape Key    - exit the program\n\n",
  135.         progname);
  136. }
  137.  
  138. GLvoid
  139. initgfx( GLvoid )
  140. {
  141.     GLfloat maxOrbit;
  142.  
  143.     /* Set up properties for the light */
  144.     GLfloat    sunSpecular[] = { 0.0, 0.0, 0.0, 1.0 };
  145.  
  146.     GLfloat    two_side = 1.0;
  147.  
  148.     GLfloat    lmodelAmbient[] = { 0.8, 0.8, 0.8, 1.0 };
  149.  
  150.     /* set clear color to black */
  151.     glClearColor( 0.0, 0.0, 0.0, 1.0 );
  152.  
  153.     /* enable the depth buffer */
  154.     glEnable( GL_DEPTH_TEST );
  155.  
  156.     /* Maximum size of all the objects in your scene */
  157.     maxOrbit = earthOrbit + moonOrbit + moonRadius;
  158.  
  159.     /* Set up near and far so that ( far - near ) > maxObjectSize, */
  160.     /* and determine the viewing distance (adjust for zooming) */
  161.     near = 1.0;
  162.     far = near + 8*maxOrbit; 
  163.  
  164.     resetView();
  165.  
  166.     /* Set the light properties */
  167.     glLightfv( GL_LIGHT0, GL_SPECULAR, sunSpecular );
  168.  
  169.     glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, two_side );
  170.     glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodelAmbient );
  171.  
  172.     /* Turn on the default light */
  173.     glEnable( GL_LIGHT0 );
  174.  
  175.     /* Enable fast material changes for diffuse material */
  176.     glColorMaterial( GL_FRONT, GL_DIFFUSE );
  177.  
  178.     /* Set up two fonts to use for rendering */
  179.     fixedFont = GLUT_BITMAP_9_BY_15;
  180.     strokeFont = GLUT_STROKE_ROMAN;
  181. }
  182.  
  183. GLvoid 
  184. reshape( GLsizei width, GLsizei height )
  185. {
  186.     GLdouble    aspect;
  187.  
  188.     glViewport( 0, 0, width, height );
  189.  
  190.     /* compute aspect ratio */
  191.     aspect = (GLdouble) width / (GLdouble) height;
  192.  
  193.     glMatrixMode( GL_PROJECTION );
  194.  
  195.     /* Reset world coordinates first ... */
  196.     glLoadIdentity();
  197.  
  198.     /* Reset the viewing volume based on the new aspect ratio */
  199.     gluPerspective( 45.0, aspect, near, far );
  200.  
  201.     glMatrixMode( GL_MODELVIEW );
  202. }
  203.  
  204. void 
  205. checkError( char *label )
  206. {
  207.     GLenum error;
  208.     while ( (error = glGetError()) != GL_NO_ERROR )
  209.         printf( "%s: %s\n", label, gluErrorString(error) );
  210. }
  211.  
  212. GLvoid 
  213. keyboard( GLubyte key, GLint x, GLint y )
  214. {
  215.     static GLboolean    rotateFlag = GL_TRUE;
  216.  
  217.     switch (key) {
  218.     case 'r':
  219.         rotateFlag = !rotateFlag;
  220.         if (rotateFlag) {
  221.             glutIdleFunc( animate );
  222.         } else {
  223.             glutIdleFunc( NULL );
  224.         }
  225.         glutPostRedisplay();
  226.         break;
  227.     case ' ':    /* toggle fill mode */
  228.         filledFlag = !filledFlag;
  229.         glutPostRedisplay();
  230.         break;
  231.     case 'R':
  232.         resetView();
  233.         glutPostRedisplay();
  234.         break;
  235.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  236.         exit(0);
  237.     }
  238. }
  239.  
  240. GLvoid 
  241. specialkeys( GLint key, GLint x, GLint y )
  242. {
  243.     switch (key) {
  244.     case GLUT_KEY_F1:    /* Function key #1 */
  245.         /* print help information */
  246.         printHelp( progname );
  247.         break;
  248.     }
  249. }
  250.  
  251. GLvoid 
  252. mouse( GLint button, GLint state, GLint x, GLint y )
  253. {
  254.     if (state == GLUT_DOWN) {
  255.         switch (button) {
  256.         case GLUT_LEFT_BUTTON:
  257.             action = MOVE_EYE;
  258.             break;
  259.         case GLUT_MIDDLE_BUTTON:
  260.             action = TWIST_EYE;
  261.             break;
  262.         case GLUT_RIGHT_BUTTON:
  263.             action = ZOOM;
  264.             break;
  265.         }
  266.  
  267.         /* Update the saved mouse position */
  268.         xStart = x;
  269.         yStart = y;
  270.     } else {
  271.         action = MOVE_NONE;
  272.     }
  273.  
  274. }
  275.  
  276. GLvoid
  277. motion( GLint x, GLint y )
  278. {
  279.     switch (action) {
  280.     case MOVE_EYE:
  281.         /* Adjust the eye position based on the mouse position */
  282.         azimAngle += (GLdouble) (x - xStart);
  283.         incAngle -= (GLdouble) (y - yStart);
  284.         break;
  285.     case TWIST_EYE:
  286.         /* Adjust the eye twist based on the mouse position */
  287.         twistAngle = fmodf(twistAngle+(x - xStart), 360.0);
  288.         break;
  289.     case ZOOM:
  290.         /* Adjust the eye distance based on the mouse position */
  291.         distance -= (GLdouble) (y - yStart)/10.0;
  292.         break;
  293.     default:
  294.         printf("unknown action %d\n", action);
  295.     }
  296.     
  297.     /* Update the stored mouse position for later use */
  298.     xStart = x;
  299.     yStart = y;
  300.  
  301.     glutPostRedisplay();
  302. }
  303.  
  304. GLvoid 
  305. animate( GLvoid )
  306. {
  307.     /* update the rotation of the earth and moon in their orbits */
  308.     year = fmodf( (year + 0.5), 360.0 );
  309.     day = fmodf( (day + 5.0), 360.0 );
  310.  
  311.     /* Tell GLUT to redraw the scene */
  312.     glutPostRedisplay();
  313. }
  314.  
  315. GLvoid
  316. visibility( int state ) 
  317. {
  318.     if (state == GLUT_VISIBLE) {
  319.         glutIdleFunc( animate );
  320.     } else {
  321.         glutIdleFunc( NULL );
  322.     }
  323. }
  324.  
  325. void
  326. resetView( GLvoid )
  327. {
  328.     distance = near + (far - near) / 2.0;
  329.     twistAngle = 0.0;    /* rotation of viewing volume (camera) */
  330.     incAngle = 0.0;
  331.     azimAngle = 0.0;
  332. }
  333.  
  334. void
  335. polarView( GLfloat distance, GLfloat azimuth, GLfloat incidence,
  336.             GLfloat twist)
  337. {
  338.     glTranslatef( 0.0, 0.0, -distance);
  339.     glRotatef( -twist, 0.0, 0.0, 1.0);
  340.     glRotatef( -incidence, 1.0, 0.0, 0.0);
  341.     glRotatef( -azimuth, 0.0, 0.0, 1.0);
  342. }
  343.  
  344. GLvoid
  345. renderBitmapString( void *font, char *string )
  346. {
  347.         int i;
  348.         int len = (int) strlen(string);
  349.         for (i = 0; i < len; i++) {
  350.                 glutBitmapCharacter(font, string[i]);
  351.         }
  352. }
  353.  
  354. GLvoid
  355. renderStrokeString( void *font, char *string )
  356. {
  357.         int i;
  358.         int len = (int) strlen(string);
  359.         for (i = 0; i < len; i++) {
  360.                 glutStrokeCharacter(font, string[i]);
  361.         }
  362. }
  363.  
  364. /* print mouse and keyboard input commands */
  365. GLvoid
  366. printInputCommands( void *font )
  367. {
  368.     static char *lmouse = "left mouse - change incidence & azimuth";
  369.     static char *mmouse = "middle mouse - change twist";
  370.     static char *rmouse = "right mouse - zoom in and out";
  371.     static char *Rkey = "R key - reset view";
  372.  
  373.     GLfloat yoffset;
  374.     GLsizei winHeight = glutGet(GLUT_WINDOW_HEIGHT);
  375.  
  376.     yoffset = winHeight-15.0;
  377.     glRasterPos3f( 10.0, yoffset, 0.0 );
  378.     renderBitmapString( font, lmouse );
  379.  
  380.     yoffset -= 20.0;
  381.     glRasterPos3f( 10.0, yoffset, 0.0 );
  382.     renderBitmapString( font, mmouse );
  383.  
  384.     yoffset -= 20.0;
  385.     glRasterPos3f( 10.0, yoffset, 0.0 );
  386.     renderBitmapString( font, rmouse );
  387.  
  388.     yoffset -= 20.0;
  389.     glRasterPos3f( 10.0, yoffset, 0.0 );
  390.     renderBitmapString( font, Rkey );
  391. }
  392.  
  393. /* update status of polarView parameters */
  394. GLvoid
  395. printStatus( void *font ) 
  396. {
  397.     static char s[50];
  398.     GLfloat yoffset = 65.0;
  399.  
  400.     /* update polarview information */
  401.     glRasterPos3f( 10.0, yoffset, 0.0 ); 
  402.     sprintf (s, "incidence is %4d", (GLint) incAngle);
  403.     renderBitmapString( font, s );
  404.  
  405.     yoffset -= 20.0;
  406.     glRasterPos3f( 10.0, yoffset, 0.0 );
  407.     sprintf (s, "azimuth is %4d", (GLint) azimAngle);
  408.     renderBitmapString( font, s );
  409.  
  410.     yoffset -= 20.0;
  411.     glRasterPos3f( 10.0, yoffset, 0.0 );
  412.     sprintf (s, "Twist is %4d", (GLint) twistAngle);
  413.     renderBitmapString( font, s );
  414. }
  415.  
  416. GLvoid
  417. renderStationaryText( void *font )
  418. {
  419.     GLsizei winWidth, winHeight;
  420.  
  421.     winWidth = glutGet(GLUT_WINDOW_WIDTH); 
  422.     winHeight = glutGet(GLUT_WINDOW_HEIGHT);
  423.  
  424.     /* Turn off the depth buffer */
  425.     glDisable( GL_DEPTH_TEST );
  426.  
  427.     /* save and then clear modelview matrix */
  428.     glPushMatrix(); 
  429.     glLoadIdentity(); 
  430.  
  431.     /* save Projection matrix */
  432.     glMatrixMode( GL_PROJECTION );
  433.     glPushMatrix();
  434.         /* reset world space to display status */
  435.         glLoadIdentity();
  436.         glOrtho( 0.0, winWidth, 0.0, winHeight, -1.0, 1.0 );
  437.  
  438.         printInputCommands( font );
  439.         printStatus( font );
  440.  
  441.     /* restore projection matrix */
  442.     glPopMatrix();
  443.  
  444.     /* restore previous modelview transformations */
  445.     glMatrixMode( GL_MODELVIEW );
  446.     glPopMatrix();
  447.  
  448.     /* Turn on the depth buffer */
  449.     glEnable( GL_DEPTH_TEST );
  450. }
  451.  
  452. GLvoid
  453. drawScene( GLvoid )
  454. {
  455.     static GLfloat  yellow[] = { 1.0, 1.0, 0.0, 1.0 };
  456.     static GLfloat  blue[] = { 0.0, 0.0, 1.0, 1.0 };
  457.     static GLfloat  gray[] = { 0.4, 0.4, 0.4, 1.0 };
  458.     static GLfloat  moltenRed[] = { 1.0, 0.1, 0.05, 1.0 };
  459.  
  460.     static GLfloat  noEmission[] = { 0.0, 0.0, 0.0, 1.0 };
  461.     static GLfloat  defaultDiffuse[] = { 0.8, 0.8, 0.8, 1.0 };
  462.  
  463.     /* a local light */
  464.     static GLfloat  lightPosition[] = { 0.0, 0.0, 0.0, 1.0 };
  465.  
  466.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  467.  
  468.     glPushMatrix();
  469.  
  470.         /* set up viewing transformation */
  471.         polarView( distance, azimAngle, incAngle, twistAngle );
  472.  
  473.         /* draw sun */
  474.  
  475.         /* position the light at the same location as the sun,
  476.          * so that the light emanates from it */
  477.         glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
  478.  
  479.         /* use the same color for the labels as for the planets */
  480.         glColor3f( 1.0, 1.0, 0.0 );
  481.         glPushMatrix();
  482.             glTranslatef(0.0, sunRadius+0.1, 0.0);
  483.             glScalef( 0.003, 0.003, 0.003 );
  484.             renderStrokeString(strokeFont, "sun");
  485.         glPopMatrix();
  486.  
  487.         glEnable( GL_LIGHTING );
  488.         glEnable( GL_COLOR_MATERIAL );
  489.  
  490.         /* Give the sun a yellow glow */
  491.         glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, yellow );
  492.  
  493.         glPushMatrix();
  494.             /* rotate on our own axis */
  495.             glRotatef( 90.0, 1.0, 0.0, 0.0 );
  496.             if (filledFlag)
  497.                 glutSolidSphere( sunRadius, 15, 15 );
  498.             else
  499.                 glutWireSphere( sunRadius, 15, 15 );
  500.         glPopMatrix();
  501.  
  502.         /* turn emmission off while drawing planets */
  503.         glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, noEmission );
  504.  
  505.         /* set material for the earth */
  506.         glColor4fv( blue );
  507.  
  508.         /* set material for the core */
  509.         glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, 
  510.                 moltenRed );
  511.  
  512.         glPushMatrix();
  513.  
  514.             /* draw earth */
  515.  
  516.             /* rotate to the right time of year */
  517.             glRotatef( year, 0.0, 1.0, 0.0 );
  518.  
  519.             /* translate out to our orbit about the sun */
  520.             glTranslatef( earthOrbit, 0.0, 0.0 );
  521.  
  522.             glDisable( GL_LIGHTING );
  523.             glPushMatrix();
  524.                 glTranslatef(0.0, earthRadius+0.1, 0.0);
  525.                 glRotatef(360-year, 0.0, 1.0, 0.0);
  526.                 glScalef( 0.003, 0.003, 0.003 );
  527.                 renderStrokeString(strokeFont, "earth");
  528.             glPopMatrix();
  529.             glEnable( GL_LIGHTING );
  530.  
  531.             glPushMatrix();
  532.                 /* rotate on our own axis */
  533.                 glRotatef( 90.0, 1.0, 0.0, 0.0 );
  534.                 if (filledFlag)
  535.                     glutSolidSphere( earthRadius, 15, 15 );
  536.                 else
  537.                     glutWireSphere( earthRadius, 15, 15 );
  538.             glPopMatrix();
  539.  
  540.             /* set material for the moon */
  541.             glColor4fv( gray );
  542.  
  543.             /* set material for the core of the moon */
  544.             glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, gray );
  545.  
  546.             /* draw moon */
  547.             glPushMatrix();
  548.                 /* rotate to the right time of day */
  549.                 glRotatef( day, 0.0, 1.0, 0.0 );
  550.  
  551.                 /* translate out to our orbit about the earth */
  552.                 glTranslatef( moonOrbit, 0.0, 0.0 );
  553.  
  554.                 glDisable( GL_LIGHTING );
  555.                 glPushMatrix();
  556.                     glTranslatef(0.0, moonRadius+0.1, 0.0);
  557.                     glRotatef(360-year-day, 0.0, 1.0, 0.0);
  558.                     glScalef( 0.003, 0.003, 0.003 );
  559.                     renderStrokeString(strokeFont, "moon");
  560.                 glPopMatrix();
  561.                 glEnable( GL_LIGHTING );
  562.  
  563.                 /* rotate on our axis */
  564.                 glRotatef( 90.0, 1.0, 0.0, 0.0 );
  565.                 if (filledFlag)
  566.                     glutSolidSphere( moonRadius, 15, 15 );
  567.                 else
  568.                     glutWireSphere( moonRadius, 15, 15 );
  569.  
  570.             glPopMatrix();
  571.         glPopMatrix();
  572.  
  573.         glDisable( GL_COLOR_MATERIAL );
  574.         glDisable( GL_LIGHTING );
  575.  
  576.     glPopMatrix();
  577.  
  578.     glColor3f( 1.0, 1.0, 0.0 );
  579.     renderStationaryText( fixedFont );
  580.  
  581.     checkError( "drawScene" );
  582.  
  583.     glutSwapBuffers();
  584. }
  585.