// Flagellum.cpp // NKU CSC 480 - Kirby // ---------------------------------------------------------------------- // Demonstrating nesting of transformations. // Draw a 3-jointed arm flailing about using angles that are // sinusoidal functions of time. // ---------------------------------------------------------------------- #include #include #include #include #include #include "Stopwatch.h" using namespace std ; // Global constants: scene rotation, in rev/sec. const double ROTATION_FREQ = 0.03 ; // Stopwatch for controlling animation. Stopwatch* G_pStopwatch ; void drawLimb( double length, double thickness ) // Draws a limb with given thickness running from x=0 to length. // Draw a sphere at the origin serving as a "ball joint." { assert( length > 2*thickness ) ; // otherwise ball joint looks awful // Ball joint diameter is a little larger than limb thickness. double radiusSphere= 1.1*thickness ; glutWireSphere( radiusSphere, 12, 12 ) ; // Draw the limb extending out x axis from origin. glMatrixMode( GL_MODELVIEW ) ; glPushMatrix() ; glTranslated( length/2, 0, 0 ) ; glScaled( length, thickness, thickness ) ; glutWireCube( 1 ) ; // 1x1x1 glPopMatrix() ; } void drawFlagellum( double angle1, double angle2, double angle3 ) // Draw a whip-like arm with three limbs at given joint angles. { const double LIMB_LENGTH= 1.0 ; const double LIMB_THICKNESS= 0.15 ; glMatrixMode( GL_MODELVIEW ) ; // Torso glPushMatrix() ; glTranslated( -1,0,0 ) ; glutWireIcosahedron() ; glPopMatrix() ; // Arm glPushMatrix() ; // upper arm glRotated( angle1, 0,0,1 ) ; glColor3d( 1,1,0 ) ; drawLimb( LIMB_LENGTH, LIMB_THICKNESS ) ; glPushMatrix() ; // forearm glColor3d(1,0,1) ; glTranslated( LIMB_LENGTH, 0, 0 ) ; glRotated( angle2, 0,0,1 ) ; drawLimb( LIMB_LENGTH, LIMB_THICKNESS ) ; glPushMatrix() ; // hand glColor3d( 0,1,1 ) ; glTranslated( LIMB_LENGTH, 0, 0 ) ; glRotated( angle3, 0,0,1 ) ; drawLimb( LIMB_LENGTH, LIMB_THICKNESS ) ; glPopMatrix() ; glPopMatrix() ; glPopMatrix(); glColor3d( 1,1,1 ) ; } void textLabel( const char* szLabel, double x, double y ) // Write a string at given x,y position in view volume (z=0). { glDisable( GL_LIGHTING ) ; glRasterPos2f( x, y ) ; while ( *szLabel ) glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_10, *szLabel++ ) ; } void projection() // Set up projection: gentle perspective. { glMatrixMode( GL_PROJECTION ) ; glLoadIdentity() ; gluPerspective( 35, 1, 7, 13 ) ; gluLookAt( 0,0,10, 0,0,0, 0,1,0 ) ; glMatrixMode( GL_MODELVIEW ) ; } void display() // Display the scene: a "robot" with some explanatory text. { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; glMatrixMode( GL_MODELVIEW ) ; glLoadIdentity() ; // Text. textLabel( "Toggle animation: Space bar", -2.8, -3.0 ) ; // Get elapsed animation time (in seconds) from stopwatch. double t= G_pStopwatch->getValue() * 0.001 ; // Set animation/rotation of scene. double degrees= t * ROTATION_FREQ * 360 ; glRotated( -degrees, 0,1,0 ) ; // Determine joint angles from time using sine waves. const double MAX_ANGLE= 50.0 ; // maximum joint angle (+/-) in degrees const double FREQ1= 0.6 ; const double FREQ2= 0.8 ; const double FREQ3= 1.3 ; double angle1= MAX_ANGLE * sin( FREQ1 * t ) ; double angle2= MAX_ANGLE * sin( FREQ2 * t ) ; double angle3= MAX_ANGLE * sin( FREQ3 * t ) ; // Draw flagellum. drawFlagellum( angle1, angle2, angle3 ) ; glutSwapBuffers() ; } void animate() // One frame of animation. { glutPostRedisplay() ; } void toggleAnimation() // Toggle animation on and off. { if ( G_pStopwatch->isStopped() ) { G_pStopwatch->start() ; glutIdleFunc( animate ) ; } else { G_pStopwatch->stop() ; glutIdleFunc( NULL ) ; } } void kbDispatch( unsigned char ch, int x, int y ) // Respond to key presses (ASCII key values). { switch( ch ) { case ' ': toggleAnimation() ; break ; } glutPostRedisplay() ; } int main( int argc, char** argv ) { // Initialize OpenGL. glutInit( &argc, argv ) ; glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH ) ; glEnable( GL_DEPTH_TEST ) ; glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ) ; glEnable( GL_NORMALIZE ) ; // Window attributes. glutInitWindowSize( 700, 700 ) ; glutInitWindowPosition( 100, 100 ) ; glutCreateWindow( "NKU CSC 480: Flagellum" ) ; // Register callbacks. glutKeyboardFunc( kbDispatch ) ; glutDisplayFunc( display ) ; // Initialize animation motor. G_pStopwatch= new Stopwatch ; toggleAnimation() ; // Go. projection() ; glutMainLoop() ; return 0 ; }