(no commit message)
[atyndall/cits2231.git] / scene.c
1 /**\r
2  * CITS2231 Graphics Scene Editor\r
3  * @author Ashley Tyndall (20915779)\r
4  */\r
5 \r
6 #include <stdlib.h>\r
7 #include <stdio.h>\r
8 #include <dirent.h>\r
9 #include <string.h>\r
10 #include <math.h>\r
11 #include <GL/gl.h>\r
12 #include <GL/glut.h>\r
13 \r
14 #include "bitmap.h"\r
15 \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
23 \r
24 // A type for a mesh\r
25 typedef struct {         \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
32 } mesh;\r
33 \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
36 \r
37 // A type for a 2D texture, with height and width in pixels\r
38 typedef struct {\r
39     int height;\r
40     int width;\r
41     GLubyte *rgbData;   // Array of bytes with the colour data for the texture\r
42 } texture;\r
43 \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
46 \r
47 typedef struct {  \r
48     // You'll need to add scale, rotation, material, mesh number, etc.,\r
49     // to this structure\r
50     float x,y,z;\r
51 } SceneObject;\r
52 \r
53 // Menu enum\r
54 enum menu {\r
55   // Main menu\r
56   ROTATE_MOVE_CAMERA,\r
57   POSITION_SCALE,\r
58   ROTATION_TEXTURE_SCALE,\r
59   EXIT,\r
60 \r
61   // Material submenu\r
62   MATERIAL_ALL_RGB,\r
63   MATERIAL_AMBIENT_RGB,\r
64   MATERIAL_DIFFUSE_RGB,\r
65   MATERIAL_SPECULAR_RGB,\r
66   MATERIAL_ALL_ADSS,\r
67   MATERIAL_RED_ADSS,\r
68   MATERIAL_GREEN_ADSS,\r
69   MATERIAL_BLUE_ADSS,\r
70 \r
71   // Light submenu\r
72   LIGHT_MOVE_LIGHT_1,\r
73   LIGHT_RGBALL_LIGHT_1,\r
74   LIGHT_MOVE_LIGHT_2,\r
75   LIGHT_RGBALL_LIGHT_2\r
76 };\r
77 \r
78 // Menu arrays\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
86 };\r
87 \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
100 };\r
101 \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
105 \r
106 // Directories containing models\r
107 char *dirDefault1 = "models-textures";\r
108 char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures";\r
109 \r
110 char dataDir[200];  // Stores the directory name for the meshes and textures.\r
111 \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
117 };\r
118 \r
119 static GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light\r
120 static GLfloat lightPosition[4];\r
121 static float lightAngle = 10.0, lightHeight = 20;\r
122 \r
123 /**\r
124  * Prints out error message when file cannot be read\r
125  * @param fileName Name of file that could not be read\r
126  */\r
127 void fileErr(char* fileName) {\r
128     printf("Error reading file: %s\n", fileName);\r
129     printf("If not in the CSSE labs, you will need to include the directory containing\n");\r
130     printf("the models on the command line, or put it in the same folder as the exectutable.");\r
131     exit(EXIT_FAILURE);\r
132 }  \r
133 \r
134 /**\r
135  * Reads .bmp texture files and converts them to a texture object\r
136  * @param fileName .bmp texture file\r
137  * @return texture object\r
138  */\r
139 texture* loadTexture(char *fileName) {\r
140     texture* t = malloc(sizeof (texture));\r
141     BITMAPINFO *info;\r
142 \r
143     t->rgbData = LoadDIBitmap(fileName, &info);\r
144     t->height=info->bmiHeader.biHeight;\r
145     t->width=info->bmiHeader.biWidth;\r
146 \r
147     return t;\r
148 }\r
149 \r
150 /**\r
151  * Reads .x files and converts them to a mesh object\r
152  * @param fileName .x mesh file\r
153  * @return mesh object\r
154  */\r
155 mesh* loadMesh(char* fileName) {\r
156     mesh* m = malloc(sizeof (mesh));\r
157     FILE* fp = fopen(fileName, "r");\r
158     char line[256] = "";\r
159     int lineBuffSize = 256;\r
160 \r
161     if(fp == NULL) fileErr(fileName);\r
162 \r
163     while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 )\r
164         fgets(line, lineBuffSize, fp);\r
165 \r
166     fscanf(fp, "%d;\n", &(m->nVertices));\r
167     m->vertices = malloc(m->nVertices * sizeof(vertex));\r
168     for(int i=0; i < m->nVertices; i++)\r
169         fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) );\r
170 \r
171     fscanf(fp, "%d;\n", &(m->nTriangles));\r
172     m->triangles = malloc(m->nTriangles * sizeof(triangle));\r
173     for(int i=0; i < m->nTriangles; i++)\r
174         fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2);\r
175 \r
176     while(strcmp(line,"  MeshNormals {\r\n") != 0 && strcmp(line,"  MeshNormals {\n") != 0)\r
177         fgets(line, lineBuffSize, fp);\r
178 \r
179     fgets(line, lineBuffSize, fp);\r
180     m->normals = malloc(m->nVertices * sizeof(normal));\r
181     for(int i=0; i < m->nVertices; i++)\r
182         fscanf(fp, "%f; %f; %f;%*[;,]\n",\r
183                &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2]));\r
184 \r
185     while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0)\r
186         fgets(line, lineBuffSize, fp);\r
187 \r
188     fgets(line, lineBuffSize, fp);\r
189     m->texCoords = malloc(m->nVertices * sizeof(texCoord));\r
190     for(int i=0; i < m->nVertices; i++)\r
191         fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) );\r
192     fclose(fp);\r
193     \r
194     return m;\r
195 }\r
196 \r
197 // [You may want to add to this function.]\r
198 /**\r
199  * Loads mesh[i] if it isn't already loaded.\r
200  * You must call getMesh(i) at least once before using mesh[i].\r
201  *\r
202  * @param i Mesh ID\r
203  */\r
204 void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded.  \r
205     char fileName[220];\r
206     if(i>=NMESH || i<0) {\r
207         printf("Error in getMesh - wrong model number");\r
208         exit(1);\r
209     }\r
210     if(meshes[i] != NULL)\r
211         return;\r
212     sprintf(fileName, "%s/model%d.x", dataDir, i+1);\r
213     meshes[i] = loadMesh(fileName);\r
214 }\r
215 \r
216 /**\r
217  * Loads texture i if it isn't already loaded\r
218  *\r
219  * After calling getTexture(i), you can make texture i the current texture using\r
220  *      glBindTexture(GL_TEXTURE_2D, i);\r
221  * Use i=0 to return to the default plain texture.\r
222  *\r
223  * You can then scale the texture via:\r
224  *      glMatrixMode(GL_TEXTURE);\r
225  * See the textbook, section 8.8.3.\r
226  *\r
227  * You must call getTexture(i) at least once before using texture i.\r
228  * @param i Texture ID\r
229  */\r
230 void getTexture(int i) {\r
231     char fileName[220];\r
232     if(i<1 || i>NTEXTURE) {\r
233         printf("Error in getTexture - wrong texture number");\r
234         exit(1);\r
235     }\r
236     if(textures[i-1] != NULL)\r
237         return;\r
238     sprintf(fileName, "%s/texture%d.bmp", dataDir, i);\r
239 \r
240     textures[i-1] = loadTexture(fileName);\r
241 \r
242     glBindTexture(GL_TEXTURE_2D, i);\r
243 \r
244     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height,\r
245                  0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
246     gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, \r
247                       GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
248     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\r
249     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\r
250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);\r
252 \r
253     glBindTexture(GL_TEXTURE_2D, 0);  // Back to default texture\r
254 }\r
255 \r
256 /**\r
257  * Event hander for main menu events\r
258  * @param id ID of menu item selected\r
259  */\r
260 void processMainEvents(int id) {\r
261   switch (id) {\r
262     case ROTATE_MOVE_CAMERA:\r
263       // Do stuff\r
264       break;\r
265 \r
266     case POSITION_SCALE:\r
267       // Do stuff\r
268       break;\r
269 \r
270     case ROTATION_TEXTURE_SCALE:\r
271       // Do stuff\r
272       break;\r
273 \r
274     case EXIT:\r
275       exit(EXIT_SUCCESS);\r
276 \r
277   }\r
278 }\r
279 \r
280 /**\r
281  * Event hander for materials menu events\r
282  * @param id ID of menu item selected\r
283  */\r
284 void processMaterialEvents(int id) {\r
285   switch (id) {\r
286     case MATERIAL_ALL_RGB:\r
287       // Do stuff\r
288       break;\r
289 \r
290     case MATERIAL_AMBIENT_RGB:\r
291       // Do stuff\r
292       break;\r
293 \r
294     case MATERIAL_DIFFUSE_RGB:\r
295       // Do stuff\r
296       break;\r
297 \r
298     case MATERIAL_SPECULAR_RGB:\r
299       // Do stuff\r
300       break;\r
301 \r
302     case MATERIAL_ALL_ADSS:\r
303       // Do stuff\r
304       break;\r
305 \r
306     case MATERIAL_RED_ADSS:\r
307       // Do stuff\r
308       break;\r
309 \r
310     case MATERIAL_GREEN_ADSS:\r
311       // Do stuff\r
312       break;\r
313 \r
314     case MATERIAL_BLUE_ADSS:\r
315       // Do stuff\r
316       break;\r
317 \r
318   }\r
319 }\r
320 \r
321 /**\r
322  * Event hander for light menu events\r
323  * @param id ID of menu item selected\r
324  */\r
325 void processLightEvents(int id) {\r
326   switch (id) {\r
327     case LIGHT_MOVE_LIGHT_1:\r
328       // Do stuff\r
329       break;\r
330 \r
331     case LIGHT_RGBALL_LIGHT_1:\r
332       // Do stuff\r
333       break;\r
334 \r
335     case LIGHT_MOVE_LIGHT_2:\r
336       // Do stuff\r
337       break;\r
338 \r
339     case LIGHT_RGBALL_LIGHT_2:\r
340       // Do stuff\r
341       break;\r
342 \r
343   }\r
344 }\r
345 \r
346 /**\r
347  * Event hander for object menu events\r
348  * @param id ID of object selected\r
349  */\r
350 void processObjectEvents(int id) {\r
351 \r
352 }\r
353 \r
354 /**\r
355  * Event hander for texture menu events\r
356  * @param id ID of texutre selected\r
357  */\r
358 void processTextureEvents(int id) {\r
359 \r
360 }\r
361 \r
362 /**\r
363  * Event hander for ground texture menu events\r
364  * @param id ID of ground texture selected\r
365  */\r
366 void processGTextureEvents(int id) {\r
367 \r
368 }\r
369 \r
370 /**\r
371  * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number\r
372  * @param numToRound Number to round\r
373  * @param multiple Multiple to round up to\r
374  * @return Rounded number\r
375  */\r
376 int roundUp(int numToRound, int multiple) {\r
377   if(multiple == 0) {\r
378     return numToRound;\r
379   }\r
380 \r
381   int remainder = numToRound % multiple;\r
382   if (remainder == 0)\r
383     return numToRound;\r
384   return numToRound + multiple - remainder;\r
385 }\r
386 \r
387 /**\r
388  * Makes a submenu from an array of items, splitting the list into subsubmenus\r
389  * of only 10 items.\r
390  * @param menuEntries Array of menu items\r
391  * @param menuEntriesSize Size of menuEntries\r
392  * @param callback Callback function for this array of menu items\r
393  * @return Reference to menu created\r
394  */\r
395 int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) {\r
396   if ( menuEntriesSize == 0 ) return -1;\r
397 \r
398   int menuNumber = roundUp(menuEntriesSize, 10) / 10;\r
399   int submenuObjects[menuNumber-1];\r
400 \r
401   for( int i = 0; i < menuNumber; i++ ) {\r
402     submenuObjects[i] = glutCreateMenu(callback);\r
403     int startNum = i*11 - (i-1);\r
404     for ( int j = startNum - 1; j < (startNum+9); j++ ) {\r
405       if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array\r
406       glutAddMenuEntry( menuEntries[j], j + 1 );\r
407     }\r
408   } \r
409 \r
410   int mainMenu = glutCreateMenu(callback);\r
411   for ( int i = 0; i < menuNumber; i++ ) {\r
412     char name[10]; // buffer to hold name\r
413     int startNum = i*11 - (i-1);\r
414     int endNum = startNum + 9;\r
415     if ( i == menuNumber - 1 ) { // We're on the last one\r
416       endNum = startNum + (menuEntriesSize - startNum); // Work out final number\r
417     }\r
418     sprintf(name, "%d-%d", startNum, endNum);\r
419     glutAddSubMenu( name, submenuObjects[i] );\r
420   }\r
421 \r
422   return mainMenu;\r
423 }\r
424 \r
425 /**\r
426  * Creates menu for program\r
427  */\r
428 void makeMenu() {\r
429   // Construct material menu\r
430   int materialMenu = glutCreateMenu(processMaterialEvents);\r
431   glutAddMenuEntry("All R/G/B", MATERIAL_ALL_RGB);\r
432   glutAddMenuEntry("Ambient R/G/B", MATERIAL_AMBIENT_RGB);\r
433   glutAddMenuEntry("Diffuse R/G/B", MATERIAL_DIFFUSE_RGB);\r
434   glutAddMenuEntry("Specular R/G/B", MATERIAL_SPECULAR_RGB);\r
435   glutAddMenuEntry("All Amb/Diff/Spec/Shine", MATERIAL_ALL_ADSS);\r
436   glutAddMenuEntry("Red Amb/Diff/Spec/Shine", MATERIAL_RED_ADSS);\r
437   glutAddMenuEntry("Green Amb/Diff/Spec/Shine", MATERIAL_GREEN_ADSS);\r
438   glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", MATERIAL_BLUE_ADSS);\r
439 \r
440   // Construct light menu\r
441   int lightMenu = glutCreateMenu(processLightEvents);\r
442   glutAddMenuEntry("Move Light 1", LIGHT_MOVE_LIGHT_1);\r
443   glutAddMenuEntry("R/G/B/All Light 1", LIGHT_RGBALL_LIGHT_1);\r
444   glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2);\r
445   glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2);\r
446 \r
447   // Construct object menu\r
448   int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]);\r
449   int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, processObjectEvents );\r
450 \r
451   // Construct texture / ground texture menus\r
452   int textureMenuEntriesSize = sizeof(textureMenuEntries) / sizeof(textureMenuEntries[0]);\r
453   int textureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processTextureEvents );\r
454   int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processGTextureEvents );\r
455 \r
456   // Construct main menu\r
457   glutCreateMenu(processMainEvents);\r
458   //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA);\r
459   //glutAddSubMenu("Add object", objectMenu);\r
460   //glutAddMenuEntry("Position/Scale", POSITION_SCALE);\r
461   //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE);\r
462   //glutAddSubMenu("Material", materialMenu);\r
463   //glutAddSubMenu("Texture", textureMenu);\r
464   //glutAddSubMenu("Ground texture", gTextureMenu);\r
465   //glutAddSubMenu("Lights", lightMenu);\r
466   glutAddMenuEntry("Exit", EXIT);\r
467 \r
468   // Bind to right mouse button\r
469   glutAttachMenu(GLUT_RIGHT_BUTTON);\r
470 }\r
471 \r
472 /**\r
473  * Called when window is resized\r
474  * @param w New width\r
475  * @param h New height\r
476  */\r
477 void windowReshape(int w, int h) {\r
478   GLdouble near = -10.0;\r
479   GLdouble far = 10.0;\r
480 \r
481   glViewport(0, 0, (GLsizei) w, (GLsizei) h);\r
482   glMatrixMode(GL_PROJECTION);\r
483   glLoadIdentity();\r
484   if (w <= h) \r
485     glOrtho(near, far, near*(GLfloat)h/(GLfloat)w,\r
486              far*(GLfloat)h/(GLfloat)w, near, far);\r
487   else\r
488     glOrtho(near*(GLfloat)w/(GLfloat)h,\r
489              far*(GLfloat)w/(GLfloat)h, near, far, near, far);\r
490    glMatrixMode(GL_MODELVIEW); \r
491    glLoadIdentity();\r
492 }\r
493 \r
494 /**\r
495  * Called when mouse event occurs\r
496  * @param btn Mouse button\r
497  * @param state State of mouse button\r
498  * @param x Mouse x position\r
499  * @param y Mouse y position\r
500  */\r
501 void mouse(int btn, int state, int x, int y) {\r
502   \r
503 }\r
504 \r
505 /**\r
506  * Draw a floor.\r
507  */\r
508 void drawFloor() {\r
509   glDisable(GL_LIGHTING);\r
510 \r
511   //if (useTexture) {\r
512   //  glEnable(GL_TEXTURE_2D);\r
513   //}\r
514 \r
515   glBegin(GL_QUADS);\r
516     glTexCoord2f(0.0, 0.0);\r
517     glVertex3fv(floorVertices[0]);\r
518     glTexCoord2f(0.0, 16.0);\r
519     glVertex3fv(floorVertices[1]);\r
520     glTexCoord2f(16.0, 16.0);\r
521     glVertex3fv(floorVertices[2]);\r
522     glTexCoord2f(16.0, 0.0);\r
523     glVertex3fv(floorVertices[3]);\r
524   glEnd();\r
525 \r
526   /*if (useTexture) {\r
527     glDisable(GL_TEXTURE_2D);\r
528   }*/\r
529 \r
530   glEnable(GL_LIGHTING);\r
531 }\r
532 \r
533 /**\r
534  * Display function\r
535  */\r
536 void display() {\r
537   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
538   glLoadIdentity();\r
539   gluLookAt(\r
540     40.0, 180.0, 60.0,  /* eye is at (0,8,60) */\r
541     0.0, 0.0,  0.0,  /* center is at (0,0,0) */\r
542     0.0, 1.0,  0.0   /* up is in postivie Y direction */\r
543     );\r
544 \r
545   /* Reposition the light source. */\r
546   lightPosition[0] = 12*cos(lightAngle);\r
547   lightPosition[1] = lightHeight;\r
548   lightPosition[2] = 12*sin(lightAngle);\r
549   lightPosition[3] = 0.0;\r
550 \r
551   glPushMatrix();\r
552     glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);\r
553 \r
554     glEnable(GL_BLEND);\r
555     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
556     drawFloor();\r
557     glDisable(GL_BLEND);\r
558 \r
559     glPushMatrix();\r
560       glLoadIdentity();\r
561       glColor3f(1.0, 0.0, 1.0);\r
562       glTranslatef(0.0, 0.0, -1.0);\r
563 \r
564       glutSolidTeapot(1); // Draw teapot for test\r
565     glPopMatrix();\r
566 \r
567     glPushMatrix();\r
568       glDisable(GL_LIGHTING);\r
569       glLoadIdentity();\r
570       glColor3f(1.0, 1.0, 1.0);\r
571 \r
572       /* Draw a yellow ball at the light source. */\r
573       glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);\r
574       glutSolidSphere(1.0, 5, 5);\r
575 \r
576       glEnable(GL_LIGHTING);\r
577     glPopMatrix();\r
578 \r
579   glPopMatrix();\r
580 \r
581   glutSwapBuffers();\r
582 }\r
583 \r
584 /**\r
585  * init function; sets initial OpenGL state\r
586  */\r
587 void init() {\r
588   glMatrixMode(GL_PROJECTION);\r
589 \r
590   gluPerspective(\r
591      60.0,  /* field of view in degree */\r
592       1.0,  /* aspect ratio */ \r
593       0.0,  /* Z near */\r
594     900.0   /* Z far */\r
595     );    \r
596 \r
597   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);\r
598   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);\r
599   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);\r
600   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);\r
601   glEnable(GL_LIGHT0);\r
602   glEnable(GL_LIGHTING);\r
603 \r
604   glMatrixMode(GL_MODELVIEW);\r
605 }\r
606 \r
607 /**\r
608  * Main function\r
609  * @param argc Number of arguments\r
610  * @param argv Array of arguments\r
611  * @return Program exit code\r
612  */\r
613 int main(int argc, char **argv) {\r
614   if(argc>1)\r
615     strcpy(dataDir, argv[1]);\r
616   else if(opendir(dirDefault1))\r
617     strcpy(dataDir, dirDefault1);\r
618   else if(opendir(dirDefault2))\r
619     strcpy(dataDir, dirDefault2);\r
620   else fileErr(dirDefault1);\r
621 \r
622   for(int i=0; i<NMESH; i++) meshes[i]=NULL;\r
623   for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;\r
624 \r
625   glutInit(&argc, argv);\r
626 \r
627   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);\r
628 \r
629   glutInitWindowSize(500, 500);\r
630   glutCreateWindow("Scene Editor");\r
631 \r
632   glShadeModel(GL_SMOOTH); // Enables Smooth Shading\r
633   glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background\r
634   glClearDepth(1.0f); // Depth Buffer Setup\r
635   glEnable(GL_DEPTH_TEST); // Enables Depth Testing\r
636   glDepthFunc(GL_LEQUAL);  // the type\r
637   glEnable(GL_CULL_FACE);\r
638   glEnable(GL_TEXTURE_2D);\r
639   glLineWidth(3.0);\r
640 \r
641   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);\r
642 \r
643   glutReshapeFunc(windowReshape);\r
644   glutDisplayFunc(display);\r
645   glutMouseFunc(mouse);\r
646 \r
647   makeMenu();\r
648 \r
649   init();\r
650 \r
651   glutMainLoop();\r
652 }\r

UCC git Repository :: git.ucc.asn.au