Code subject: demonstrate how to add lighting and material properties
Posted: Sun Mar 20, 2011 9:59 pm
Joined: Tue Mar 27, 2007 10:55 pm Posts: 2272 Location: Earth Has thanked: 39 time Have thanks: 61 time
LightTorus.c
Code:
/************************************************** * LightTorus.c * * Program to demonstrate how to add lighting * and material properties to a torus. * This program extends the program WrapTorus. * * The triangles or quadrilaterals are wrapped around the * torus in a single long strip. See figure XXX on page XXX * in the above mentioned book. * * * Author: Samuel R. Buss * * Software accompanying the book * 3D Computer Graphics: A Mathematical Introduction with OpenGL, * by S. Buss, Cambridge University Press, 2002. * * Software is "as-is" and carries no warranty. It may be used without * restriction, but if you modify it, please change the filenames to * prevent confusion between different versions. * Bug reports: Sam Buss, sbuss@ucsd.edu. * Web page: http://math.ucsd.edu/~sbuss/MathCG * * USAGES: There are a number of keyboard commands that control * the animation. They must be typed into the graphics window, * and are listed below: * * CONTROLLING RESOLUTION OF THE TORUS MESH * Press "W" to increase the number wraps. * Press "w" to decrease the number wraps. * Press "N" to increase the number of segments per wrap. * Press "n" to decrease the number of segments per wrap. * Press "q" to toggle between quadrangles and triangles. * * CONTROLLING THE ANIMATION: * Press the "a" key to toggle the animation off and on. * Press the "s" key to perform a single step of the animation. * The left and right arrow keys controls the * rate of rotation around the y-axis. * The up and down arrow keys increase and decrease the rate of * rotation around the x-axis. In order to reverse rotational * direction you must zero or reset the torus ("0" or "r"). * Press the "r" key to reset the torus back to initial * position, with no rotation. * Press "0" (zero) to zero the rotation rates. * * CONTROLLING LIGHTS * Press '1' or '2' to toggle the first or second light off and on. * Press 'f' to toggle between flat and smooth shading. * Press 'l' to toggle local modes on and off (local viewer and positional light, * or non-local viewer and directional light). * * COMMANDS SHOWING OPENGL FEATURES: * Pressing "p" toggles between wireframe and polygon mode. * Pressing "f" key toggles between flat and smooth shading. * **/
// glutKeyboardFunc is called below to set this function to handle // all "normal" key presses. void myKeyboardFunc( unsigned char key, int x, int y ) { switch ( key ) { case 'a': runMode = !runMode; break; case 's': runMode = GL_TRUE; updateScene(); runMode = GL_FALSE; break; case 27: // Escape key exit(1); case 'r': // Reset the animation (resets everything) ResetAnimation(); break; case '0': // Zero the rotation rates ZeroRotation(); break; case 'f': // Shade mode toggles from flat to smooth ShadeModelToggle(); break; case 'p': // Polygon mode toggles between fill and line FillModeToggle(); break; case 'w': // Decrement number of wraps around torus WrapLess(); break; case 'W': // Increment number of wraps around torus WrapMore(); break; case 'n': // Decrement number of polys per wrap NumPerWrapLess(); break; case 'N': // Increment number of polys per wrap NumPerWrapMore(); break; case 'q': // Toggle between triangles and Quadrilaterals QuadTriangleToggle(); break; case 'l': // Toggle between local and non-local viewer ('l' is for 'local') LocalToggle(); break; case '1': // Toggle light #0 on and off Light0Toggle(); break; case '2': // Toggle light #1 on and off Light1Toggle(); break; } }
// glutSpecialFunc is called below to set this function to handle // all "special" key presses. See glut.h for the names of // special keys. void mySpecialKeyFunc( int key, int x, int y ) { switch ( key ) { case GLUT_KEY_UP: // Either increase upward rotation, or slow downward rotation KeyUp(); break; case GLUT_KEY_DOWN: // Either increase downwardward rotation, or slow upward rotation KeyDown(); break; case GLUT_KEY_LEFT: // Either increase left rotation, or slow down rightward rotation. KeyLeft(); break; case GLUT_KEY_RIGHT: // Either increase right rotation, or slow down leftward rotation. KeyRight(); break; } }
// The routines below are coded so that the only way to change from // one direction of rotation to the opposite direction is to first // reset the animation,
// Toggle from local to global mode void LocalToggle() { LocalMode = !LocalMode; if ( LocalMode ) { Lt0pos[3] = Lt1pos[3] = 1.0; // Put lights back at finite location. } else { Lt0pos[3] = Lt1pos[3] = 0.0; // Put lights at infinity too. } }
// The next two routines toggle the lights on and off void Light0Toggle() { Light0Flag = 1-Light0Flag; }
// Increment number of wraps void WrapMore() { NumWraps++; }
// Decrement number of wraps void WrapLess() { if (NumWraps>4) { NumWraps--; } }
// Increment number of segments per wrap void NumPerWrapMore() { NumPerWrap++; }
// Decrement number segments per wrap void NumPerWrapLess() { if (NumPerWrap>4) { NumPerWrap--; } }
/* * issue vertex command for segment number j of wrap number i. */ void putVert(int i, int j) { float wrapFrac = (j%NumPerWrap)/(float)NumPerWrap; float phi = PI2*wrapFrac; float theta = PI2*(i%NumWraps+wrapFrac)/(float)NumWraps; float sinphi = sin(phi); float cosphi = cos(phi); float sintheta = sin(theta); float costheta = cos(theta); float y = MinorRadius*sinphi; float r = MajorRadius + MinorRadius*cosphi; float x = sintheta*r; float z = costheta*r; glNormal3f(sintheta*cosphi, sinphi, costheta*cosphi); glVertex3f(x,y,z); }
void updateScene( void ) { int i,j;
// Clear the redering window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glShadeModel( shadeModel ); // Set the shading to flat or smooth. glPolygonMode(GL_FRONT_AND_BACK, polygonMode); // Set to be "wire" or "solid" glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, LocalMode);
// Set up lights if ( Light0Flag==1 || Light1Flag==1 ) { // Emissive spheres have no other color. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Noemit); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Noemit); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0); } if ( Light0Flag==1 ) { glPushMatrix(); glTranslatef(Lt0pos[0], Lt0pos[1], Lt0pos[2]); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt0spec); glutSolidSphere(0.2,5,5); glPopMatrix(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, Lt0pos); } else { glDisable(GL_LIGHT0); } if ( Light1Flag==1 ) { glPushMatrix(); glTranslatef(Lt1pos[0], Lt1pos[1], Lt1pos[2]); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Lt1spec); glutSolidSphere(0.2,5,5); glPopMatrix(); glEnable(GL_LIGHT1); glLightfv(GL_LIGHT1, GL_POSITION, Lt1pos); } else { glDisable(GL_LIGHT1); }
glEnable(GL_LIGHTING); // Enable lighting calculations glEnable(GL_LIGHT0); // Turn on lights (unnecessary here, since also in Animate() glEnable(GL_LIGHT1); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight); // Ambient light
// Light 0 (Position is set in updateScene) glLightfv(GL_LIGHT0, GL_AMBIENT, Lt0amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, Lt0diff); glLightfv(GL_LIGHT0, GL_SPECULAR, Lt0spec);
// Light 1 (Position is set in updateScene) glLightfv(GL_LIGHT1, GL_AMBIENT, Lt1amb); glLightfv(GL_LIGHT1, GL_DIFFUSE, Lt1diff); glLightfv(GL_LIGHT1, GL_SPECULAR, Lt1spec);
}
// Called when the window is resized // Sets up the projection view matrix (somewhat poorly, however) void resizeWindow(int w, int h) { float aspectRatio; glViewport( 0, 0, w, h ); // View port uses whole window h = (w == 0) ? 1 : h; aspectRatio = (float)w/(float)h;
// Set up the proection view matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 60.0, aspectRatio, 1.0, 30.0 );
glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // Move system 10 units away to be able to view from the origin. glTranslatef(0.0, 0.0, -10.0);
// Tilt system 15 degrees downward in order to view from above // the xy-plane. glRotatef(15.0, 1.0,0.0,0.0); }
// Main routine // Set up OpenGL, hook up callbacks, and start the main loop int main( int argc, char** argv ) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
// Window position (from top corner), and size (width and hieght) glutInitWindowPosition( 10, 60 ); glutInitWindowSize( 620, 160 ); glutCreateWindow( "Light Torus demo" );
// Set up callback functions for key presses glutKeyboardFunc( myKeyboardFunc ); glutSpecialFunc( mySpecialKeyFunc );
// Set up the callback function for resizing windows glutReshapeFunc( resizeWindow );
// Call this for background processing glutIdleFunc( updateScene ); // Call this whenever window needs redrawing glutDisplayFunc( updateScene );
// Start the main loop. glutMainLoop never returns. glutMainLoop( );
return(0); // This line is never reached. }
LightTorus.h:
Code:
/* * LightTorus.h * * Author: Samuel R. Buss * * Software accompanying the book * 3D Computer Graphics: A Mathematical Introduction with OpenGL, * by S. Buss, Cambridge University Press, 2002. * * Software is "as-is" and carries no warranty. It may be used without * restriction, but if you modify it, please change the filenames to * prevent confusion between different versions. * Bug reports: Sam Buss, sbuss@ucsd.edu. * Web page: http://math.ucsd.edu/~sbuss/MathCG */
// Function prototypes
void myKeyboardFunc( unsigned char key, int x, int y ); void mySpecialKeyFunc( int key, int x, int y );
void updateScene( void );
void initRendering(); void resizeWindow(int w, int h);