2 * CITS2231 Graphics Scene Editor
\r
3 * @author Ashley Tyndall (20915779)
\r
12 #include <GL/glut.h>
\r
16 // Type definitions for vertex-coordinates, normals, texture-coordinates,
\r
17 // and triangles (via the indices of 3 vertices).
\r
18 typedef GLfloat vertex[3];
\r
19 typedef GLfloat normal[3];
\r
20 typedef GLfloat texCoord[2];
\r
21 typedef GLint vertexIndex;
\r
22 typedef vertexIndex triangle[3];
\r
24 // A type for a mesh
\r
26 int nVertices; // The number of vertices in the mesh
\r
27 vertex* vertices; // Array with coordinates of vertices
\r
28 normal* normals; // Array with normals of vertices
\r
29 texCoord* texCoords; // Array with texture-coordinates of vertices
\r
30 int nTriangles; // The number of triangles in the mesh
\r
31 triangle* triangles; // Array of trangles via 3 indices into "vertices"
\r
34 #define NMESH 54 // The number of meshes (in the models-textures dir)
\r
35 mesh* meshes[NMESH]; // An array of pointers to the meshes - see getMesh
\r
37 // A type for a 2D texture, with height and width in pixels
\r
41 GLubyte *rgbData; // Array of bytes with the colour data for the texture
\r
44 #define NTEXTURE 30 // The number of textures (in the models-textures dir)
\r
45 texture* textures[NTEXTURE]; // An array of texture pointers - see getTexture
\r
48 // You'll need to add scale, rotation, material, mesh number, etc.,
\r
49 // to this structure
\r
58 ROTATION_TEXTURE_SCALE,
\r
63 MATERIAL_AMBIENT_RGB,
\r
64 MATERIAL_DIFFUSE_RGB,
\r
65 MATERIAL_SPECULAR_RGB,
\r
68 MATERIAL_GREEN_ADSS,
\r
73 LIGHT_RGBALL_LIGHT_1,
\r
75 LIGHT_RGBALL_LIGHT_2
\r
79 const char *textureMenuEntries[NTEXTURE] = {
\r
80 "1 Plain", "2 Rust", "3 Concrete", "4 Carpet", "5 Beach Sand",
\r
81 "6 Rocky", "7 Brick", "8 Water", "9 Paper", "10 Marble",
\r
82 "11 Wood", "12 Scales", "13 Fur", "14 Denim", "15 Hessian",
\r
83 "16 Orange Peel", "17 Ice Crystals", "18 Grass", "19 Corrugated Iron", "20 Styrofoam",
\r
84 "21 Bubble Wrap", "22 Leather", "23 Camouflage", "24 Asphalt", "25 Scratched Ice",
\r
85 "26 Rattan", "27 Snow", "28 Dry Mud", "29 Old Concrete", "30 Leopard Skin"
\r
88 const char *objectMenuEntries[NMESH] = {
\r
89 "1 Thin Dinosaur","2 Big Dog","3 Saddle Dinosaur", "4 Dragon", "5 Cleopatra",
\r
90 "6 Bone I", "7 Bone II", "8 Rabbit", "9 Long Dragon", "10 Buddha",
\r
91 "11 Sitting Rabbit", "12 Frog", "13 Cow", "14 Monster", "15 Sea Horse",
\r
92 "16 Head", "17 Pelican", "18 Horse", "19 Kneeling Angel", "20 Porsche I",
\r
93 "21 Truck", "22 Statue of Liberty", "23 Sitting Angel", "24 Metal Part", "25 Car",
\r
94 "26 Apatosaurus", "27 Airliner", "28 Motorbike", "29 Dolphin", "30 Spaceman",
\r
95 "31 Winnie the Pooh", "32 Shark", "33 Crocodile", "34 Toddler", "35 Fat Dinosaur",
\r
96 "36 Chihuahua", "37 Sabre-toothed Tiger", "38 Lioness", "39 Fish", "40 Horse (head down)",
\r
97 "41 Horse (head up)", "42 Skull", "43 Fighter Jet I", "44 Toad", "45 Convertible",
\r
98 "46 Porsche II", "47 Hare", "48 Vintage Car", "49 Fighter Jet II", "50 Winged Monkey",
\r
99 "51 Chef", "52 Parasaurolophus", "53 Rooster", "54 T-rex"
\r
102 #define MAXOBJECTS 256
\r
103 SceneObject sceneObjs[MAXOBJECTS]; // An array with details of the objects in a scene
\r
104 int nObjects=0; // How many objects there are in the scene currently.
\r
106 // Directories containing models
\r
107 char *dirDefault1 = "models-textures";
\r
108 char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures";
\r
110 char dataDir[200]; // Stores the directory name for the meshes and textures.
\r
112 static GLfloat floorVertices[4][3] = {
\r
113 { -1000.0, 0.0, 1000.0 },
\r
114 { 1000.0, 0.0, 1000.0 },
\r
115 { 1000.0, 0.0, -1000.0 },
\r
116 { -1000.0, 0.0, -1000.0 },
\r
119 static GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light
\r
120 static GLfloat lightPosition[4];
\r
122 int moving, startx, starty;
\r
123 int lightMoving = 0, lightStartX, lightStartY;
\r
125 /* Time varying or user-controled variables. */
\r
126 static float jump = 0.0;
\r
127 static float lightAngle = 0.0, lightHeight = 20;
\r
128 GLfloat angle = -150; /* in degrees */
\r
129 GLfloat angle2 = 30; /* in degrees */
\r
132 * Prints out error message when file cannot be read
\r
133 * @param fileName Name of file that could not be read
\r
135 void fileErr(char* fileName) {
\r
136 printf("Error reading file: %s\n", fileName);
\r
137 printf("If not in the CSSE labs, you will need to include the directory containing\n");
\r
138 printf("the models on the command line, or put it in the same folder as the exectutable.");
\r
139 exit(EXIT_FAILURE);
\r
143 * Reads .bmp texture files and converts them to a texture object
\r
144 * @param fileName .bmp texture file
\r
145 * @return texture object
\r
147 texture* loadTexture(char *fileName) {
\r
148 texture* t = malloc(sizeof (texture));
\r
151 t->rgbData = LoadDIBitmap(fileName, &info);
\r
152 t->height=info->bmiHeader.biHeight;
\r
153 t->width=info->bmiHeader.biWidth;
\r
159 * Reads .x files and converts them to a mesh object
\r
160 * @param fileName .x mesh file
\r
161 * @return mesh object
\r
163 mesh* loadMesh(char* fileName) {
\r
164 mesh* m = malloc(sizeof (mesh));
\r
165 FILE* fp = fopen(fileName, "r");
\r
166 char line[256] = "";
\r
167 int lineBuffSize = 256;
\r
169 if(fp == NULL) fileErr(fileName);
\r
171 while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 )
\r
172 fgets(line, lineBuffSize, fp);
\r
174 fscanf(fp, "%d;\n", &(m->nVertices));
\r
175 m->vertices = malloc(m->nVertices * sizeof(vertex));
\r
176 for(int i=0; i < m->nVertices; i++)
\r
177 fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) );
\r
179 fscanf(fp, "%d;\n", &(m->nTriangles));
\r
180 m->triangles = malloc(m->nTriangles * sizeof(triangle));
\r
181 for(int i=0; i < m->nTriangles; i++)
\r
182 fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2);
\r
184 while(strcmp(line," MeshNormals {\r\n") != 0 && strcmp(line," MeshNormals {\n") != 0)
\r
185 fgets(line, lineBuffSize, fp);
\r
187 fgets(line, lineBuffSize, fp);
\r
188 m->normals = malloc(m->nVertices * sizeof(normal));
\r
189 for(int i=0; i < m->nVertices; i++)
\r
190 fscanf(fp, "%f; %f; %f;%*[;,]\n",
\r
191 &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2]));
\r
193 while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0)
\r
194 fgets(line, lineBuffSize, fp);
\r
196 fgets(line, lineBuffSize, fp);
\r
197 m->texCoords = malloc(m->nVertices * sizeof(texCoord));
\r
198 for(int i=0; i < m->nVertices; i++)
\r
199 fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) );
\r
205 // [You may want to add to this function.]
\r
207 * Loads mesh[i] if it isn't already loaded.
\r
208 * You must call getMesh(i) at least once before using mesh[i].
\r
212 void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded.
\r
213 char fileName[220];
\r
214 if(i>=NMESH || i<0) {
\r
215 printf("Error in getMesh - wrong model number");
\r
218 if(meshes[i] != NULL)
\r
220 sprintf(fileName, "%s/model%d.x", dataDir, i+1);
\r
221 meshes[i] = loadMesh(fileName);
\r
225 * Loads texture i if it isn't already loaded
\r
227 * After calling getTexture(i), you can make texture i the current texture using
\r
228 * glBindTexture(GL_TEXTURE_2D, i);
\r
229 * Use i=0 to return to the default plain texture.
\r
231 * You can then scale the texture via:
\r
232 * glMatrixMode(GL_TEXTURE);
\r
233 * See the textbook, section 8.8.3.
\r
235 * You must call getTexture(i) at least once before using texture i.
\r
236 * @param i Texture ID
\r
238 void getTexture(int i) {
\r
239 char fileName[220];
\r
240 if(i<1 || i>NTEXTURE) {
\r
241 printf("Error in getTexture - wrong texture number");
\r
244 if(textures[i-1] != NULL)
\r
246 sprintf(fileName, "%s/texture%d.bmp", dataDir, i);
\r
248 textures[i-1] = loadTexture(fileName);
\r
250 glBindTexture(GL_TEXTURE_2D, i);
\r
252 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height,
\r
253 0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData);
\r
254 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB,
\r
255 GL_UNSIGNED_BYTE, textures[i-1]->rgbData);
\r
256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
\r
257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
\r
258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
\r
259 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
\r
261 glBindTexture(GL_TEXTURE_2D, 0); // Back to default texture
\r
265 * Event hander for main menu events
\r
266 * @param id ID of menu item selected
\r
268 void processMainEvents(int id) {
\r
270 case ROTATE_MOVE_CAMERA:
\r
274 case POSITION_SCALE:
\r
278 case ROTATION_TEXTURE_SCALE:
\r
283 exit(EXIT_SUCCESS);
\r
289 * Event hander for materials menu events
\r
290 * @param id ID of menu item selected
\r
292 void processMaterialEvents(int id) {
\r
294 case MATERIAL_ALL_RGB:
\r
298 case MATERIAL_AMBIENT_RGB:
\r
302 case MATERIAL_DIFFUSE_RGB:
\r
306 case MATERIAL_SPECULAR_RGB:
\r
310 case MATERIAL_ALL_ADSS:
\r
314 case MATERIAL_RED_ADSS:
\r
318 case MATERIAL_GREEN_ADSS:
\r
322 case MATERIAL_BLUE_ADSS:
\r
330 * Event hander for light menu events
\r
331 * @param id ID of menu item selected
\r
333 void processLightEvents(int id) {
\r
335 case LIGHT_MOVE_LIGHT_1:
\r
339 case LIGHT_RGBALL_LIGHT_1:
\r
343 case LIGHT_MOVE_LIGHT_2:
\r
347 case LIGHT_RGBALL_LIGHT_2:
\r
355 * Event hander for object menu events
\r
356 * @param id ID of object selected
\r
358 void processObjectEvents(int id) {
\r
363 * Event hander for texture menu events
\r
364 * @param id ID of texutre selected
\r
366 void processTextureEvents(int id) {
\r
371 * Event hander for ground texture menu events
\r
372 * @param id ID of ground texture selected
\r
374 void processGTextureEvents(int id) {
\r
379 * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number
\r
380 * @param numToRound Number to round
\r
381 * @param multiple Multiple to round up to
\r
382 * @return Rounded number
\r
384 int roundUp(int numToRound, int multiple) {
\r
385 if(multiple == 0) {
\r
389 int remainder = numToRound % multiple;
\r
390 if (remainder == 0)
\r
392 return numToRound + multiple - remainder;
\r
396 * Makes a submenu from an array of items, splitting the list into subsubmenus
\r
397 * of only 10 items.
\r
398 * @param menuEntries Array of menu items
\r
399 * @param menuEntriesSize Size of menuEntries
\r
400 * @param callback Callback function for this array of menu items
\r
401 * @return Reference to menu created
\r
403 int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) {
\r
404 if ( menuEntriesSize == 0 ) return -1;
\r
406 int menuNumber = roundUp(menuEntriesSize, 10) / 10;
\r
407 int submenuObjects[menuNumber-1];
\r
409 for( int i = 0; i < menuNumber; i++ ) {
\r
410 submenuObjects[i] = glutCreateMenu(callback);
\r
411 int startNum = i*11 - (i-1);
\r
412 for ( int j = startNum - 1; j < (startNum+9); j++ ) {
\r
413 if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array
\r
414 glutAddMenuEntry( menuEntries[j], j + 1 );
\r
418 int mainMenu = glutCreateMenu(callback);
\r
419 for ( int i = 0; i < menuNumber; i++ ) {
\r
420 char name[10]; // buffer to hold name
\r
421 int startNum = i*11 - (i-1);
\r
422 int endNum = startNum + 9;
\r
423 if ( i == menuNumber - 1 ) { // We're on the last one
\r
424 endNum = startNum + (menuEntriesSize - startNum); // Work out final number
\r
426 sprintf(name, "%d-%d", startNum, endNum);
\r
427 glutAddSubMenu( name, submenuObjects[i] );
\r
434 * Creates menu for program
\r
437 // Construct material menu
\r
438 int materialMenu = glutCreateMenu(processMaterialEvents);
\r
439 glutAddMenuEntry("All R/G/B", MATERIAL_ALL_RGB);
\r
440 glutAddMenuEntry("Ambient R/G/B", MATERIAL_AMBIENT_RGB);
\r
441 glutAddMenuEntry("Diffuse R/G/B", MATERIAL_DIFFUSE_RGB);
\r
442 glutAddMenuEntry("Specular R/G/B", MATERIAL_SPECULAR_RGB);
\r
443 glutAddMenuEntry("All Amb/Diff/Spec/Shine", MATERIAL_ALL_ADSS);
\r
444 glutAddMenuEntry("Red Amb/Diff/Spec/Shine", MATERIAL_RED_ADSS);
\r
445 glutAddMenuEntry("Green Amb/Diff/Spec/Shine", MATERIAL_GREEN_ADSS);
\r
446 glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", MATERIAL_BLUE_ADSS);
\r
448 // Construct light menu
\r
449 int lightMenu = glutCreateMenu(processLightEvents);
\r
450 glutAddMenuEntry("Move Light 1", LIGHT_MOVE_LIGHT_1);
\r
451 glutAddMenuEntry("R/G/B/All Light 1", LIGHT_RGBALL_LIGHT_1);
\r
452 glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2);
\r
453 glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2);
\r
455 // Construct object menu
\r
456 int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]);
\r
457 int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, processObjectEvents );
\r
459 // Construct texture / ground texture menus
\r
460 int textureMenuEntriesSize = sizeof(textureMenuEntries) / sizeof(textureMenuEntries[0]);
\r
461 int textureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processTextureEvents );
\r
462 int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processGTextureEvents );
\r
464 // Construct main menu
\r
465 glutCreateMenu(processMainEvents);
\r
466 //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA);
\r
467 //glutAddSubMenu("Add object", objectMenu);
\r
468 //glutAddMenuEntry("Position/Scale", POSITION_SCALE);
\r
469 //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE);
\r
470 //glutAddSubMenu("Material", materialMenu);
\r
471 //glutAddSubMenu("Texture", textureMenu);
\r
472 //glutAddSubMenu("Ground texture", gTextureMenu);
\r
473 //glutAddSubMenu("Lights", lightMenu);
\r
474 glutAddMenuEntry("Exit", EXIT);
\r
476 // Bind to right mouse button
\r
477 glutAttachMenu(GLUT_RIGHT_BUTTON);
\r
481 * Called when window is resized
\r
482 * @param w New width
\r
483 * @param h New height
\r
485 void windowReshape(int w, int h) {
\r
486 GLdouble near = -10.0;
\r
487 GLdouble far = 10.0;
\r
489 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
\r
490 glMatrixMode(GL_PROJECTION);
\r
493 glOrtho(near, far, near*(GLfloat)h/(GLfloat)w,
\r
494 far*(GLfloat)h/(GLfloat)w, near, far);
\r
496 glOrtho(near*(GLfloat)w/(GLfloat)h,
\r
497 far*(GLfloat)w/(GLfloat)h, near, far, near, far);
\r
498 glMatrixMode(GL_MODELVIEW);
\r
503 * Called when mouse event occurs
\r
504 * @param btn Mouse button
\r
505 * @param state State of mouse button
\r
506 * @param x Mouse x position
\r
507 * @param y Mouse y position
\r
509 /*void mouse(int btn, int state, int x, int y) {
\r
513 mouse(int button, int state, int x, int y)
\r
515 if (button == GLUT_LEFT_BUTTON) {
\r
516 if (state == GLUT_DOWN) {
\r
521 if (state == GLUT_UP) {
\r
525 if (button == GLUT_MIDDLE_BUTTON) {
\r
526 if (state == GLUT_DOWN) {
\r
531 if (state == GLUT_UP) {
\r
538 motion(int x, int y)
\r
541 angle = angle + (x - startx);
\r
542 angle2 = angle2 + (y - starty);
\r
545 glutPostRedisplay();
\r
548 lightAngle += (x - lightStartX)/40.0;
\r
549 lightHeight += (lightStartY - y)/20.0;
\r
552 glutPostRedisplay();
\r
561 glDisable(GL_LIGHTING);
\r
563 //if (useTexture) {
\r
564 // glEnable(GL_TEXTURE_2D);
\r
567 /*glBegin(GL_QUADS);
\r
568 glTexCoord2f(0.0, 0.0);
\r
569 glVertex3fv(floorVertices[0]);
\r
570 glTexCoord2f(0.0, 16.0);
\r
571 glVertex3fv(floorVertices[1]);
\r
572 glTexCoord2f(16.0, 16.0);
\r
573 glVertex3fv(floorVertices[2]);
\r
574 glTexCoord2f(16.0, 0.0);
\r
575 glVertex3fv(floorVertices[3]);
\r
578 /*if (useTexture) {
\r
579 glDisable(GL_TEXTURE_2D);
\r
582 glEnable(GL_LIGHTING);
\r
589 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
592 0.0, 0.0, 60.0, /* eye is at (x,y,z) */
\r
593 0.0, 0.0, 0.0, /* center is at (x,y,z) */
\r
594 0.0, -1.0, 0.0 /* up is in postivie Y direction */
\r
597 /* Reposition the light source. */
\r
598 lightPosition[0] = 12*cos(lightAngle);
\r
599 lightPosition[1] = lightHeight;
\r
600 lightPosition[2] = 12*sin(lightAngle);
\r
601 lightPosition[3] = 0.0;
\r
604 /* Perform scene rotations based on user mouse input. */
\r
605 glRotatef(angle2, 1.0, 0.0, 0.0);
\r
606 glRotatef(angle, 0.0, 1.0, 0.0);
\r
608 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
\r
610 glEnable(GL_BLEND);
\r
611 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
613 glDisable(GL_BLEND);
\r
617 //glTranslatef(0.0, 0.0, 0.0);
\r
619 glutSolidTeapot(30); // Draw teapot for test
\r
623 glDisable(GL_LIGHTING);
\r
624 glColor3f(1.0, 1.0, 1.0);
\r
626 /* Draw a yellow ball at the light source. */
\r
627 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
\r
628 glutSolidSphere(1.0, 5, 5);
\r
630 glEnable(GL_LIGHTING);
\r
639 * init function; sets initial OpenGL state
\r
642 glMatrixMode(GL_PROJECTION);
\r
646 60.0, /* field of view in degree */
\r
647 1.0, /* aspect ratio */
\r
652 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
\r
653 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
\r
654 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
\r
655 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
\r
656 glEnable(GL_LIGHT0);
\r
657 glEnable(GL_LIGHTING);
\r
659 glMatrixMode(GL_MODELVIEW);
\r
665 * @param argc Number of arguments
\r
666 * @param argv Array of arguments
\r
667 * @return Program exit code
\r
669 int main(int argc, char **argv) {
\r
671 strcpy(dataDir, argv[1]);
\r
672 else if(opendir(dirDefault1))
\r
673 strcpy(dataDir, dirDefault1);
\r
674 else if(opendir(dirDefault2))
\r
675 strcpy(dataDir, dirDefault2);
\r
676 else fileErr(dirDefault1);
\r
678 for(int i=0; i<NMESH; i++) meshes[i]=NULL;
\r
679 for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;
\r
681 glutInit(&argc, argv);
\r
683 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
\r
685 glutInitWindowSize(500, 500);
\r
686 glutCreateWindow("Scene Editor");
\r
688 glShadeModel(GL_SMOOTH); // Enables Smooth Shading
\r
689 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
\r
690 glClearDepth(1.0f); // Depth Buffer Setup
\r
691 glEnable(GL_DEPTH_TEST); // Enables Depth Testing
\r
692 glDepthFunc(GL_LEQUAL); // the type
\r
693 glEnable(GL_CULL_FACE);
\r
694 glEnable(GL_TEXTURE_2D);
\r
697 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
\r
699 glutReshapeFunc(windowReshape);
\r
700 glutDisplayFunc(display);
\r
701 glutMouseFunc(mouse);
\r
702 glutMotionFunc(motion);
\r