home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl2 / examples / selection / selectSolar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  10.4 KB  |  401 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. /* selectSolar.c
  19.  *    Selection is demonstrated here. A simple solar system
  20.  *    is drawn first in render mode, then in selection mode with
  21.  *    a narrower perspective, selecting the center of the scene.
  22.  *    Names are assigned to the shapes, and if they score hits
  23.  *    within the selected region the selected names can be retrieved. 
  24.  *
  25.  *    SPACE key        - toggle selection mode 
  26.  *    <r> key            - toggle rotation on/off
  27.  *    Escape key        - exit the program
  28.  */
  29. #include <GL/gl.h>
  30. #include <GL/glu.h>
  31. #include <GL/glut.h>
  32.  
  33. #include <stdio.h>
  34. #include <math.h>
  35.  
  36. /* Function Prototypes */
  37.  
  38. GLvoid initgfx( GLvoid );
  39. GLvoid drawScene( GLvoid );
  40. GLvoid reshape( GLsizei, GLsizei );
  41. GLvoid keyboard( GLubyte, GLint, GLint );
  42. GLvoid animate( GLvoid );
  43. GLvoid visibility( int );
  44.  
  45. void updateViewVolume( GLdouble, GLdouble, GLdouble, GLdouble );
  46. void printHits( GLint, GLint, GLint, GLuint [] );
  47. void printHelp( char * );
  48.  
  49. /* Global Definitions */
  50.  
  51. #define KEY_ESC    27    /* ascii value for the escape key */
  52.  
  53. #define BUFSIZE 512    /* hit buffer size */
  54.  
  55. #define UNNAMED_OBJECT    (-1)    /* marks empty name stack */
  56.  
  57. /* Global Variables */
  58.  
  59. static GLdouble aspect;
  60.  
  61. static GLuint    viewVolumeList;
  62.  
  63. static GLboolean selectionFlag = GL_TRUE;
  64. static GLboolean rotateFlag = GL_TRUE;
  65.  
  66. static GLdouble depthNormalizeFactor, znear = 6.0, zfar = 14.0;
  67.  
  68. /* matrices and midpoint for gluUnProject */
  69. static GLdouble modelview[16], projection[16];
  70. static GLint     viewport[4], midX, midY;
  71.  
  72. /* objects to be drawn */
  73. static enum shapes { SUN, EARTH, MOON };
  74. static char *shapeNames[] =  { "Sun", "Earth", "Moon" };
  75.  
  76. static GLfloat year = 0;
  77.  
  78. void
  79. main( int argc, char **argv )
  80. {
  81.     GLsizei width, height;
  82.  
  83.     glutInit( &argc, argv );
  84.  
  85.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  86.     height = glutGet( GLUT_SCREEN_HEIGHT );
  87.     glutInitWindowPosition( width / 4, height / 4 );
  88.     glutInitWindowSize( (width / 2) - 4, height / 2 );
  89.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  90.     glutCreateWindow( argv[0] );
  91.  
  92.     initgfx();
  93.  
  94.     glutKeyboardFunc( keyboard );
  95.     glutReshapeFunc( reshape );
  96.     glutIdleFunc( animate ); 
  97.     glutVisibilityFunc( visibility ); 
  98.     glutDisplayFunc( drawScene ); 
  99.  
  100.     printHelp( argv[0] );
  101.  
  102.     glutMainLoop();
  103. }
  104.  
  105. GLvoid
  106. printHelp( char *progname )
  107. {
  108.     fprintf(stdout, "\n%s\nThis program demonstrates selection\n"
  109.         "SPACE key            - toggle selection mode \n"
  110.         "<r> key            - toggle rotation on/off \n"
  111.         "Escape key            - exit the program \n\n",
  112.         progname );
  113. }
  114.  
  115. void
  116. initgfx()
  117. {
  118.     GLfloat mat_specular[] = { 0.8, 0.8, 0.8, 1.0 };
  119.     GLfloat mat_shininess[] = { 10.0 };
  120.     GLfloat mat_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  121.  
  122.     glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  123.     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
  124.     glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  125.     glEnable( GL_LIGHTING );
  126.     glEnable( GL_LIGHT0 );
  127.  
  128.     glClearColor( 0, 0, 0, 1 );
  129.     glEnable( GL_DEPTH_TEST );
  130.  
  131.     viewVolumeList = glGenLists( 1 ); 
  132.  
  133.     /* depth values in hit record are in the range 0 to 2**32 - 1 */
  134.     depthNormalizeFactor = pow(2, 32) - 1;
  135. }
  136.  
  137. GLvoid 
  138. keyboard( GLubyte key, GLint x, GLint y )
  139. {
  140.  
  141.     switch (key) {
  142.     case ' ':     /* toggle selection when SPACE BAR is pressed */
  143.         selectionFlag = !selectionFlag;    
  144.         glutPostRedisplay();
  145.         break;
  146.         
  147.     case 'r':     /* toggle rotation on/off */
  148.         rotateFlag = !rotateFlag;    
  149.         if ( rotateFlag ) 
  150.             glutIdleFunc( animate ); 
  151.         else 
  152.             glutIdleFunc( NULL ); 
  153.         glutPostRedisplay();
  154.         break;
  155.  
  156.     case KEY_ESC:    /* Exit whenever the Escape key is pressed */
  157.         exit(0);
  158.     }
  159. }
  160.  
  161. GLvoid
  162. reshape( GLsizei width, GLsizei height )
  163. {
  164.     glViewport( 0, 0, width, height );
  165.  
  166.     aspect = (GLdouble) width / (GLdouble) height;
  167.  
  168.     glMatrixMode( GL_PROJECTION );
  169.     glLoadIdentity();
  170.     gluPerspective( 45.0, aspect, znear, zfar);
  171.     glMatrixMode( GL_MODELVIEW );
  172.     glLoadIdentity();
  173.  
  174.     glGetIntegerv( GL_VIEWPORT, viewport );
  175.     glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
  176.     glGetDoublev( GL_PROJECTION_MATRIX, projection );
  177.  
  178.     updateViewVolume( 15.0, aspect, znear+0.01, zfar-0.01 );  
  179. }
  180.  
  181. GLvoid
  182. animate( GLvoid )
  183. {
  184.     /* update the current year */
  185.     year = fmodf((year + 0.2), 360);
  186.  
  187.         /* Tell GLUT to redraw the scene */
  188.         glutPostRedisplay();
  189. }
  190.  
  191. GLvoid
  192. visibility( int state )
  193. {
  194.         if (state == GLUT_VISIBLE && rotateFlag) {
  195.                 glutIdleFunc( animate );
  196.         } else {
  197.                 glutIdleFunc( NULL );
  198.         }
  199. }
  200.  
  201. GLvoid
  202. drawSolar( GLboolean selecting )
  203. {
  204.     static GLfloat sun_diffuse[] = { 1.0, 1.0, 0.0, 1.0 };
  205.     static GLfloat sun_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  206.     static GLfloat no_specular[] = { 0.0, 0.0, 0.0, 1.0 };
  207.     static GLfloat earth_diffuse[] = { 0.0, 0.3, 1.0, 1.0 };
  208.     static GLfloat moon_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  209.     static GLfloat position[] = { 0.0, 0.0, 1.0, 0.0 };
  210.  
  211.     /* simulate local light centered at sun using an infinite light */
  212.     static GLfloat sun_position[] = { -1.0, 0.0, 0.0, 0.0 };
  213.  
  214.     glPushMatrix();
  215.         /* sun surface lit by light attached to eye */
  216.         glLightfv(GL_LIGHT0, GL_POSITION, position);
  217.  
  218.         /* viewing transformation */
  219.         glTranslatef(0.0, 0.0, -10.0);
  220.         glRotatef( 10.0, 1.0, 0.0, 0.0 );
  221.  
  222.         glPushMatrix();
  223.             glRotatef (90.0, 1.0, 0.0, 0.0);
  224.             glMaterialfv(GL_FRONT, GL_DIFFUSE, sun_diffuse);
  225.             glMaterialfv(GL_FRONT, GL_SPECULAR, sun_specular);
  226.             glLoadName(SUN);
  227.             glutSolidSphere(0.7, 15, 15);
  228.         glPopMatrix();
  229.         glPushMatrix();
  230.             glRotatef (year, 0.0, 1.0, 0.0);
  231.             glTranslatef (2.5, 0.0, 0.0);
  232.             glPushMatrix();
  233.                 /* infinite light looks like local light at 
  234.                  * sun because rotating in sync with planet */
  235.                 glLightfv(GL_LIGHT0, GL_POSITION, sun_position);
  236.                 glRotatef (90.0, 1.0, 0.0, 0.0);
  237.                 glMaterialfv(GL_FRONT, GL_SPECULAR, 
  238.                     no_specular);
  239.                 glMaterialfv(GL_FRONT, GL_DIFFUSE,
  240.                     earth_diffuse);
  241.                 glLoadName(EARTH);
  242.                 glutSolidSphere(0.5, 15, 15);
  243.             glPopMatrix();
  244.             glPushMatrix();
  245.                 glRotatef( fmodf((year*20.0), 360.0),
  246.                     0.0, 1.0, 0.0);
  247.                 glTranslatef (1.0, 0.0, 0.0);
  248.                 glRotatef (90.0, 1.0, 0.0, 0.0);
  249.                 glMaterialfv(GL_FRONT, GL_DIFFUSE,
  250.                     moon_diffuse);
  251.                 glPushName(MOON);
  252.                 glutSolidSphere(0.2, 15, 15);
  253.             glPopMatrix();
  254.         glPopMatrix();
  255.  
  256.     glPopMatrix();
  257.  
  258.     (selecting ? glFlush(): glutSwapBuffers());
  259. }
  260.  
  261. GLvoid  
  262. drawScene( GLvoid )
  263. {
  264.     GLuint selectBuf[BUFSIZE];
  265.     GLint hits;
  266.  
  267.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  268.  
  269.     /* draw selection viewing volume slightly inside 
  270.      * actual selection volume so that it is visible 
  271.      */
  272.     glDisable( GL_LIGHTING );
  273.     glCallList( viewVolumeList ); 
  274.     glEnable( GL_LIGHTING );
  275.  
  276.     drawSolar( GL_FALSE );
  277.     if ( selectionFlag ) {
  278.         glSelectBuffer (BUFSIZE, selectBuf);
  279.         (GLvoid) glRenderMode( GL_SELECT );
  280.         glInitNames();
  281.         glPushName( UNNAMED_OBJECT );
  282.  
  283.         glMatrixMode( GL_PROJECTION );
  284.         glPushMatrix();
  285.             glLoadIdentity();
  286.             /* set fovy much smaller than normal to select 
  287.              * only center of scene
  288.              */
  289.             gluPerspective( 15.0, aspect, znear, zfar );
  290.             glMatrixMode( GL_MODELVIEW );
  291.             drawSolar( GL_TRUE );
  292.     
  293.             hits = glRenderMode( GL_RENDER );
  294.             printHits( hits, midX, midY, selectBuf );    
  295.             glMatrixMode( GL_PROJECTION );
  296.         glPopMatrix();
  297.         glMatrixMode( GL_MODELVIEW );
  298.     }
  299. }
  300.  
  301. /* draw a perspective viewing volume indicating selected region */
  302. GLvoid 
  303. updateViewVolume( GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far )
  304. {
  305.     GLfloat halfFovyRadians;
  306.     GLfloat farLeft, farRight, farBottom, farTop;
  307.     GLfloat nearLeft, nearRight, nearBottom, nearTop;
  308.         
  309.     halfFovyRadians = (fovy/2.0) * (M_PI/180.0);
  310.     
  311.     farTop = far * tan( halfFovyRadians );
  312.     farBottom = -farTop;
  313.     farRight = aspect * farTop;
  314.     farLeft = -farRight;
  315.  
  316.     /* offset near clipping plane slightly inwards
  317.      * so that it will be visible.  */
  318.     nearTop = near * tan( halfFovyRadians ) - 0.03;
  319.     nearBottom = -nearTop;
  320.     nearRight = aspect * nearTop;
  321.     nearLeft = -nearRight;
  322.     
  323.     midX = nearLeft - nearRight;
  324.     midY = nearTop - nearBottom;
  325.  
  326.     glNewList( viewVolumeList, GL_COMPILE );
  327.     glColor3f (1.0, 0.0, 0.0);
  328.     /* draw far clipping plane */
  329.     glBegin( GL_LINE_LOOP );
  330.         glVertex3f (farLeft, farBottom, -far);
  331.         glVertex3f (farRight, farBottom, -far);
  332.         glVertex3f (farRight, farTop, -far);
  333.         glVertex3f (farLeft, farTop, -far);
  334.     glEnd();
  335.  
  336.     glColor3f( 1.0, 1.0, 0.0 );
  337.     /* draw near clipping plane */
  338.     glBegin( GL_LINE_LOOP );
  339.         glVertex3f (nearLeft, nearBottom, -near);
  340.         glVertex3f (nearRight, nearBottom, -near);
  341.         glVertex3f (nearRight, nearTop, -near);
  342.         glVertex3f (nearLeft, nearTop, -near);
  343.     glEnd();
  344.  
  345.     /* connect clipping planes */    
  346.     glBegin( GL_LINES );                    /* 4 lines */
  347.         glVertex3f (nearLeft, nearBottom, -near);
  348.         glVertex3f (farLeft, farBottom, -far);
  349.  
  350.         glVertex3f (nearRight, nearBottom, -near);
  351.         glVertex3f (farRight, farBottom, -far);
  352.  
  353.         glVertex3f (nearRight, nearTop, -near);
  354.         glVertex3f (farRight, farTop, -far);
  355.  
  356.         glVertex3f (nearLeft, nearTop, -near);
  357.         glVertex3f (farLeft, farTop, -far);
  358.     glEnd();
  359.     glEndList( );
  360. }
  361.  
  362. GLvoid 
  363. printHits (GLint hits, GLint winx, GLint winy, GLuint buffer[] )
  364. {
  365.     unsigned int i, j, nameCount;
  366.     GLuint *bufp;
  367.     GLdouble min_depth, max_depth, objx, objy, objz;
  368.     
  369.     printf ("hits = %d\n", hits);
  370.     bufp = (GLuint *) buffer;
  371.     for (i = 0; i < hits; i++) 
  372.     {    /*  for each hit  */
  373.         nameCount = *bufp; bufp++;
  374.         printf( " number of names for this hit = %d\n", 
  375.             nameCount ); 
  376.  
  377.         min_depth = ((GLdouble)(*bufp)/depthNormalizeFactor); bufp++;
  378.         gluUnProject( winx, winy, min_depth,
  379.                   modelview, projection, viewport, 
  380.                   &objx, &objy, &objz);
  381.         printf( " z1 = %f", objz );
  382.  
  383.         max_depth = ((GLdouble)(*bufp)/depthNormalizeFactor); bufp++;
  384.         gluUnProject( winx, winy, max_depth,
  385.                   modelview, projection, viewport, 
  386.                   &objx, &objy, &objz);
  387.         printf( " z2 = %f\n", objz );
  388.  
  389.         printf( " names are: " );
  390.         for ( j = 0; j < nameCount; j++, bufp++ ) 
  391.         {    /*  for each name */
  392.             if ((GLint) *bufp == UNNAMED_OBJECT ) {
  393.                 fprintf( stdout, "UNNAMED_OBJECT\n" );
  394.             } else {
  395.                 fprintf( stdout, "\t%s", shapeNames[*bufp] );
  396.             }
  397.         }
  398.         printf( "\n\n" );
  399.     }
  400. }
  401.