/** Course: CSC 6820 - Computer Graphics Project: 2 Author: Jeff Chastine Date: Oct. 9th Last Modified: Oct. 16th ** Extra Credit: There's a few extra features in here that I just did to explore, but the 'real' extra credit lies in the texture mapping on both the gold teapot and the plane. The menuing system can be accessed by (right-clicking), and includes changing between checkerboard and the smiley texture, changing between bilinear and point sampling filtering modes as well as turning on and off fog. Another cool effect was rotating the spotlight around with the teapot. This gives a nice look, and you can really see the Gouraud shading issues with a low polygon count this way! ** NOTE: the bitmap 'smiley' needs to be placed straight into the C:\ directory! Purpose: This assignment gives exposure to the OpenGL lighting model as well as materials and texture mapping. The application renders 4 teapots, each with different ambient, diffuse and specular properties; these objects are illuminated by three different types of lights: an ambient light, a directional light, and a spot light. These can all be turned on and off through the menuing system. Additionally, the assignment explores high versus low polygon count, and how this affects the rendering of the spotlight. The plane polygon can be sub-divided and un-sub-divided by pressing the B and b key, respectfully. Keys: Movement: - A : strafe left - D : strage right - E/+ : move forward - S/- : move backward - Y : move camera up - N : move camera down - LEFT_ARROW : rotate left - RIGHT_ARROW : rotate right - UP_ARROW : look up - DOWN_ARROW : look down Geometry: - k : sub-divide plane - l : un-sub-divide plane Lighting and Texturing: - t/T : use texture/don't use it - w/W : wireframe mode/shaded mode - p/P : spotlight on/off - o/O : ambient on/off - i/I : directional on/off Mouse Control: Right-clicking yields the main menu. The mouse is speed sensitive, so the faster you move in a direction, the faster the rotation of the camera. */ // Include libraries for OpenGL, and stream abilities for the file #include #include #include // The size of the plane #define SIZE_OF_PLANE 1024 //Light1 - SpotLight settings GLfloat ambient_light[] = {0.0f, 0.0f, 0.0f, 1.0f}; GLfloat specular_light[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat diffuse_light[] = {0.7f, 0.7f, 0.7f, 1.0f}; GLfloat light_position[] = {0.0f, 100.0f, 0.0f, 1.0f}; GLfloat spot_direction[] = {0.0f, -1.0f, 0.0f, 0.0f}; //Light2 - Ambient light setting GLfloat ambient_light2[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Light3 - Directional light settings GLfloat diffuse_light3[] = {0.8f, 0.8f, 0.8f, 1.0f}; GLfloat specular_light3[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat light_position3[] = {-100.0f, 10.0f, 0.0f, 0.0f}; GLfloat spot_direction3[] = {-1.0f, -1.0f, 0.0f, 0.0f}; // Camera state GLfloat camera_state[4][4]; // Material 0 - plane GLfloat ambient0[] = {0.2, 0.2, 0.2, 1.0}; GLfloat diffuse0[] = {0.8, 0.8, 0.8, 1.0}; GLfloat specular0[] = {1.0, 1.0, 1.0, 1.0}; GLfloat shininess0 = 85.0f; // Material 1 - red GLfloat ambient1[] = {0.2, 0.0, 0.0, 1.0}; GLfloat diffuse1[] = {0.4, 0.0, 0.0, 1.0}; GLfloat specular1[] = {0.2, 0.2, 0.2, 1.0}; GLfloat shininess1 = 2.0f; // Material 2 - blue GLfloat ambient2[] = {0.0, 0.0, 0.3, 1.0}; GLfloat diffuse2[] = {0.1, 0.1, 0.6, 1.0}; GLfloat specular2[] = {1.0, 1.0, 1.0, 1.0}; GLfloat shininess2 = 250.0f; // Material 3 - green GLfloat ambient3[] = {0.05, 0.2, 0.05, 1.0}; GLfloat diffuse3[] = {0.1, 0.6, 0.1, 1.0}; GLfloat specular3[] = {1.0, 1.0, 1.0, 1.0}; GLfloat shininess3 = 15.0f; // Material 4 - gold GLfloat ambient4[] = {0.30, 0.20, 0.03, 1.0}; GLfloat diffuse4[] = {0.80, 0.60, 0.10, 1.0}; GLfloat specular4[] = {1.0, 0.90, 0.80, 1.0}; GLfloat shininess4 = 30.0f; // To move camera position up and down int camY, camX, camZ; // To rotate the camera left and right GLfloat camAlpha, camBeta; // The current number of subdivisions for the plane int numDivisions = 64; // Used to determine whether you're going left or right GLfloat oldX, oldY; // Variables for the current mode int firstTime = 1; int wireframe_mode = 0; int texture_mode = 1; int trippy_mode = 0; int spot_rot = 0; int pot_rot = 0; int image_count = 1; int key_up_pressed, key_down_pressed, key_left_pressed, key_right_pressed, forward_pressed, back_pressed; // Two arrays to hold the checkerboard and smiley textures GLubyte checkerboard[256][256][3]; GLubyte qual_image [256][256][3]; // Texture names GLuint checkerTexObject=0, qualImage=0; //Current Raster position GLfloat ras_pos[4]; // Setting up the lighting function prototype void setupLighting(); // This function draws the plane, given it's size (SIZE_OF_PLANE) // and the number of subdivisions. The number of subdivisions is // changed by the user pressing 'l' and 'k' void drawPlane() { int gridSize = SIZE_OF_PLANE/numDivisions; int offset = SIZE_OF_PLANE/2; int i, j; // Set the color to white (depending on mode) glColor3f (1.0, 1.0, 1.0); // Loop through each 'grid', setting the point, the normal // the texture coordinate for (i = 0; i < numDivisions; i++) { for (j = 0; j < numDivisions; j++) { // Change your filling algorithm if necessarry if (wireframe_mode) { glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); } else { glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); } glBegin(GL_POLYGON); // Set the normal, the texture coordinate and the point glNormal3f(0.0, 1.0, 0.0); glTexCoord2f((float)(i*gridSize)/(float)SIZE_OF_PLANE, (float)(j*gridSize)/(float)SIZE_OF_PLANE); glVertex3f (i*gridSize-offset, 0, j*gridSize-offset); // Set the normal, the texture coordinate and the point glNormal3f(0.0, 1.0, 0.0); glTexCoord2f((float)((i+1)*gridSize)/(float)SIZE_OF_PLANE, (float)(j*gridSize)/(float)SIZE_OF_PLANE); glVertex3f (i*gridSize-offset+gridSize, 0, j*gridSize-offset); // Set the normal, the texture coordinate and the point glNormal3f(0.0, 1.0, 0.0); glTexCoord2f((float)((i+1)*gridSize)/(float)SIZE_OF_PLANE, (float)((j+1)*gridSize)/(float)SIZE_OF_PLANE); glVertex3f (i*gridSize-offset+gridSize, 0, j*gridSize-offset+gridSize); // Set the normal, the texture coordinate and the point glNormal3f(0.0, 1.0, 0.0); glTexCoord2f((float)(i*gridSize)/(float)SIZE_OF_PLANE, (float)((j+1)*gridSize)/(float)SIZE_OF_PLANE); glVertex3f (i*gridSize-offset, 0, j*gridSize-offset+gridSize); glEnd(); } } glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); } // Set the material for the plane // Update the ambient, diffuse, specular and shininess components void material0() { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient0); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse0); glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular0); glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess0); } // Red // Update the ambient, diffuse, specular and shininess components void material1() { // Change the ambient property of material 1 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient1); // Change the ambient diffuse of material 1 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse1); // Change the specular property of material 1 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular1); // Change the ambient shininess of material 1 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess1); } // Blue // Update the ambient, diffuse, specular and shininess components void material2() { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient2); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse2); glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular2); glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess2); } // Green // Update the ambient, diffuse, specular and shininess components void material3() { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient3); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse3); glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular3); glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess3); } // Gold // Update the ambient, diffuse, specular and shininess components void material4() { glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, ambient4); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse4); glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular4); glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &shininess4); } /** function paint: this function is the main display callback for the application. Because the application is interactive, there are several options with how the objects are drawn. Recall that affine transformations occur in reverse order. */ void paint (void) { static int stat_counter = 1; // Clear both the color and depth buffers glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); // Working on the camera stuff glPushMatrix(); // Translate for the camera state glTranslatef(-camX, -camY, -camZ); // Rotate by the camera state glRotatef(-camBeta, 1.0f, 0.0f, 0.0f); glRotatef(camAlpha,0.0f, 0.0f, 1.0f); // Reset for next time camAlpha = camBeta = 0; camX = camY = camZ = 0; // Update camera state matrix to include above rotations glMultMatrixf((float*)camera_state); // Get the current MVM and update the camera_state matrix glGetFloatv(GL_MODELVIEW_MATRIX, (float*)camera_state); glPopMatrix(); // Apply the camera state to future operations glMultMatrixf((float*)camera_state); // Turn on texturing by default - may be turned off later glEnable(GL_TEXTURE_2D); // Set up how the texture should be applied to the glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Determine which texture to apply, calling glTexImage2D. Note, because // the qual_image is a bitmap, GL_BGR_EXT was necessary. if (image_count == 0){ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, checkerboard); } else if (image_count == 1) { glTexImage2D (GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, qual_image); } // If texturing is off, turn off lighting and texturing temporarily if (!texture_mode) { glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); } else { glEnable (GL_LIGHTING); glEnable(GL_TEXTURE_2D); } // setup the material and draw the plane material0(); drawPlane(); // re-enable lighting and texturing glEnable(GL_LIGHTING); glDisable (GL_TEXTURE_2D); // Make sure the lights are rotated as well glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT2, GL_POSITION, light_position3); glLightfv (GL_LIGHT2, GL_SPOT_DIRECTION, spot_direction3); // Rotate all of the pots glRotatef (pot_rot, 0.0f, 1.0f, 0.0f); glPushMatrix(); glTranslatef(0.0, 100.0, 0.0f); glScalef(0.1f, 0.1f, 0.1f); glRotatef(spot_rot, 0.0f, 0.0f, 1.0f); // As an added feature, rotate the spotlight - very cool effect! glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); glRotatef (-90.0f, 1.0f, 0.0f, 0.0f); glutSolidCone (15, 15, 10, 10); glPopMatrix(); glPushMatrix();//teapot4 - red glTranslatef(-20.0f, 4.0f, -20.0f); glRotatef(-pot_rot*2, 0.0f, 1.0f, 0.0f); material1(); glutSolidTeapot(5.0); glPopMatrix();//teapot2 glPushMatrix();//teapot2 - blue glTranslatef(-20.0f, 4.0f, 20.0f); glRotatef(pot_rot, 0.0f, 1.0f, 0.0f); material2(); glutSolidTeapot(5.0); glPopMatrix();//teapot2 glPushMatrix();//teapot1 - gold and textured (just for fun) glEnable(GL_TEXTURE_2D); glTranslatef(20.0f, 4.0f, -20.0f); glRotatef(-pot_rot, 0.0f, 1.0f, 0.0f); material4(); glutSolidTeapot(5.0); glDisable(GL_TEXTURE_2D); glPopMatrix();//teapot1 glPushMatrix();//teapot3 - green glTranslatef(20.0f, 4.0f, 20.0f); glRotatef (45.0f, 0.0f, 1.0f, 0.0f); material3(); glutSolidTeapot(5.0); glPopMatrix();//teapot3 // return to view matrix glPopMatrix(); //glRasterPos2f(rand()%1000-500,rand()%1000-500); glGetFloatv(GL_CURRENT_RASTER_POSITION, ras_pos); stat_counter++; if (stat_counter >= 15) { glColor3f(1.0f, 0.0f, 0.0f); glRasterPos2f(ras_pos[0], ras_pos[1]); } glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, 'a'); // display the secondary (offscreen) buffer glutSwapBuffers(); } /** function setupLighting: this function is responsible for setting up the light's position, as well as the ambient, diffuse and specular lighting. */ void setupLighting() { // Variables for the spotlight that don't change float spot_cutoff = 35; float spot_exp = 30; // Make sure you're in MODELVIEW before you do this... glMatrixMode(GL_MODELVIEW); // Enable the lighting features glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_LIGHT2); // Update all of the spotlight properties glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, &spot_cutoff); glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, &spot_exp); // The second light - ambient glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_light2); // The third light - directional properties glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse_light3); glLightfv(GL_LIGHT2, GL_SPECULAR, specular_light3); glLightfv(GL_LIGHT2, GL_POSITION, light_position3); glLightfv (GL_LIGHT2, GL_SPOT_DIRECTION, spot_direction3); } // This function I can't take credit for - it came from the book, // and seemed to get the job done. It sets up a checkboard texture void setupCheckerboard() { int c, i, j; for (i = 0; i < 256; i++) { for (j = 0; j < 256; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkerboard[i][j][0] = (GLubyte)c; checkerboard[i][j][1] = (GLubyte)c; checkerboard[i][j][2] = (GLubyte)c; } } } // This function loads in a bitmap from file void setupQualImage() { int counter = 0; int i, j; char r, g, b; FILE* filePtr; r = g = b = 0; filePtr = fopen("C:\\smiley.bmp", "r"); if (filePtr == NULL){} //exit(1); // remove the first 54 bytes (header) for (counter = 0; counter < 54; counter++) { fscanf (filePtr, "%c", &r); } for (i = 255; i >= 0; i--) { for (j = 0; j < 256; j++) { fscanf (filePtr, "%c", &b); qual_image[i][j][0] = (GLubyte)b; fscanf (filePtr, "%c", &g); qual_image[i][j][1] = (GLubyte)g; fscanf (filePtr, "%c", &r); qual_image[i][j][2] = (GLubyte)r; } } fclose(filePtr); } // Here is the initialization function void init() { int i, j; // Set up fog color GLfloat fog_color[3] = {0.8f, 0.8f, 0.8f}; // Setup camera parameters, switching to PROJECTION mode glMatrixMode(GL_PROJECTION); // Clear the matrix glLoadIdentity(); // 60 degrees, aspect ratio of 1, near and far clipping gluPerspective(60.0f, 1.0, 0.1, 1000); // Always return to MODELVIEW for safety glMatrixMode(GL_MODELVIEW); setupLighting(); // Remove unwanted triangles glEnable(GL_DEPTH_TEST); // Set the background color glClearColor (0.8f, 0.8f, 0.8f, 1.0f); glEnable (GL_TEXTURE_2D); // setup textures setupCheckerboard(); //setupQualImage(); // Ignore the padding glPixelStorei(GL_UNPACK_ALIGNMENT, 3); // Find unused numbers for the texture objects glGenTextures (1, &checkerTexObject); glGenTextures (2, &qualImage); // Form a new texture object glBindTexture (GL_TEXTURE_2D, checkerTexObject); // Let opengl know about the textures - passing all relevant information glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, checkerboard); glTexImage2D (GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, qual_image); // Setup the texturing mode. Here we repeat in case we 'overflow' // beyond the range of (0, 1] glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Setup the minification and magnification filters to bilinear filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Initialize the camera state for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { camera_state[i][j] = 0; } } camera_state[0][0] = 1.0f; camera_state[1][1] = 1.0f; camera_state[2][2] = 1.0f; camera_state[3][3] = 1.0f; // Setup fog parameters (note it has not yet been enabled) glEnable (GL_FOG); glFogf(GL_FOG_MODE, GL_EXP); glFogf(GL_FOG_DENSITY, 0.003); glFogfv(GL_FOG_COLOR, fog_color); glHint (GL_FOG_HINT, GL_FASTEST); // Setup the shade model glShadeModel (GL_SMOOTH); // the original position of the mouse camY = 30.0; camX = 0.0; camZ = 105.0; oldX = 0.0f; oldY = 0.0f; firstTime = 1; } // This is the callback function for mouse movement, which updates // the alpha and beta rotations of the camera. It then redisplays // the screen (calling paint) to update the actual camera state matrix. void mouseMoved (int x, int y) { GLfloat deltaX, deltaY; // prevent it from thinking we started at 0, 0 if (firstTime) { oldX = x; oldY = y; firstTime = 0; } deltaX = x-oldX; deltaY = y-oldY; // Moving left if (deltaX>0) { camAlpha+=deltaX*0.5; } // Moving right else if (deltaX<0) { camAlpha+=deltaX*0.5; } // Moving up if (deltaY>0) { camBeta+=deltaY*0.5; } // Moving down else if (deltaY<0) { camBeta+=deltaY*0.5; } oldX = x; oldY = y; glutPostRedisplay(); } void specialKeys(int key, int x, int y) { char c = (char)key; switch (c){ case GLUT_KEY_UP: camBeta-=3; break; case GLUT_KEY_DOWN: camBeta+=3; break; case GLUT_KEY_LEFT: camAlpha-=3; break; case GLUT_KEY_RIGHT: camAlpha+=3; break; } glutPostRedisplay(); } /** function keyPressed: this function is the callback for key events. See the documentation above for their assignments. */ void keyPressed (unsigned char key, int x, int y) { // First, convert to a char char c = (char)key; switch (c){ case 's': case 'S': camZ+=2; break; case 'e': case 'E': camZ-=2; break; case 'a': case 'A': camX-=2; break; case 'd': case 'D': camX+=2; break; case 'y': case 'Y': camY++; break; case 'n': case 'N': camY--; break; case 'k': if (numDivisions>1) numDivisions/=2; break; case 'l': if (numDivisions <= 64) numDivisions*=2; break; case 'w': wireframe_mode = 1; break; case 'W': wireframe_mode = 0; break; case 't': texture_mode = 1; break; case 'T': texture_mode = 0; break; case 'g': spot_rot+=5; break; case 'G': spot_rot-=5; break; case 27: exit(1); break; case 'p': glEnable(GL_LIGHT0); break; case 'P': glDisable(GL_LIGHT0); break; case 'o': glEnable(GL_LIGHT1); break; case 'O': glDisable(GL_LIGHT1); break; case 'i': glEnable(GL_LIGHT2); break; case 'I': glDisable(GL_LIGHT2); break; } // Redraw the screen glutPostRedisplay(); } // I set up a menu function so that it would be easier to turn on/off // some of the options. void menuFunction(int value) { firstTime = 1; switch (value) { case 1: glEnable(GL_LIGHT1); break; case 2: glDisable(GL_LIGHT1); break; case 3: glEnable(GL_LIGHT0); break; case 4: glDisable(GL_LIGHT0); break; case 5: glEnable(GL_LIGHT2); break; case 6: glDisable(GL_LIGHT2); break; case 9: glEnable (GL_FOG); break; case 10: glDisable (GL_FOG); break; case 11: image_count = 0; break; case 12: image_count = 1; break; case 13: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); break; case 14: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); break; } } // The idle function is used to animate the pots. void idleFunc() { pot_rot++; if (pot_rot> 360) pot_rot = 0; glutPostRedisplay(); } // A self-explanatory function void setupMenuSystem() { // Menuing system glutCreateMenu(menuFunction); glutAddMenuEntry ("Turn on ambient",1); glutAddMenuEntry ("Turn off ambient", 2); glutAddMenuEntry ("Turn on spot", 3); glutAddMenuEntry ("Turn off spot", 4); glutAddMenuEntry ("Turn on directional", 5); glutAddMenuEntry ("Turn off directional", 6); glutAddMenuEntry ("Turn on fog", 9); glutAddMenuEntry ("Turn off fog", 10); glutAddMenuEntry ("Checker texture", 11); glutAddMenuEntry ("Smiley texture", 12); glutAddMenuEntry ("Bilinear Filtering", 13); glutAddMenuEntry ("Nearest Filtering", 14); glutAttachMenu(GLUT_RIGHT_BUTTON); } /** MAIN: the entry point into the program, this function sets the window parameters, callback functions, initializes state variables, and then goes into GLs main event-processing loop. */ void main (void) { // Double-buffered, RGBA bit depth, z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); // Nice, big-ol' window glutInitWindowSize(800, 800); // Position and show the window with a title glutInitWindowPosition(300, 0); glutCreateWindow ("CSC 6820 Project 2: Jeff Chastine"); // Callbacks for display, keys pressed, and mouse being clicked glutDisplayFunc (paint); glutKeyboardFunc (keyPressed); glutSpecialFunc(specialKeys); glutPassiveMotionFunc (mouseMoved); glutIdleFunc (idleFunc); setupMenuSystem(); // initialize variables init(); glutFullScreen(); // Start main loop glutMainLoop(); }