(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 #include <time.h>\r
14 \r
15 #include "bitmap.h"\r
16 \r
17 // Type definitions for vertex-coordinates, normals, texture-coordinates, \r
18 // and triangles (via the indices of 3 vertices).\r
19 typedef GLfloat vertex[3];\r
20 typedef GLfloat normal[3];\r
21 typedef GLfloat texCoord[2];\r
22 typedef GLint vertexIndex;\r
23 typedef vertexIndex triangle[3];\r
24 \r
25 // A type for a mesh\r
26 typedef struct {         \r
27     int nVertices;           //  The number of vertices in the mesh\r
28     vertex* vertices;        //  Array with coordinates of vertices\r
29     normal* normals;         //  Array with normals of vertices\r
30     texCoord* texCoords;     //  Array with texture-coordinates of vertices\r
31     int nTriangles;          //  The number of triangles in the mesh\r
32     triangle* triangles;     //  Array of trangles via 3 indices into "vertices"\r
33 } mesh;\r
34 \r
35 #define NMESH 54       // The number of meshes (in the models-textures dir)\r
36 mesh* meshes[NMESH];   // An array of pointers to the meshes - see getMesh\r
37 \r
38 // A type for a 2D texture, with height and width in pixels\r
39 typedef struct {\r
40     int height;\r
41     int width;\r
42     GLubyte *rgbData;   // Array of bytes with the colour data for the texture\r
43 } texture;\r
44 \r
45 #define NTEXTURE 30     // The number of textures (in the models-textures dir)\r
46 texture* textures[NTEXTURE];   // An array of texture pointers - see getTexture\r
47 \r
48 typedef struct {  \r
49     // You'll need to add scale, rotation, material, mesh number, etc.,\r
50     // to this structure\r
51     float x,y,z;\r
52 } SceneObject;\r
53 \r
54 // Menu enum\r
55 enum menu {\r
56   // Main menu\r
57   ROTATE_MOVE_CAMERA,\r
58   POSITION_SCALE,\r
59   ROTATION_TEXTURE_SCALE,\r
60   EXIT,\r
61 \r
62   // Material submenu\r
63   MATERIAL_ALL_RGB,\r
64   MATERIAL_AMBIENT_RGB,\r
65   MATERIAL_DIFFUSE_RGB,\r
66   MATERIAL_SPECULAR_RGB,\r
67   MATERIAL_ALL_ADSS,\r
68   MATERIAL_RED_ADSS,\r
69   MATERIAL_GREEN_ADSS,\r
70   MATERIAL_BLUE_ADSS,\r
71 \r
72   // Light submenu\r
73   LIGHT_MOVE_LIGHT_1,\r
74   LIGHT_RGBALL_LIGHT_1,\r
75   LIGHT_MOVE_LIGHT_2,\r
76   LIGHT_RGBALL_LIGHT_2\r
77 };\r
78 \r
79 // Menu arrays\r
80 const char *textureMenuEntries[NTEXTURE] = {\r
81   "1 Plain", "2 Rust", "3 Concrete", "4 Carpet", "5 Beach Sand",\r
82   "6 Rocky", "7 Brick", "8 Water", "9 Paper", "10 Marble",\r
83   "11 Wood", "12 Scales", "13 Fur", "14 Denim", "15 Hessian",\r
84   "16 Orange Peel", "17 Ice Crystals", "18 Grass", "19 Corrugated Iron", "20 Styrofoam",\r
85   "21 Bubble Wrap", "22 Leather", "23 Camouflage", "24 Asphalt", "25 Scratched Ice",\r
86   "26 Rattan", "27 Snow", "28 Dry Mud", "29 Old Concrete", "30 Leopard Skin"\r
87 };\r
88 \r
89 const char *objectMenuEntries[NMESH] = {\r
90   "1 Thin Dinosaur","2 Big Dog","3 Saddle Dinosaur", "4 Dragon", "5 Cleopatra",\r
91   "6 Bone I", "7 Bone II", "8 Rabbit", "9 Long Dragon", "10 Buddha",\r
92   "11 Sitting Rabbit", "12 Frog", "13 Cow", "14 Monster", "15 Sea Horse",\r
93   "16 Head", "17 Pelican", "18 Horse", "19 Kneeling Angel", "20 Porsche I",\r
94   "21 Truck", "22 Statue of Liberty", "23 Sitting Angel", "24 Metal Part", "25 Car",\r
95   "26 Apatosaurus", "27 Airliner", "28 Motorbike", "29 Dolphin", "30 Spaceman",\r
96   "31 Winnie the Pooh", "32 Shark", "33 Crocodile", "34 Toddler", "35 Fat Dinosaur",\r
97   "36 Chihuahua", "37 Sabre-toothed Tiger", "38 Lioness", "39 Fish", "40 Horse (head down)",\r
98   "41 Horse (head up)", "42 Skull", "43 Fighter Jet I", "44 Toad", "45 Convertible",\r
99   "46 Porsche II", "47 Hare", "48 Vintage Car", "49 Fighter Jet II", "50 Winged Monkey",\r
100   "51 Chef", "52 Parasaurolophus", "53 Rooster", "54 T-rex"\r
101 };\r
102 \r
103 #define MAXOBJECTS 256\r
104 SceneObject sceneObjs[MAXOBJECTS];  // An array with details of the objects in a scene\r
105 int nObjects=0;                     // How many objects there are in the scene currently.\r
106 \r
107 // Directories containing models\r
108 char *dirDefault1 = "models-textures";\r
109 char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures";\r
110 \r
111 char dataDir[200];  // Stores the directory name for the meshes and textures.\r
112 \r
113 static GLfloat floorVertices[4][3] = {\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   { -1000.0, 0.0, -1000.0 },\r
118 };\r
119 \r
120 static GLfloat lightColor[] = {1.0, 1.0, 1.0, 1.0}; // White light\r
121 static GLfloat lightPosition[4];\r
122 \r
123 int moving, startx, starty;\r
124 int lightMoving = 0, lightStartX, lightStartY;\r
125 \r
126 /* Time varying or user-controled variables. */\r
127 static float jump = 0.0;\r
128 static float lightAngle = 0.0, lightHeight = 20;\r
129 GLfloat angle = -150;   /* in degrees */\r
130 GLfloat angle2 = 30;   /* in degrees */\r
131 \r
132 /**\r
133  * Prints out error message when file cannot be read\r
134  * @param fileName Name of file that could not be read\r
135  */\r
136 void fileErr(char* fileName) {\r
137     printf("Error reading file: %s\n", fileName);\r
138     printf("If not in the CSSE labs, you will need to include the directory containing\n");\r
139     printf("the models on the command line, or put it in the same folder as the exectutable.");\r
140     exit(EXIT_FAILURE);\r
141 }  \r
142 \r
143 /**\r
144  * Reads .bmp texture files and converts them to a texture object\r
145  * @param fileName .bmp texture file\r
146  * @return texture object\r
147  */\r
148 texture* loadTexture(char *fileName) {\r
149     texture* t = malloc(sizeof (texture));\r
150     BITMAPINFO *info;\r
151 \r
152     t->rgbData = LoadDIBitmap(fileName, &info);\r
153     t->height=info->bmiHeader.biHeight;\r
154     t->width=info->bmiHeader.biWidth;\r
155 \r
156     return t;\r
157 }\r
158 \r
159 /**\r
160  * Reads .x files and converts them to a mesh object\r
161  * @param fileName .x mesh file\r
162  * @return mesh object\r
163  */\r
164 mesh* loadMesh(char* fileName) {\r
165     mesh* m = malloc(sizeof (mesh));\r
166     FILE* fp = fopen(fileName, "r");\r
167     char line[256] = "";\r
168     int lineBuffSize = 256;\r
169 \r
170     if(fp == NULL) fileErr(fileName);\r
171 \r
172     while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 )\r
173         fgets(line, lineBuffSize, fp);\r
174 \r
175     fscanf(fp, "%d;\n", &(m->nVertices));\r
176     m->vertices = malloc(m->nVertices * sizeof(vertex));\r
177     for(int i=0; i < m->nVertices; i++)\r
178         fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) );\r
179 \r
180     fscanf(fp, "%d;\n", &(m->nTriangles));\r
181     m->triangles = malloc(m->nTriangles * sizeof(triangle));\r
182     for(int i=0; i < m->nTriangles; i++)\r
183         fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2);\r
184 \r
185     while(strcmp(line,"  MeshNormals {\r\n") != 0 && strcmp(line,"  MeshNormals {\n") != 0)\r
186         fgets(line, lineBuffSize, fp);\r
187 \r
188     fgets(line, lineBuffSize, fp);\r
189     m->normals = malloc(m->nVertices * sizeof(normal));\r
190     for(int i=0; i < m->nVertices; i++)\r
191         fscanf(fp, "%f; %f; %f;%*[;,]\n",\r
192                &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2]));\r
193 \r
194     while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0)\r
195         fgets(line, lineBuffSize, fp);\r
196 \r
197     fgets(line, lineBuffSize, fp);\r
198     m->texCoords = malloc(m->nVertices * sizeof(texCoord));\r
199     for(int i=0; i < m->nVertices; i++)\r
200         fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) );\r
201     fclose(fp);\r
202     \r
203     return m;\r
204 }\r
205 \r
206 // [You may want to add to this function.]\r
207 /**\r
208  * Loads mesh[i] if it isn't already loaded.\r
209  * You must call getMesh(i) at least once before using mesh[i].\r
210  *\r
211  * @param i Mesh ID\r
212  */\r
213 void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded.  \r
214     char fileName[220];\r
215     if(i>=NMESH || i<0) {\r
216         printf("Error in getMesh - wrong model number");\r
217         exit(1);\r
218     }\r
219     if(meshes[i] != NULL)\r
220         return;\r
221     sprintf(fileName, "%s/model%d.x", dataDir, i+1);\r
222     meshes[i] = loadMesh(fileName);\r
223 }\r
224 \r
225 /**\r
226  * Loads texture i if it isn't already loaded\r
227  *\r
228  * After calling getTexture(i), you can make texture i the current texture using\r
229  *      glBindTexture(GL_TEXTURE_2D, i);\r
230  * Use i=0 to return to the default plain texture.\r
231  *\r
232  * You can then scale the texture via:\r
233  *      glMatrixMode(GL_TEXTURE);\r
234  * See the textbook, section 8.8.3.\r
235  *\r
236  * You must call getTexture(i) at least once before using texture i.\r
237  * @param i Texture ID\r
238  */\r
239 void getTexture(int i) {\r
240     char fileName[220];\r
241     if(i<1 || i>NTEXTURE) {\r
242         printf("Error in getTexture - wrong texture number");\r
243         exit(1);\r
244     }\r
245     if(textures[i-1] != NULL)\r
246         return;\r
247     sprintf(fileName, "%s/texture%d.bmp", dataDir, i);\r
248 \r
249     textures[i-1] = loadTexture(fileName);\r
250 \r
251     glBindTexture(GL_TEXTURE_2D, i);\r
252 \r
253     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height,\r
254                  0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
255     gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, \r
256                       GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
257     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\r
258     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\r
259     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
260     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);\r
261 \r
262     glBindTexture(GL_TEXTURE_2D, 0);  // Back to default texture\r
263 }\r
264 \r
265 /**\r
266  * Event hander for main menu events\r
267  * @param id ID of menu item selected\r
268  */\r
269 void processMainEvents(int id) {\r
270   switch (id) {\r
271     case ROTATE_MOVE_CAMERA:\r
272       // Do stuff\r
273       break;\r
274 \r
275     case POSITION_SCALE:\r
276       // Do stuff\r
277       break;\r
278 \r
279     case ROTATION_TEXTURE_SCALE:\r
280       // Do stuff\r
281       break;\r
282 \r
283     case EXIT:\r
284       exit(EXIT_SUCCESS);\r
285 \r
286   }\r
287 }\r
288 \r
289 /**\r
290  * Event hander for materials menu events\r
291  * @param id ID of menu item selected\r
292  */\r
293 void processMaterialEvents(int id) {\r
294   switch (id) {\r
295     case MATERIAL_ALL_RGB:\r
296       // Do stuff\r
297       break;\r
298 \r
299     case MATERIAL_AMBIENT_RGB:\r
300       // Do stuff\r
301       break;\r
302 \r
303     case MATERIAL_DIFFUSE_RGB:\r
304       // Do stuff\r
305       break;\r
306 \r
307     case MATERIAL_SPECULAR_RGB:\r
308       // Do stuff\r
309       break;\r
310 \r
311     case MATERIAL_ALL_ADSS:\r
312       // Do stuff\r
313       break;\r
314 \r
315     case MATERIAL_RED_ADSS:\r
316       // Do stuff\r
317       break;\r
318 \r
319     case MATERIAL_GREEN_ADSS:\r
320       // Do stuff\r
321       break;\r
322 \r
323     case MATERIAL_BLUE_ADSS:\r
324       // Do stuff\r
325       break;\r
326 \r
327   }\r
328 }\r
329 \r
330 /**\r
331  * Event hander for light menu events\r
332  * @param id ID of menu item selected\r
333  */\r
334 void processLightEvents(int id) {\r
335   switch (id) {\r
336     case LIGHT_MOVE_LIGHT_1:\r
337       // Do stuff\r
338       break;\r
339 \r
340     case LIGHT_RGBALL_LIGHT_1:\r
341       // Do stuff\r
342       break;\r
343 \r
344     case LIGHT_MOVE_LIGHT_2:\r
345       // Do stuff\r
346       break;\r
347 \r
348     case LIGHT_RGBALL_LIGHT_2:\r
349       // Do stuff\r
350       break;\r
351 \r
352   }\r
353 }\r
354 \r
355 /**\r
356  * Event hander for object menu events\r
357  * @param id ID of object selected\r
358  */\r
359 void processObjectEvents(int id) {\r
360 \r
361 }\r
362 \r
363 /**\r
364  * Event hander for texture menu events\r
365  * @param id ID of texutre selected\r
366  */\r
367 void processTextureEvents(int id) {\r
368 \r
369 }\r
370 \r
371 /**\r
372  * Event hander for ground texture menu events\r
373  * @param id ID of ground texture selected\r
374  */\r
375 void processGTextureEvents(int id) {\r
376 \r
377 }\r
378 \r
379 /**\r
380  * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number\r
381  * @param numToRound Number to round\r
382  * @param multiple Multiple to round up to\r
383  * @return Rounded number\r
384  */\r
385 int roundUp(int numToRound, int multiple) {\r
386   if(multiple == 0) {\r
387     return numToRound;\r
388   }\r
389 \r
390   int remainder = numToRound % multiple;\r
391   if (remainder == 0)\r
392     return numToRound;\r
393   return numToRound + multiple - remainder;\r
394 }\r
395 \r
396 /**\r
397  * Makes a submenu from an array of items, splitting the list into subsubmenus\r
398  * of only 10 items.\r
399  * @param menuEntries Array of menu items\r
400  * @param menuEntriesSize Size of menuEntries\r
401  * @param callback Callback function for this array of menu items\r
402  * @return Reference to menu created\r
403  */\r
404 int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) {\r
405   if ( menuEntriesSize == 0 ) return -1;\r
406 \r
407   int menuNumber = roundUp(menuEntriesSize, 10) / 10;\r
408   int submenuObjects[menuNumber-1];\r
409 \r
410   for( int i = 0; i < menuNumber; i++ ) {\r
411     submenuObjects[i] = glutCreateMenu(callback);\r
412     int startNum = i*11 - (i-1);\r
413     for ( int j = startNum - 1; j < (startNum+9); j++ ) {\r
414       if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array\r
415       glutAddMenuEntry( menuEntries[j], j + 1 );\r
416     }\r
417   } \r
418 \r
419   int mainMenu = glutCreateMenu(callback);\r
420   for ( int i = 0; i < menuNumber; i++ ) {\r
421     char name[10]; // buffer to hold name\r
422     int startNum = i*11 - (i-1);\r
423     int endNum = startNum + 9;\r
424     if ( i == menuNumber - 1 ) { // We're on the last one\r
425       endNum = startNum + (menuEntriesSize - startNum); // Work out final number\r
426     }\r
427     sprintf(name, "%d-%d", startNum, endNum);\r
428     glutAddSubMenu( name, submenuObjects[i] );\r
429   }\r
430 \r
431   return mainMenu;\r
432 }\r
433 \r
434 /**\r
435  * Creates menu for program\r
436  */\r
437 void makeMenu() {\r
438   // Construct material menu\r
439   int materialMenu = glutCreateMenu(processMaterialEvents);\r
440   glutAddMenuEntry("All R/G/B", MATERIAL_ALL_RGB);\r
441   glutAddMenuEntry("Ambient R/G/B", MATERIAL_AMBIENT_RGB);\r
442   glutAddMenuEntry("Diffuse R/G/B", MATERIAL_DIFFUSE_RGB);\r
443   glutAddMenuEntry("Specular R/G/B", MATERIAL_SPECULAR_RGB);\r
444   glutAddMenuEntry("All Amb/Diff/Spec/Shine", MATERIAL_ALL_ADSS);\r
445   glutAddMenuEntry("Red Amb/Diff/Spec/Shine", MATERIAL_RED_ADSS);\r
446   glutAddMenuEntry("Green Amb/Diff/Spec/Shine", MATERIAL_GREEN_ADSS);\r
447   glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", MATERIAL_BLUE_ADSS);\r
448 \r
449   // Construct light menu\r
450   int lightMenu = glutCreateMenu(processLightEvents);\r
451   glutAddMenuEntry("Move Light 1", LIGHT_MOVE_LIGHT_1);\r
452   glutAddMenuEntry("R/G/B/All Light 1", LIGHT_RGBALL_LIGHT_1);\r
453   glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2);\r
454   glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2);\r
455 \r
456   // Construct object menu\r
457   int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]);\r
458   int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, processObjectEvents );\r
459 \r
460   // Construct texture / ground texture menus\r
461   int textureMenuEntriesSize = sizeof(textureMenuEntries) / sizeof(textureMenuEntries[0]);\r
462   int textureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processTextureEvents );\r
463   int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processGTextureEvents );\r
464 \r
465   // Construct main menu\r
466   glutCreateMenu(processMainEvents);\r
467   //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA);\r
468   //glutAddSubMenu("Add object", objectMenu);\r
469   //glutAddMenuEntry("Position/Scale", POSITION_SCALE);\r
470   //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE);\r
471   //glutAddSubMenu("Material", materialMenu);\r
472   //glutAddSubMenu("Texture", textureMenu);\r
473   //glutAddSubMenu("Ground texture", gTextureMenu);\r
474   //glutAddSubMenu("Lights", lightMenu);\r
475   glutAddMenuEntry("Exit", EXIT);\r
476 \r
477   // Bind to right mouse button\r
478   glutAttachMenu(GLUT_RIGHT_BUTTON);\r
479 }\r
480 \r
481 /**\r
482  * Called when window is resized\r
483  * @param w New width\r
484  * @param h New height\r
485  */\r
486 void windowReshape(int w, int h) {\r
487   GLdouble near = -1000.0;\r
488   GLdouble far = 1000.0;\r
489 \r
490   glViewport(0, 0, (GLsizei) w, (GLsizei) h);\r
491   glMatrixMode(GL_PROJECTION);\r
492   glLoadIdentity();\r
493   if (w <= h) \r
494     glOrtho(near, far, near*(GLfloat)h/(GLfloat)w,\r
495              far*(GLfloat)h/(GLfloat)w, near, far);\r
496   else\r
497     glOrtho(near*(GLfloat)w/(GLfloat)h,\r
498              far*(GLfloat)w/(GLfloat)h, near, far, near, far);\r
499    glMatrixMode(GL_MODELVIEW); \r
500    glLoadIdentity();\r
501 }\r
502 \r
503 /**\r
504  * Called when mouse event occurs\r
505  * @param btn Mouse button\r
506  * @param state State of mouse button\r
507  * @param x Mouse x position\r
508  * @param y Mouse y position\r
509  */\r
510 /*void mouse(int btn, int state, int x, int y) {\r
511   \r
512 }*//*\r
513 static void\r
514 mouse(int button, int state, int x, int y)\r
515 {\r
516   if (button == GLUT_LEFT_BUTTON) {\r
517     if (state == GLUT_DOWN) {\r
518       moving = 1;\r
519       startx = x;\r
520       starty = y;\r
521     }\r
522     if (state == GLUT_UP) {\r
523       moving = 0;\r
524     }\r
525   }\r
526   if (button == GLUT_MIDDLE_BUTTON) {\r
527     if (state == GLUT_DOWN) {\r
528       lightMoving = 1;\r
529       lightStartX = x;\r
530       lightStartY = y;\r
531     }\r
532     if (state == GLUT_UP) {\r
533       lightMoving = 0;\r
534     }\r
535   }\r
536 }\r
537 \r
538 static void\r
539 motion(int x, int y)\r
540 {\r
541   if (moving) {\r
542     angle = angle + (x - startx);\r
543     angle2 = angle2 + (y - starty);\r
544     startx = x;\r
545     starty = y;\r
546     glutPostRedisplay();\r
547   }\r
548   if (lightMoving) {\r
549     lightAngle += (x - lightStartX)/40.0;\r
550     lightHeight += (lightStartY - y)/20.0;\r
551     lightStartX = x;\r
552     lightStartY = y;\r
553     glutPostRedisplay();\r
554   }\r
555 }*/\r
556 \r
557 void idle() {\r
558   angle = (int)(angle + 10) % 360;\r
559     //angle2 = (int)(angle2 + 10) % 360;\r
560     printf("Angle 1: %f, Angle 2: %f\n", angle, angle2);\r
561     sleep(25);\r
562     glutPostRedisplay();\r
563 }\r
564 \r
565 \r
566 int drawFloorRecurse = 2;\r
567 \r
568 void drawSquare(int recurseLevel, float x1, float y1, float x2, float y2) {\r
569 \r
570   printf("%d, %d, %d, %d\n", x1, y2, x2, y2);\r
571 \r
572   if ( drawFloorRecurse != recurseLevel ) {\r
573     float xm = (x1 + x2) / 2.0;\r
574     float ym = (y1 + y2) / 2.0;\r
575     int rnew = recurseLevel + 1;\r
576     printf("Recursing to level %d\n", rnew);\r
577 \r
578     // Split into four sub-quads\r
579     drawSquare(rnew, x1, y1, xm, ym);\r
580     drawSquare(rnew, x1, ym, xm, y2);\r
581     drawSquare(rnew, xm, ym, x2, y2);\r
582     drawSquare(rnew, xm, y1, x2, ym);\r
583 \r
584   } else {\r
585     printf("Drawing (%.10f, %.10f) -> (%.10f, %.10f)\n", x1, y2, x2, y2);\r
586     glBegin(GL_QUADS);\r
587       glVertex3f(x1, 0.0, y1);\r
588       glVertex3f(x1, 0.0, y2);\r
589       glVertex3f(x2, 0.0, y2);\r
590       glVertex3f(x2, 0.0, y1);\r
591     glEnd();\r
592   }\r
593 \r
594 }\r
595 \r
596 /**\r
597  * Draw a floor.\r
598  */\r
599 void drawFloor() {\r
600   glDisable(GL_LIGHTING);\r
601 \r
602   //if (useTexture) {\r
603   //  glEnable(GL_TEXTURE_2D);\r
604   //}\r
605 \r
606   /*glBegin(GL_QUADS);\r
607     glTexCoord2f(0.0, 0.0);\r
608     glVertex3fv(floorVertices[0]);\r
609     glTexCoord2f(0.0, 16.0);\r
610     glVertex3fv(floorVertices[1]);\r
611     glTexCoord2f(16.0, 16.0);\r
612     glVertex3fv(floorVertices[2]);\r
613     glTexCoord2f(16.0, 0.0);\r
614     glVertex3fv(floorVertices[3]);\r
615   glEnd();*/\r
616 \r
617 drawSquare(0, -1000.0, -1000.0, 1000.0, 1000.0);\r
618 \r
619   /*if (useTexture) {\r
620     glDisable(GL_TEXTURE_2D);\r
621   }*/\r
622 \r
623   glEnable(GL_LIGHTING);\r
624 }\r
625 \r
626 /*void drawSquare(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {\r
627   drawSquare(0, x1, y1, x2, y2);\r
628 }*/\r
629 \r
630 /**\r
631  * Display function\r
632  */\r
633 void display() {\r
634   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
635   glLoadIdentity();\r
636   gluLookAt(\r
637     0.0, 0.0, 60.0,  /* eye is at (x,y,z) */\r
638     0.0, 0.0,  0.0,  /* center is at (x,y,z) */\r
639     0.0, 1.0,  0.0   /* up is in postivie Y direction */\r
640     );\r
641 \r
642   /* Reposition the light source. */\r
643   lightPosition[0] = 12*cos(lightAngle);\r
644   lightPosition[1] = lightHeight;\r
645   lightPosition[2] = 12*sin(lightAngle);\r
646   lightPosition[3] = 0.0;\r
647 \r
648   glPushMatrix();\r
649       /* Perform scene rotations based on user mouse input. */\r
650     glRotatef(angle2, 1.0, 0.0, 0.0);\r
651     glRotatef(angle, 0.0, 1.0, 0.0);\r
652 \r
653     glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);\r
654 \r
655     glEnable(GL_BLEND);\r
656     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
657     drawFloor();\r
658     glDisable(GL_BLEND);\r
659 \r
660     glPushMatrix();\r
661     \r
662       //glTranslatef(0.0, 0.0, 0.0);\r
663       glutWireTeapot(30); // Draw teapot for test\r
664     glPopMatrix();\r
665 \r
666     glPushMatrix();\r
667       glDisable(GL_LIGHTING);\r
668       glColor3f(1.0, 1.0, 1.0);\r
669 \r
670       /* Draw a yellow ball at the light source. */\r
671       glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);\r
672       glutSolidSphere(1.0, 5, 5);\r
673 \r
674       glEnable(GL_LIGHTING);\r
675     glPopMatrix();\r
676 \r
677   glPopMatrix();\r
678 \r
679   glutSwapBuffers();\r
680 }\r
681 \r
682 /**\r
683  * init function; sets initial OpenGL state\r
684  */\r
685 void init() {\r
686   glMatrixMode(GL_PROJECTION);\r
687   glLoadIdentity();\r
688 \r
689   gluPerspective(\r
690        60.0,  /* field of view in degree */\r
691         1.0,  /* aspect ratio */\r
692     -1000.0,  /* Z near */\r
693      1000.0   /* Z far */\r
694     );    \r
695 \r
696   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);\r
697   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);\r
698   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);\r
699   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);\r
700   glEnable(GL_LIGHT0);\r
701   glEnable(GL_LIGHTING);\r
702 \r
703   glMatrixMode(GL_MODELVIEW);\r
704   glLoadIdentity();\r
705 }\r
706 \r
707 /**\r
708  * Main function\r
709  * @param argc Number of arguments\r
710  * @param argv Array of arguments\r
711  * @return Program exit code\r
712  */\r
713 int main(int argc, char **argv) {\r
714   if(argc>1)\r
715     strcpy(dataDir, argv[1]);\r
716   else if(opendir(dirDefault1))\r
717     strcpy(dataDir, dirDefault1);\r
718   else if(opendir(dirDefault2))\r
719     strcpy(dataDir, dirDefault2);\r
720   else fileErr(dirDefault1);\r
721 \r
722   for(int i=0; i<NMESH; i++) meshes[i]=NULL;\r
723   for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;\r
724 \r
725   glutInit(&argc, argv);\r
726 \r
727   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);\r
728 \r
729   glutInitWindowSize(500, 500);\r
730   glutCreateWindow("Scene Editor");\r
731 \r
732   glShadeModel(GL_SMOOTH); // Enables Smooth Shading\r
733   glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background\r
734   glClearDepth(1.0f); // Depth Buffer Setup\r
735   glEnable(GL_DEPTH_TEST); // Enables Depth Testing\r
736   glDepthFunc(GL_LEQUAL);  // the type\r
737   glEnable(GL_CULL_FACE);\r
738   glEnable(GL_TEXTURE_2D);\r
739   glLineWidth(1.0);\r
740 \r
741   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);\r
742 \r
743   glutReshapeFunc(windowReshape);\r
744   glutDisplayFunc(display);\r
745   //glutMouseFunc(mouse);\r
746   //glutMotionFunc(motion);\r
747   glutIdleFunc(idle);\r
748 \r
749   makeMenu();\r
750 \r
751   init();\r
752 \r
753   glutMainLoop();\r
754 }\r

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