/* prac9a.c */ /* Purpose: Create two interlocking gears that rotate when the system is idle. */ #ifdef __APPLE__ #include #else #include #endif #include #include #include #define KEY_ESC 27 /* glut doesn't define this one */ /* Global variables */ static GLfloat mGearRotationAngle = 0; static const int mSlices = 12; /* Must be an even number */ static const GLfloat mOuterRadius = 2; static const GLfloat mInnerRadius = 1; static const GLfloat mNobblyBitHeight = 1; static const GLdouble PI = 3.1415926535897932384626433832795; static const GLfloat mGearRotationInc = 0.7; void printHelp( void ) { fprintf(stdout, "\nGears\n\n" "Escape key - exit the program\n\n"); } GLvoid keyboard( GLubyte key, GLint x, GLint y) { switch (key) { case KEY_ESC: /* exit when escape key is pressed */ exit(0); break; } } GLvoid specialkeys( GLint key, GLint x, GLint y) { switch (key) { case GLUT_KEY_F1: /* print Help information */ printHelp ( ); break; } } GLvoid checkError( const char* const label ) { GLenum error; error = glGetError(); while ( GL_NO_ERROR != error ) { fprintf( stderr,"%s: %s\n", label, gluErrorString(error) ); error = glGetError(); } } /* Note that the CALLBACK is neccessary to work under MS Windows */ GLvoid CALLBACK checkError2(GLvoid) { checkError("Quadric Error"); } void reshape(GLint width, GLint height) { GLdouble aspect; GLdouble size = 3 * (mOuterRadius+mNobblyBitHeight); aspect = (GLdouble)width / (GLdouble)height; /* We still want the output to cover the whole window */ glViewport(0, 0, width, height); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); /* Get the viewing volume set up to match the aspect ratio of the viewport */ if (width > height) { glOrtho(-size*aspect, size * aspect, -size, size, -1, 1); } else { glOrtho(-size, size, -size / aspect, size / aspect, -1, 1); } glMatrixMode( GL_MODELVIEW ); } /* Rotate the gears when idle */ void idle(void) { mGearRotationAngle = fmod(mGearRotationAngle + mGearRotationInc, 360.0); glutPostRedisplay(); } void visibility (int state) { /* If the window is not visible then stop the animation. Restart animation when visible. */ if (GLUT_VISIBLE == state) { glutIdleFunc( idle ); } else { glutIdleFunc( NULL ); } } void drawNobblyBit(void) { GLfloat nobblyBitWidth = 2*PI*mOuterRadius/mSlices; glBegin(GL_LINE_STRIP); glVertex2f(0.0, 0.0); glVertex2f(0.0, mNobblyBitHeight); glVertex2f(nobblyBitWidth, mNobblyBitHeight); glVertex2f(nobblyBitWidth, 0.0); glEnd(); } void drawGear(void) { /* This is highly inefficient. Quadric objects should be stored and reused rather than created and deleted every function call. */ GLUquadricObj* pQuadric = gluNewQuadric(); int i; /* Set up the quadric error callback function */ gluQuadricCallback(pQuadric, GLU_ERROR, checkError2); /* Draw the circular part of the gear */ gluDisk(pQuadric, mInnerRadius, mOuterRadius, mSlices, 20); /* Put the knobbly bits on the gear */ for (i = 1; i< mSlices; i+=2) { glPushMatrix(); glRotatef( 360.0/(GLfloat)mSlices *i, 0, 0, 1); glTranslatef(0.0, mOuterRadius, 0.0); glRotatef( -(360.0/(GLfloat)mSlices)/2.0, 0, 0, 1); drawNobblyBit(); glPopMatrix(); } gluDeleteQuadric(pQuadric); } GLvoid display( GLvoid ) { /* Do all your OpenGL rendering here */ glClear( GL_COLOR_BUFFER_BIT ); glLoadIdentity(); /* Reset the ModelView transformation every time we draw */ glPushMatrix(); glRotatef(mGearRotationAngle, 0, 0, 1); drawGear(); glPopMatrix(); glPushMatrix(); glTranslatef(2.0*mOuterRadius+mNobblyBitHeight, 0, 0); glRotatef(-mGearRotationAngle, 0, 0, 1); drawGear(); glPopMatrix(); /* Don't check errors every frame - expensive. Only do it while debugging. */ checkError( "display" ); /* For single buffered display glFlush(); */ /* For double buffered display */ glutSwapBuffers(); } GLvoid init( GLvoid ) { glClearColor( 1.0, 1.0, 1.0, 1.0); glColor3f(1.0,0.0,0.0); glLineWidth(3.0); } int main( int argc, char *argv[] ) { glutInit( &argc, argv ); /* For single buffered display: */ /*glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB ); */ /* For double buffered display: */ glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); glutCreateWindow( argv[0] ); init(); glutKeyboardFunc( keyboard ); glutSpecialFunc( specialkeys ); glutDisplayFunc( display ); glutReshapeFunc( reshape ); glutIdleFunc( idle ); glutVisibilityFunc( visibility ); printHelp( ); glutMainLoop(); return 0; }