home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Silicon Graphics, Inc. 1996 */
-
- /*
- * flyutil.c
- * This file contains utility routines used by the fly program.
- *
- * Copyright 1991, 1992, 1993, Silicon Graphics, Inc.
- * Technical Education R & D
- */
-
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glut.h>
-
- #include "fly.h"
- #include "fonts.h"
-
- /* Global Variables */
-
- static GLfloat floorPoints[FLOORPOINTS+1][FLOORPOINTS+1][3] = { 0 };
- static GLfloat floorNormals[FLOORPOINTS+1][FLOORPOINTS+1][3] = { 0 };
-
- extern enum drawStyles { LIT_SMOOTH, LIT_FLAT, WIRE };
-
- GLint drawStyle = LIT_SMOOTH;
-
- GLboolean drawNormalsFlag = GL_FALSE;
-
- /* initial characteristics of the eye */
- static GLint direction = FORWARD; /* FORWARD or BACKWARD */
-
- static GLsizei winWidth, winHeight;
-
- GLboolean debugFlag = GL_FALSE; /* print eye position info? */
- GLboolean blendFlag = GL_FALSE;
- GLboolean lighting = GL_TRUE;
- GLboolean showGridFlag = GL_FALSE;
-
- static GLboolean autopilot = GL_FALSE; /* is autopilot mode on? */
- static GLboolean moving = GL_FALSE;
-
- static GLint xPos, yPos; /* mouse position */
-
- GLfloat ex, ey, ez; /* eye position */
- GLfloat dx,dy,dz; /* change in eye position */
-
- GLfloat yaw; /* eye rotation about y axis in degrees */
- GLfloat pitch; /* eye rotation about x axis in degrees */
- GLfloat velocity = 0.15; /* eye velocity */
- GLfloat turn_rate = 3.0; /* eye turning agility */
-
- GLdouble znear = 5.0, zfar = 50.0;
-
- GLboolean resetauto = GL_TRUE; /* first autopilot since reset? */
-
- GLvoid
- initEye(GLvoid)
- {
- /* initial position of the eye in the world */
- ex = 20.0;
- ey = 10.0;
- ez = 20.0;
-
- yaw = -45.0; /* rotation around eye y axis in degrees */
- pitch = 20.0; /* rotation around eye x axis in degrees */
- autopilot = GL_FALSE;
- resetauto = GL_TRUE;
- moving = GL_FALSE;
- }
-
- /* Define user input functions */
- GLvoid
- toggleDrawNormals( GLvoid )
- {
- drawNormalsFlag = !drawNormalsFlag;
- }
-
- GLvoid
- toggleShowGrid( GLvoid )
- {
- showGridFlag = !showGridFlag;
- }
-
- GLvoid
- setDebug( GLvoid )
- {
- debugFlag = !debugFlag;
- }
-
- GLvoid
- toggleBlend( GLvoid )
- {
- blendFlag = !blendFlag;
- fprintf( stdout, "blendFlag = %d\n", blendFlag );
- if ( !blendFlag )
- disableBlending();
- }
-
- GLvoid
- enableBlending( GLvoid )
- {
- glEnable( GL_BLEND );
- /* disable writing to the depth buffer so that transparent
- * shapes don't block other shapes
- */
- glDepthMask( 0 );
- }
-
- GLvoid
- disableBlending( GLvoid )
- {
- glDisable( GL_BLEND );
- /* enable writing to the depth buffer */
- glDepthMask( 1 );
- }
-
- GLvoid
- setDrawStyle( GLvoid )
- {
- if (++drawStyle > WIRE)
- drawStyle = LIT_SMOOTH;
-
- switch (drawStyle)
- {
- case LIT_SMOOTH:
- glShadeModel( GL_SMOOTH );
- lighting = GL_TRUE;
- break;
- case LIT_FLAT:
- glShadeModel( GL_FLAT );
- lighting = GL_TRUE;
- break;
- case WIRE:
- /* already in GL_FLAT mode */
- lighting = GL_FALSE;
- break;
- default:
- break;
- }
- }
-
- GLboolean
- inMotion( GLvoid )
- {
- return ( autopilot || moving );
- }
-
- GLvoid
- setAutopilot( GLvoid )
- {
- autopilot = ! autopilot;
- if ( autopilot )
- {
- if (resetauto) {
- glTranslatef( 0.0, 0.0, -znear+1.0 );
- resetauto = GL_FALSE;
- }
- moving = GL_FALSE;
- }
- }
-
- GLvoid
- startMove( int button, int x, int y )
- {
- moving = GL_TRUE;
- autopilot = GL_FALSE;
-
- switch ( button ) {
- case GLUT_LEFT_BUTTON:
- direction = FORWARD;
- break;
- case GLUT_MIDDLE_BUTTON:
- direction = BACKWARD;
- break;
- case GLUT_RIGHT_BUTTON:
- default:
- printf("unexpected mouse button %d\n", button);
- }
- updatePosition( x, y );
- }
-
- GLvoid
- stopMove( GLvoid )
- {
- moving = GL_FALSE;
- }
-
- GLvoid
- moveEye( GLvoid )
- {
- static float auto_angle; /* autopilot rotation */
-
- if (autopilot)
- {
- /* using autopilot, eye moves in a circle */
- ex = 10.0*fcos(auto_angle);
- ey = 2.5;
- ez = 10.0*fsin(auto_angle);
-
- /* increment the angle around the circle */
- auto_angle = auto_angle + velocity/10.0;
-
- /* update the rotation of the eye, always look forward */
- yaw = 180.0/M_PI*auto_angle + 180.0;
-
- if (debugFlag)
- fprintf(stdout,"\nex=%f,ey=%f,ez=%f\n",ex,ey,ez);
- }
- /* else if not using the autopilot, calculate new
- * eye position based on the mouse position
- */
- else if (moving)
- {
- /* update eye orientation */
- yaw += turn_rate*(float)(xPos-winWidth/2)/winWidth;
- pitch += turn_rate*(float)(yPos-winHeight/2)/winHeight;
-
- /* changes in eye position */
- dx = fsin(yaw * M_PI/180.0);
- dy = fsin(pitch* M_PI/180.0);
- dz = fcos(yaw * M_PI/180.0);
-
- /* update eye position */
- ex = ex + velocity*direction*dx;
- ey = ey - velocity*direction*dy;
- ez = ez - velocity*direction*dz;
- if (debugFlag)
- fprintf (stdout, "\nex=%f, ey=%f, ez=%f\n\
- dx=%f, dy=%f, dz=%f\n\
- yaw=%f, pitch=%f\n",
- ex, ey, ez, dx, dy, dz, yaw, pitch);
- }
- }
-
- /* Updates the eye position and orientation based on the position
- * of the mouse. Works somewhat like the stick on an airplane:
- * Pushing forward on the mouse tilts down, pulling back tilts up.
- */
- GLvoid
- updatePosition( int x, int y )
- {
-
- if ( moving )
- {
- /* mouse position in window coords */
- xPos = x;
- /* compensate for difference in y origin */
- yPos = y;
- }
- }
-
-
- GLvoid
- reshape( GLsizei width, GLsizei height )
- {
- GLdouble aspect;
-
- glViewport( 0, 0, width, height );
- winWidth = width;
- winHeight = height;
-
- aspect = (GLdouble) width / (GLdouble) height;
-
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- gluPerspective( 45.0, aspect, znear, zfar );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- }
-
- GLvoid
- computeFloor( GLvoid )
- {
- register int i, j;
- GLfloat x, y, z, d, spacing, maxDist;
- static GLfloat angle;
-
- /* Create an undulating floor composed of points where the y
- * value is related to the distance from the origin multiplied
- * by the sine of an angle that is increasing by an amount
- * proportional to velocity each iteration.
- */
-
- /* spacing = distance between adjacent floor points in x & y */
- spacing = 20.0 / (float)(FLOORPOINTS - 1);
-
- /* farthest a floorpoint can be from the origin */
- maxDist = sqrtf( 200.0 );
-
- /* x and z range from -10.0 to 10.0 by spacing interval;
- * We are going to FLOORPOINTS+1 in i and j so that we'll
- * be able to compute the normals later.
- */
- for ( x = -10.0, i = 0; i < FLOORPOINTS+1; x += spacing, i++ ) {
- for ( z = -10.0, j = 0; j < FLOORPOINTS+1; z += spacing, j++ ) {
- /* compute d = distance from center of floor */
- d = sqrtf( x*x + z*z );
- y = 2.5*(maxDist-d)/maxDist*sinf((d+angle)*(360.0/10.0)*M_PI/180.0);
- floorPoints[i][j][X] = x;
- floorPoints[i][j][Y] = y;
- floorPoints[i][j][Z] = z;
- }
- }
- angle = fmodf (angle + 0.4*velocity, 360.0);
- computeNormals();
- } /* computeFloor */
-
- GLvoid
- drawFloorWire( GLvoid )
- {
- register int i, j;
-
- /* draw vertical lines connecting floor points */
- for ( i = 0; i < (FLOORPOINTS); i++ ) {
- glBegin( GL_LINE_STRIP );
- for ( j = 0; j < (FLOORPOINTS); j++ ) {
- glNormal3fv( &floorNormals[i][j][0] );
- glVertex3fv( &floorPoints[i][j][0] );
- }
- glEnd();
- }
-
- /* draw horizontal lines connecting floor points */
- for ( j = 0; j < (FLOORPOINTS); j++ ) {
- glBegin( GL_LINE_STRIP );
- for ( i = 0; i < (FLOORPOINTS); i++ ) {
- glNormal3fv( &floorNormals[i][j][0] );
- glVertex3fv( &floorPoints[i][j][0] );
- }
- glEnd();
- }
- } /* drawFloorWire */
-
- GLvoid
- drawFloorFilled( GLvoid )
- {
- register int i, j;
-
- /* Draw quad strips connecting floor points.
- * Floor is drawn column by column,
- * where each column is one quad strip.
- * Every pair of vertices after first two vertices
- * adds a new quad to the strip.
- */
- for ( i = 0; i < (FLOORPOINTS - 1); i++ ) {
- glBegin( GL_QUAD_STRIP );
- for ( j = 0; j < (FLOORPOINTS); j++ ) {
- glNormal3fv( &floorNormals[i][j][0] );
- glVertex3fv( &floorPoints[i][j][0] );
- glNormal3fv( &floorNormals[i + 1][j][0] );
- glVertex3fv( &floorPoints[i + 1][j][0] );
- }
- glEnd();
- }
- if (drawNormalsFlag)
- drawNormals();
- }
-
- /* Compute normals at each vertex of the floor,
- * computed by taking the cross products of two
- * points on the surface, and normalizing.
- */
- GLvoid
- computeNormals( GLvoid )
- {
- register int i, j;
- float dx,dy,dz,l;
- float ax,ay,az;
- float bx,by,bz;
- float nx,ny,nz;
-
- for (i=0; i < FLOORPOINTS; i++) {
- for ( j=0; j < FLOORPOINTS; j++) {
-
- /* Compute the direction vectors of two vectors
- * in the polygon. Let these two vectors be such
- * that aXb points up (has positive y), so when we
- * look at the floor from above, the floor is lit.
- */
- ax=floorPoints[i][j+1][X]-floorPoints[i][j][X];
- ay=floorPoints[i][j+1][Y]-floorPoints[i][j][Y];
- az=floorPoints[i][j+1][Z]-floorPoints[i][j][Z];
- bx=floorPoints[i+1][j][X]-floorPoints[i][j][X];
- by=floorPoints[i+1][j][Y]-floorPoints[i][j][Y];
- bz=floorPoints[i+1][j][Z]-floorPoints[i][j][Z];
-
- /* compute the cross product of those two
- * direction vectors
- */
- nx = ay*bz-az*by;
- ny = az*bx-ax*bz;
- nz = ax*by-ay*bx;
-
- /* normalize the cross product by dividing it by
- * it's length
- */
- l=sqrtf(nx*nx+ny*ny+nz*nz);
- floorNormals[i][j][X] = nx/l;
- floorNormals[i][j][Y] = ny/l;
- floorNormals[i][j][Z] = nz/l;
- }
- }
- } /* computeNormals */
-
- /* Draw unlit lines indicating normals at each vertex of the floor,
- * computed by taking the cross products of two
- * points on the surface, and normalizing.
- */
- GLvoid
- drawNormals( GLvoid )
- {
- register int i, j;
- float dx,dy,dz,l;
- float ax,ay,az;
- float bx,by,bz;
- float nx,ny,nz;
- float nv[3];
- static GLfloat redColor[] = { 1.0, 0.0, 0.0 };
-
- if (lighting)
- glDisable(GL_LIGHTING);
-
- glColor3fv( redColor );
- glBegin( GL_LINES );
- for (i=0; i < FLOORPOINTS; i++) {
- for ( j=0; j < FLOORPOINTS; j++) {
- nv[X]=floorPoints[i][j][X]+floorNormals[i][j][X];
- nv[Y]=floorPoints[i][j][Y]+floorNormals[i][j][Y];
- nv[Z]=floorPoints[i][j][Z]+floorNormals[i][j][Z];
- glVertex3fv ( floorPoints[i][j]);
- glVertex3fv ( nv );
- }
- }
- glEnd();
-
- if (lighting)
- glEnable(GL_LIGHTING);
- } /* drawNormals */
-
- GLuint
- createFont( GLfloat font[][1+MAX_STROKES*3] )
- {
- GLint mode, i, j;
- GLuint fontBase;
- GLfloat fontScale;
-
- fontBase = glGenLists( 256 );
- for (i = 0; font[i][0] != END_OF_LIST; i++) {
- glNewList( fontBase+(GLuint)font[i][0], GL_COMPILE );
- for (j = 1; mode = font[i][j]; j += 3) {
- if (mode == FONT_BEGIN) {
- fontScale = font[i][j+2];
- glBegin( (GLint) font[i][j+1] );
- } else if (mode == FONT_NEXT) {
- glVertex2f( font[i][j+1]*fontScale,
- font[i][j+2]*fontScale );
- } else if (mode == FONT_END) {
- glVertex2f( font[i][j+1]*fontScale,
- font[i][j+2]*fontScale );
- glEnd();
- } else if (mode == FONT_ADVANCE) {
- glTranslatef( font[i][j+1]*fontScale,
- font[i][j+2]*fontScale, 0.0 );
- }
- }
- glEndList();
- }
- return fontBase;
- }
-
- GLuint
- createOutlineFont( GLvoid )
- {
- return createFont( outlineFont );
- }
-
- GLuint
- createFilledFont( GLvoid )
- {
- return createFont( filledFont );
- }
-
-
- GLvoid
- renderString( GLuint fontBase, GLubyte *string )
- {
- glPushAttrib( GL_LIST_BIT );
- glListBase(fontBase);
- glCallLists(strlen(string), GL_UNSIGNED_BYTE, string);
- glPopAttrib();
- }
-