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 / labs / fly / flyutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  10.8 KB  |  492 lines

  1. /* Copyright (c) Silicon Graphics, Inc. 1996 */
  2.  
  3. /*
  4.  *  flyutil.c 
  5.  *  This file contains utility routines used by the fly program.
  6.  *
  7.  *  Copyright 1991, 1992, 1993, Silicon Graphics,  Inc.
  8.  *  Technical Education R & D
  9.  */
  10.  
  11. #include <GL/gl.h>
  12. #include <GL/glu.h>
  13. #include <GL/glut.h>
  14.  
  15. #include "fly.h"
  16. #include "fonts.h"
  17.  
  18. /* Global Variables */
  19.  
  20. static GLfloat     floorPoints[FLOORPOINTS+1][FLOORPOINTS+1][3] = { 0 };
  21. static GLfloat     floorNormals[FLOORPOINTS+1][FLOORPOINTS+1][3] = { 0 };
  22.  
  23. extern enum drawStyles { LIT_SMOOTH, LIT_FLAT, WIRE };
  24.  
  25. GLint drawStyle = LIT_SMOOTH;
  26.  
  27. GLboolean   drawNormalsFlag = GL_FALSE;
  28.  
  29. /* initial characteristics of the eye */
  30. static GLint     direction = FORWARD;    /* FORWARD or BACKWARD */
  31.  
  32. static GLsizei     winWidth, winHeight;
  33.  
  34. GLboolean debugFlag = GL_FALSE;        /* print eye position info? */
  35. GLboolean blendFlag = GL_FALSE;
  36. GLboolean lighting = GL_TRUE;
  37. GLboolean showGridFlag = GL_FALSE;
  38.  
  39. static GLboolean autopilot = GL_FALSE;    /* is autopilot mode on? */
  40. static GLboolean moving = GL_FALSE;
  41.  
  42. static GLint xPos, yPos;    /* mouse position */
  43.  
  44. GLfloat ex, ey, ez;        /* eye position */
  45. GLfloat dx,dy,dz;        /* change in eye position */
  46.  
  47. GLfloat yaw;            /* eye rotation about y axis in degrees */
  48. GLfloat pitch;            /* eye rotation about x axis in degrees */        
  49. GLfloat velocity = 0.15;    /* eye velocity */
  50. GLfloat turn_rate = 3.0;    /* eye turning agility */
  51.  
  52. GLdouble znear = 5.0, zfar = 50.0;
  53.  
  54. GLboolean resetauto = GL_TRUE;    /* first autopilot since reset? */
  55.  
  56. GLvoid
  57. initEye(GLvoid)
  58. {
  59.     /* initial position of the eye in the world */
  60.     ex = 20.0;
  61.     ey = 10.0;
  62.     ez = 20.0;
  63.  
  64.     yaw = -45.0;        /* rotation around eye y axis in degrees */
  65.     pitch = 20.0;        /* rotation around eye x axis in degrees */
  66.     autopilot = GL_FALSE;
  67.     resetauto = GL_TRUE;
  68.     moving = GL_FALSE;
  69. }
  70.  
  71. /* Define user input functions */
  72. GLvoid  
  73. toggleDrawNormals( GLvoid )
  74. {
  75.     drawNormalsFlag = !drawNormalsFlag;
  76. }
  77.  
  78. GLvoid
  79. toggleShowGrid( GLvoid )
  80. {
  81.     showGridFlag = !showGridFlag;
  82. }
  83.  
  84. GLvoid
  85. setDebug( GLvoid )
  86. {
  87.     debugFlag = !debugFlag;
  88. }
  89.  
  90. GLvoid
  91. toggleBlend( GLvoid )
  92. {
  93.     blendFlag = !blendFlag;
  94.     fprintf( stdout, "blendFlag = %d\n", blendFlag );
  95.     if ( !blendFlag )
  96.         disableBlending();
  97. }
  98.  
  99. GLvoid 
  100. enableBlending( GLvoid )
  101. {
  102.     glEnable( GL_BLEND );
  103.     /* disable writing to the depth buffer so that transparent
  104.      * shapes don't block other shapes 
  105.      */
  106.     glDepthMask( 0 );
  107. }
  108.  
  109. GLvoid 
  110. disableBlending( GLvoid )
  111. {
  112.     glDisable( GL_BLEND );
  113.     /* enable writing to the depth buffer */
  114.     glDepthMask( 1 );
  115. }
  116.  
  117. GLvoid
  118. setDrawStyle( GLvoid )
  119. {
  120.     if (++drawStyle > WIRE)
  121.         drawStyle = LIT_SMOOTH;
  122.  
  123.     switch (drawStyle)
  124.     {
  125.         case LIT_SMOOTH:
  126.             glShadeModel( GL_SMOOTH );
  127.             lighting = GL_TRUE;
  128.             break;
  129.         case LIT_FLAT:
  130.             glShadeModel( GL_FLAT );
  131.             lighting = GL_TRUE;
  132.             break;
  133.         case WIRE:
  134.             /* already in GL_FLAT mode */
  135.             lighting = GL_FALSE;
  136.             break;
  137.         default:
  138.             break;
  139.     }
  140. }
  141.  
  142. GLboolean
  143. inMotion( GLvoid )
  144. {
  145.     return ( autopilot || moving );
  146. }
  147.  
  148. GLvoid
  149. setAutopilot( GLvoid )
  150. {
  151.     autopilot = ! autopilot;
  152.     if ( autopilot )
  153.     {
  154.         if (resetauto) {
  155.             glTranslatef( 0.0, 0.0, -znear+1.0 );
  156.             resetauto = GL_FALSE;
  157.         }
  158.         moving = GL_FALSE; 
  159.     }
  160. }
  161.  
  162. GLvoid
  163. startMove( int button, int x, int y )
  164. {
  165.     moving = GL_TRUE;
  166.     autopilot = GL_FALSE;
  167.  
  168.     switch ( button ) {
  169.     case GLUT_LEFT_BUTTON: 
  170.         direction = FORWARD;
  171.         break;
  172.     case GLUT_MIDDLE_BUTTON: 
  173.         direction = BACKWARD;
  174.         break;
  175.     case GLUT_RIGHT_BUTTON: 
  176.     default:
  177.         printf("unexpected mouse button %d\n", button);
  178.     }
  179.     updatePosition( x, y );
  180. }
  181.  
  182. GLvoid
  183. stopMove( GLvoid )
  184. {
  185.     moving = GL_FALSE;
  186. }
  187.  
  188. GLvoid  
  189. moveEye( GLvoid )
  190. {
  191.     static float auto_angle;    /* autopilot rotation */
  192.     
  193.     if (autopilot)
  194.     {
  195.         /* using autopilot, eye moves in a circle */
  196.         ex = 10.0*fcos(auto_angle);
  197.         ey = 2.5;
  198.         ez = 10.0*fsin(auto_angle);
  199.     
  200.         /* increment the angle around the circle */
  201.         auto_angle = auto_angle + velocity/10.0;
  202.     
  203.         /* update the rotation of the eye, always look forward */
  204.         yaw = 180.0/M_PI*auto_angle + 180.0;
  205.         
  206.         if (debugFlag)
  207.             fprintf(stdout,"\nex=%f,ey=%f,ez=%f\n",ex,ey,ez);
  208.     }
  209.     /* else if not using the autopilot, calculate new 
  210.      * eye position based on the mouse position 
  211.      */
  212.     else if (moving)
  213.     {
  214.         /* update eye orientation */
  215.         yaw += turn_rate*(float)(xPos-winWidth/2)/winWidth;
  216.         pitch += turn_rate*(float)(yPos-winHeight/2)/winHeight;
  217.     
  218.         /* changes in eye position */
  219.         dx = fsin(yaw  * M_PI/180.0);
  220.         dy = fsin(pitch* M_PI/180.0);
  221.         dz = fcos(yaw  * M_PI/180.0);
  222.     
  223.         /* update eye position */
  224.         ex = ex + velocity*direction*dx;
  225.         ey = ey - velocity*direction*dy;
  226.         ez = ez - velocity*direction*dz;
  227.         if (debugFlag)
  228.             fprintf (stdout, "\nex=%f, ey=%f, ez=%f\n\
  229.                  dx=%f, dy=%f, dz=%f\n\
  230.                  yaw=%f, pitch=%f\n",
  231.                  ex, ey, ez, dx, dy, dz, yaw, pitch);
  232.     }   
  233. }
  234.  
  235. /* Updates the eye position and orientation based on the position 
  236.  * of the mouse. Works somewhat like the stick on an airplane:
  237.  * Pushing forward on the mouse tilts down, pulling back tilts up.
  238.  */
  239. GLvoid  
  240. updatePosition( int x, int y )
  241. {
  242.  
  243.     if ( moving ) 
  244.     {
  245.         /* mouse position in window coords */
  246.         xPos = x;
  247.         /* compensate for difference in y origin */
  248.         yPos = y;
  249.     }
  250. }
  251.  
  252.  
  253. GLvoid
  254. reshape( GLsizei width, GLsizei height )
  255. {
  256.     GLdouble     aspect;
  257.  
  258.     glViewport( 0, 0, width, height );
  259.     winWidth = width;
  260.     winHeight = height;
  261.     
  262.     aspect = (GLdouble) width / (GLdouble) height;
  263.  
  264.     glMatrixMode( GL_PROJECTION );
  265.     glLoadIdentity();
  266.     gluPerspective( 45.0, aspect, znear, zfar );
  267.     glMatrixMode( GL_MODELVIEW );
  268.     glLoadIdentity();
  269. }
  270.  
  271. GLvoid
  272. computeFloor( GLvoid )
  273. {
  274.     register int i, j;
  275.     GLfloat     x, y, z, d, spacing, maxDist;
  276.     static GLfloat angle;
  277.  
  278.     /* Create an undulating floor composed of points where the y
  279.      * value is related to the distance from the origin multiplied
  280.      * by the sine of an angle that is increasing by an amount
  281.      * proportional to velocity each iteration.
  282.      */
  283.  
  284.     /* spacing = distance between adjacent floor points in x & y */
  285.     spacing = 20.0 / (float)(FLOORPOINTS - 1);
  286.  
  287.     /* farthest a floorpoint can be from the origin */
  288.     maxDist = sqrtf( 200.0 );
  289.  
  290.     /* x and z range from -10.0 to 10.0 by spacing interval;
  291.      * We are going to FLOORPOINTS+1 in i and j so that we'll 
  292.      * be able to compute the normals later.
  293.      */
  294.     for ( x = -10.0, i = 0; i < FLOORPOINTS+1; x += spacing, i++ ) {
  295.         for ( z = -10.0, j = 0; j < FLOORPOINTS+1; z += spacing, j++ ) {
  296.             /* compute d = distance from center of floor */
  297.             d = sqrtf( x*x + z*z );
  298.             y = 2.5*(maxDist-d)/maxDist*sinf((d+angle)*(360.0/10.0)*M_PI/180.0);
  299.             floorPoints[i][j][X] = x;
  300.             floorPoints[i][j][Y] = y;
  301.             floorPoints[i][j][Z] = z;
  302.         }
  303.     }
  304.     angle = fmodf (angle + 0.4*velocity, 360.0);
  305.         computeNormals();
  306. } /* computeFloor */
  307.  
  308. GLvoid
  309. drawFloorWire( GLvoid )
  310. {
  311.     register int i, j;
  312.  
  313.     /* draw vertical lines connecting floor points */
  314.     for ( i = 0; i < (FLOORPOINTS); i++ ) {
  315.         glBegin( GL_LINE_STRIP );
  316.         for ( j = 0; j < (FLOORPOINTS); j++ ) {
  317.             glNormal3fv( &floorNormals[i][j][0] );
  318.             glVertex3fv( &floorPoints[i][j][0] );
  319.         }
  320.         glEnd();
  321.     }
  322.  
  323.     /* draw horizontal lines connecting floor points */
  324.     for ( j = 0; j < (FLOORPOINTS); j++ ) {
  325.         glBegin( GL_LINE_STRIP );
  326.         for ( i = 0; i < (FLOORPOINTS); i++ ) {
  327.             glNormal3fv( &floorNormals[i][j][0] );
  328.             glVertex3fv( &floorPoints[i][j][0] );
  329.         }
  330.         glEnd();
  331.     }
  332. } /* drawFloorWire */
  333.  
  334. GLvoid
  335. drawFloorFilled( GLvoid )
  336. {
  337.     register int i, j;
  338.  
  339.     /* Draw quad strips connecting floor points. 
  340.      * Floor is drawn column by column, 
  341.      * where each column is one quad strip.
  342.      * Every pair of vertices after first two vertices
  343.      * adds a new quad to the strip.
  344.      */
  345.     for ( i = 0; i < (FLOORPOINTS - 1); i++ ) {
  346.         glBegin( GL_QUAD_STRIP );
  347.         for ( j = 0; j < (FLOORPOINTS); j++ ) {
  348.             glNormal3fv( &floorNormals[i][j][0] );
  349.             glVertex3fv( &floorPoints[i][j][0] );
  350.             glNormal3fv( &floorNormals[i + 1][j][0] );
  351.             glVertex3fv( &floorPoints[i + 1][j][0] );
  352.         }
  353.         glEnd();
  354.     }
  355.     if (drawNormalsFlag)
  356.         drawNormals();
  357. }
  358.  
  359. /* Compute normals at each vertex of the floor,
  360.  * computed by taking the cross products of two
  361.  * points on the surface, and normalizing.
  362.  */
  363. GLvoid
  364. computeNormals( GLvoid )
  365. {
  366.     register int i, j;
  367.     float dx,dy,dz,l;       
  368.     float ax,ay,az;
  369.     float bx,by,bz;
  370.     float nx,ny,nz;
  371.  
  372.     for (i=0; i < FLOORPOINTS; i++) {
  373.         for ( j=0; j < FLOORPOINTS; j++) {
  374.  
  375.             /* Compute the direction vectors of two vectors
  376.              * in the polygon.  Let these two vectors be such
  377.              * that aXb points up (has positive y), so when we
  378.              * look at the floor from above, the floor is lit.
  379.              */
  380.             ax=floorPoints[i][j+1][X]-floorPoints[i][j][X];
  381.             ay=floorPoints[i][j+1][Y]-floorPoints[i][j][Y];
  382.             az=floorPoints[i][j+1][Z]-floorPoints[i][j][Z];
  383.             bx=floorPoints[i+1][j][X]-floorPoints[i][j][X];
  384.             by=floorPoints[i+1][j][Y]-floorPoints[i][j][Y];
  385.             bz=floorPoints[i+1][j][Z]-floorPoints[i][j][Z];
  386.  
  387.             /* compute the cross product of those two
  388.              * direction vectors 
  389.              */
  390.             nx = ay*bz-az*by;
  391.             ny = az*bx-ax*bz;
  392.             nz = ax*by-ay*bx;
  393.  
  394.             /* normalize the cross product by dividing it by
  395.              * it's length 
  396.              */
  397.             l=sqrtf(nx*nx+ny*ny+nz*nz);
  398.             floorNormals[i][j][X] = nx/l;
  399.             floorNormals[i][j][Y] = ny/l;
  400.             floorNormals[i][j][Z] = nz/l;
  401.         }
  402.     }
  403. } /* computeNormals */
  404.  
  405. /* Draw unlit lines indicating normals at each vertex of the floor,
  406.  * computed by taking the cross products of two
  407.  * points on the surface, and normalizing.
  408.  */
  409. GLvoid
  410. drawNormals( GLvoid )
  411. {
  412.     register int i, j;
  413.     float dx,dy,dz,l;       
  414.     float ax,ay,az;
  415.     float bx,by,bz;
  416.     float nx,ny,nz;
  417.     float nv[3];
  418.     static GLfloat    redColor[] = { 1.0, 0.0, 0.0 };
  419.  
  420.     if (lighting)
  421.         glDisable(GL_LIGHTING);
  422.  
  423.     glColor3fv( redColor );
  424.     glBegin( GL_LINES );
  425.     for (i=0; i < FLOORPOINTS; i++) {
  426.         for ( j=0; j < FLOORPOINTS; j++) {
  427.             nv[X]=floorPoints[i][j][X]+floorNormals[i][j][X];
  428.             nv[Y]=floorPoints[i][j][Y]+floorNormals[i][j][Y];
  429.             nv[Z]=floorPoints[i][j][Z]+floorNormals[i][j][Z];
  430.             glVertex3fv ( floorPoints[i][j]);
  431.             glVertex3fv ( nv );
  432.         }
  433.     }
  434.     glEnd();
  435.  
  436.     if (lighting)
  437.         glEnable(GL_LIGHTING);
  438. } /* drawNormals */
  439.  
  440. GLuint 
  441. createFont( GLfloat font[][1+MAX_STROKES*3] )
  442. {
  443.     GLint mode, i, j;
  444.     GLuint fontBase;
  445.     GLfloat fontScale;
  446.  
  447.     fontBase = glGenLists( 256 );
  448.     for (i = 0; font[i][0] != END_OF_LIST; i++) {
  449.         glNewList( fontBase+(GLuint)font[i][0], GL_COMPILE );
  450.         for (j = 1; mode = font[i][j]; j += 3) {
  451.             if (mode == FONT_BEGIN) {
  452.                 fontScale = font[i][j+2];
  453.                 glBegin( (GLint) font[i][j+1] );
  454.             } else if (mode == FONT_NEXT) {
  455.                 glVertex2f( font[i][j+1]*fontScale, 
  456.                         font[i][j+2]*fontScale );
  457.             } else if (mode == FONT_END) {
  458.                 glVertex2f( font[i][j+1]*fontScale, 
  459.                         font[i][j+2]*fontScale );
  460.                 glEnd();
  461.             } else if (mode == FONT_ADVANCE) {
  462.                 glTranslatef( font[i][j+1]*fontScale, 
  463.                           font[i][j+2]*fontScale, 0.0 );
  464.             }
  465.         }
  466.         glEndList();
  467.     }
  468.     return fontBase;
  469. }
  470.  
  471. GLuint 
  472. createOutlineFont( GLvoid )
  473. {
  474.     return createFont( outlineFont );
  475. }
  476.  
  477. GLuint 
  478. createFilledFont( GLvoid )
  479. {
  480.     return createFont( filledFont );
  481. }
  482.  
  483.  
  484. GLvoid 
  485. renderString( GLuint fontBase, GLubyte *string )
  486. {
  487.     glPushAttrib( GL_LIST_BIT );
  488.         glListBase(fontBase);
  489.         glCallLists(strlen(string), GL_UNSIGNED_BYTE, string);
  490.     glPopAttrib();
  491. }
  492.