////////////////////////////////////////////////////////////////// // Robert C. Duvall // Fall 2001 // #include // also includes glu and gl correctly #include // for atoi #include // for sprintf ////////////////////////////////////////////////////////////////// // Globals // // Constants // const int WINDOW_WIDTH = 800; // size of glut window const int WINDOW_HEIGHT = 600; // // Variables // int theNumRows = 10; // number of rows to draw double theAngle = 0; // current angle of rotation // keep track of the number of frames per second int theFrameCount = 0; int theLastFrameTime = 0; ////////////////////////////////////////////////////////////////// // Utility functions // void computeFPS () // post: compute frames per second and display in window's title bar { theFrameCount++; int currentTime = glutGet(GLUT_ELAPSED_TIME); if (currentTime - theLastFrameTime > 1000) { char s[16]; sprintf(s, "FPS: %4.2f", theFrameCount * 1000.0 / (currentTime - theLastFrameTime)); glutSetWindowTitle(s); theLastFrameTime = currentTime; theFrameCount = 0; } } ////////////////////////////////////////////////////////////////// // User Functions // These are the functions you will mostly be changing. // void initModel (int numRows) { theNumRows = numRows; } void animateModel () { // animate model by spinning it theAngle += 5; } void drawModel () { // color for all teapots glColor3f(0.0, 0.0, 0.9); // build pairs going up by 25 unit increments and rotating 45 degrees for (float r = -(theNumRows - 1) / 2.0; r <= (theNumRows - 1) / 2.0; r++) { for (float c = -(theNumRows - 1) / 2.0; c <= (theNumRows - 1) / 2.0; c++) { int dir = (int(r + c) % 2) ? 1 : -1; // translate to where we will place the teapot glTranslatef(r * 2.0 / theNumRows, c * 2.0 / theNumRows, 0.0); // rotate each teapot about y-axis glRotatef(dir * theAngle, 0.0, 1.0, 0.0); // draw teapot glutSolidTeapot(0.5 / theNumRows); // reset transforms back to origin glRotatef(-dir * theAngle, 0.0, 1.0, 0.0); glTranslatef(-r * 2.0 / theNumRows, -c * 2.0 / theNumRows, 0.0); } } } ////////////////////////////////////////////////////////////////// // Callback Functions // These functions are registered with the glut window and called // when certain events occur. // void onInit (int numRows) // pre: glut window has been initialized // post: model has been initialized { initModel(numRows); // set color used to clear window to black (i.e., background color) glClearColor(0.0, 0.0, 0.0, 0.0); // set to draw in window based on depth glEnable(GL_DEPTH_TEST); } void onRedraw () // pre: glut window needs to be refreshed // post: model is drawn { // erases requested bits (color and depth) in glut window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawModel(); // double-buffering - swap the back and front buffers glutSwapBuffers(); } void onIdle () // pre: glut window is not doing anything else // post: model is spun a little more { computeFPS(); animateModel(); // mark that glut window should be refreshed glutPostRedisplay(); } void onResize (int width, int height) // pre: glut window has been resized // post: resets cameras location and aspect to match window { // set viewable area to entire window glViewport(0, 0, GLint(width), GLint(height)); } ////////////////////////////////////////////////////////////////// // Main Function // int main (int argc, char *argv[]) { // initialize glut glutInit(&argc, argv); // request initial window size glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); // request glut window with double buffering and drawing based on depth glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA); // create window and make its title the name of the executable glutCreateWindow(argv[0]); // initialize model onInit(argc > 1 ? atoi(argv[1]) : 1); // tell glut how to display model glutDisplayFunc(onRedraw); // tell glut how to respond to changes in window size glutReshapeFunc(onResize); // tell glut to animate model using onIdle function glutIdleFunc(onIdle); // give control over to glut glutMainLoop(); // program should never get here return 0; }