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