1bafde50ccb55a323d33fd9e310230f951b521d2
[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 = 5;\r
129 GLfloat angle = -150;   /* in degrees */\r
130 GLfloat angle2 = 30;   /* in degrees */\r
131 \r
132 GLfloat near = -10;\r
133 GLfloat far = 10;\r
134 \r
135 /**\r
136  * Prints out error message when file cannot be read\r
137  * @param fileName Name of file that could not be read\r
138  */\r
139 void fileErr(char* fileName) {\r
140     printf("Error reading file: %s\n", fileName);\r
141     printf("If not in the CSSE labs, you will need to include the directory containing\n");\r
142     printf("the models on the command line, or put it in the same folder as the exectutable.");\r
143     exit(EXIT_FAILURE);\r
144 }  \r
145 \r
146 /**\r
147  * Reads .bmp texture files and converts them to a texture object\r
148  * @param fileName .bmp texture file\r
149  * @return texture object\r
150  */\r
151 texture* loadTexture(char *fileName) {\r
152     texture* t = malloc(sizeof (texture));\r
153     BITMAPINFO *info;\r
154 \r
155     t->rgbData = LoadDIBitmap(fileName, &info);\r
156     t->height=info->bmiHeader.biHeight;\r
157     t->width=info->bmiHeader.biWidth;\r
158 \r
159     return t;\r
160 }\r
161 \r
162 /**\r
163  * Reads .x files and converts them to a mesh object\r
164  * @param fileName .x mesh file\r
165  * @return mesh object\r
166  */\r
167 mesh* loadMesh(char* fileName) {\r
168     mesh* m = malloc(sizeof (mesh));\r
169     FILE* fp = fopen(fileName, "r");\r
170     char line[256] = "";\r
171     int lineBuffSize = 256;\r
172 \r
173     if(fp == NULL) fileErr(fileName);\r
174 \r
175     while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 )\r
176         fgets(line, lineBuffSize, fp);\r
177 \r
178     fscanf(fp, "%d;\n", &(m->nVertices));\r
179     m->vertices = malloc(m->nVertices * sizeof(vertex));\r
180     for(int i=0; i < m->nVertices; i++)\r
181         fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) );\r
182 \r
183     fscanf(fp, "%d;\n", &(m->nTriangles));\r
184     m->triangles = malloc(m->nTriangles * sizeof(triangle));\r
185     for(int i=0; i < m->nTriangles; i++)\r
186         fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2);\r
187 \r
188     while(strcmp(line,"  MeshNormals {\r\n") != 0 && strcmp(line,"  MeshNormals {\n") != 0)\r
189         fgets(line, lineBuffSize, fp);\r
190 \r
191     fgets(line, lineBuffSize, fp);\r
192     m->normals = malloc(m->nVertices * sizeof(normal));\r
193     for(int i=0; i < m->nVertices; i++)\r
194         fscanf(fp, "%f; %f; %f;%*[;,]\n",\r
195                &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2]));\r
196 \r
197     while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0)\r
198         fgets(line, lineBuffSize, fp);\r
199 \r
200     fgets(line, lineBuffSize, fp);\r
201     m->texCoords = malloc(m->nVertices * sizeof(texCoord));\r
202     for(int i=0; i < m->nVertices; i++)\r
203         fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) );\r
204     fclose(fp);\r
205     \r
206     return m;\r
207 }\r
208 \r
209 // [You may want to add to this function.]\r
210 /**\r
211  * Loads mesh[i] if it isn't already loaded.\r
212  * You must call getMesh(i) at least once before using mesh[i].\r
213  *\r
214  * @param i Mesh ID\r
215  */\r
216 void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded.  \r
217     char fileName[220];\r
218     if(i>=NMESH || i<0) {\r
219         printf("Error in getMesh - wrong model number");\r
220         exit(1);\r
221     }\r
222     if(meshes[i] != NULL)\r
223         return;\r
224     sprintf(fileName, "%s/model%d.x", dataDir, i+1);\r
225     meshes[i] = loadMesh(fileName);\r
226 }\r
227 \r
228 /**\r
229  * Loads texture i if it isn't already loaded\r
230  *\r
231  * After calling getTexture(i), you can make texture i the current texture using\r
232  *      glBindTexture(GL_TEXTURE_2D, i);\r
233  * Use i=0 to return to the default plain texture.\r
234  *\r
235  * You can then scale the texture via:\r
236  *      glMatrixMode(GL_TEXTURE);\r
237  * See the textbook, section 8.8.3.\r
238  *\r
239  * You must call getTexture(i) at least once before using texture i.\r
240  * @param i Texture ID\r
241  */\r
242 void getTexture(int i) {\r
243     char fileName[220];\r
244     if(i<1 || i>NTEXTURE) {\r
245         printf("Error in getTexture - wrong texture number");\r
246         exit(1);\r
247     }\r
248     if(textures[i-1] != NULL)\r
249         return;\r
250     sprintf(fileName, "%s/texture%d.bmp", dataDir, i);\r
251 \r
252     textures[i-1] = loadTexture(fileName);\r
253 \r
254     glBindTexture(GL_TEXTURE_2D, i);\r
255 \r
256     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height,\r
257                  0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
258     gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, \r
259                       GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
260     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\r
261     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\r
262     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
263     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);\r
264 \r
265     glBindTexture(GL_TEXTURE_2D, 0);  // Back to default texture\r
266 }\r
267 \r
268 /**\r
269  * Event hander for main menu events\r
270  * @param id ID of menu item selected\r
271  */\r
272 void processMainEvents(int id) {\r
273   switch (id) {\r
274     case ROTATE_MOVE_CAMERA:\r
275       // Do stuff\r
276       break;\r
277 \r
278     case POSITION_SCALE:\r
279       // Do stuff\r
280       break;\r
281 \r
282     case ROTATION_TEXTURE_SCALE:\r
283       // Do stuff\r
284       break;\r
285 \r
286     case EXIT:\r
287       exit(EXIT_SUCCESS);\r
288 \r
289   }\r
290 }\r
291 \r
292 /**\r
293  * Event hander for materials menu events\r
294  * @param id ID of menu item selected\r
295  */\r
296 void processMaterialEvents(int id) {\r
297   switch (id) {\r
298     case MATERIAL_ALL_RGB:\r
299       // Do stuff\r
300       break;\r
301 \r
302     case MATERIAL_AMBIENT_RGB:\r
303       // Do stuff\r
304       break;\r
305 \r
306     case MATERIAL_DIFFUSE_RGB:\r
307       // Do stuff\r
308       break;\r
309 \r
310     case MATERIAL_SPECULAR_RGB:\r
311       // Do stuff\r
312       break;\r
313 \r
314     case MATERIAL_ALL_ADSS:\r
315       // Do stuff\r
316       break;\r
317 \r
318     case MATERIAL_RED_ADSS:\r
319       // Do stuff\r
320       break;\r
321 \r
322     case MATERIAL_GREEN_ADSS:\r
323       // Do stuff\r
324       break;\r
325 \r
326     case MATERIAL_BLUE_ADSS:\r
327       // Do stuff\r
328       break;\r
329 \r
330   }\r
331 }\r
332 \r
333 /**\r
334  * Event hander for light menu events\r
335  * @param id ID of menu item selected\r
336  */\r
337 void processLightEvents(int id) {\r
338   switch (id) {\r
339     case LIGHT_MOVE_LIGHT_1:\r
340       // Do stuff\r
341       break;\r
342 \r
343     case LIGHT_RGBALL_LIGHT_1:\r
344       // Do stuff\r
345       break;\r
346 \r
347     case LIGHT_MOVE_LIGHT_2:\r
348       // Do stuff\r
349       break;\r
350 \r
351     case LIGHT_RGBALL_LIGHT_2:\r
352       // Do stuff\r
353       break;\r
354 \r
355   }\r
356 }\r
357 \r
358 /**\r
359  * Event hander for object menu events\r
360  * @param id ID of object selected\r
361  */\r
362 void processObjectEvents(int id) {\r
363 \r
364 }\r
365 \r
366 /**\r
367  * Event hander for texture menu events\r
368  * @param id ID of texutre selected\r
369  */\r
370 void processTextureEvents(int id) {\r
371 \r
372 }\r
373 \r
374 /**\r
375  * Event hander for ground texture menu events\r
376  * @param id ID of ground texture selected\r
377  */\r
378 void processGTextureEvents(int id) {\r
379 \r
380 }\r
381 \r
382 /**\r
383  * Rounds up numbers, from http://stackoverflow.com/questions/3407012/c-rounding-up-to-the-nearest-multiple-of-a-number\r
384  * @param numToRound Number to round\r
385  * @param multiple Multiple to round up to\r
386  * @return Rounded number\r
387  */\r
388 int roundUp(int numToRound, int multiple) {\r
389   if(multiple == 0) {\r
390     return numToRound;\r
391   }\r
392 \r
393   int remainder = numToRound % multiple;\r
394   if (remainder == 0)\r
395     return numToRound;\r
396   return numToRound + multiple - remainder;\r
397 }\r
398 \r
399 /**\r
400  * Makes a submenu from an array of items, splitting the list into subsubmenus\r
401  * of only 10 items.\r
402  * @param menuEntries Array of menu items\r
403  * @param menuEntriesSize Size of menuEntries\r
404  * @param callback Callback function for this array of menu items\r
405  * @return Reference to menu created\r
406  */\r
407 int makeSubmenuFromArray( const char *menuEntries[], unsigned int menuEntriesSize, void *callback ) {\r
408   if ( menuEntriesSize == 0 ) return -1;\r
409 \r
410   int menuNumber = roundUp(menuEntriesSize, 10) / 10;\r
411   int submenuObjects[menuNumber-1];\r
412 \r
413   for( int i = 0; i < menuNumber; i++ ) {\r
414     submenuObjects[i] = glutCreateMenu(callback);\r
415     int startNum = i*11 - (i-1);\r
416     for ( int j = startNum - 1; j < (startNum+9); j++ ) {\r
417       if ( j == menuEntriesSize ) break; // Detect if we've reached the end of the array\r
418       glutAddMenuEntry( menuEntries[j], j + 1 );\r
419     }\r
420   } \r
421 \r
422   int mainMenu = glutCreateMenu(callback);\r
423   for ( int i = 0; i < menuNumber; i++ ) {\r
424     char name[10]; // buffer to hold name\r
425     int startNum = i*11 - (i-1);\r
426     int endNum = startNum + 9;\r
427     if ( i == menuNumber - 1 ) { // We're on the last one\r
428       endNum = startNum + (menuEntriesSize - startNum); // Work out final number\r
429     }\r
430     sprintf(name, "%d-%d", startNum, endNum);\r
431     glutAddSubMenu( name, submenuObjects[i] );\r
432   }\r
433 \r
434   return mainMenu;\r
435 }\r
436 \r
437 /**\r
438  * Creates menu for program\r
439  */\r
440 void makeMenu() {\r
441   // Construct material menu\r
442   int materialMenu = glutCreateMenu(processMaterialEvents);\r
443   glutAddMenuEntry("All R/G/B", MATERIAL_ALL_RGB);\r
444   glutAddMenuEntry("Ambient R/G/B", MATERIAL_AMBIENT_RGB);\r
445   glutAddMenuEntry("Diffuse R/G/B", MATERIAL_DIFFUSE_RGB);\r
446   glutAddMenuEntry("Specular R/G/B", MATERIAL_SPECULAR_RGB);\r
447   glutAddMenuEntry("All Amb/Diff/Spec/Shine", MATERIAL_ALL_ADSS);\r
448   glutAddMenuEntry("Red Amb/Diff/Spec/Shine", MATERIAL_RED_ADSS);\r
449   glutAddMenuEntry("Green Amb/Diff/Spec/Shine", MATERIAL_GREEN_ADSS);\r
450   glutAddMenuEntry("Blue Amb/Diff/Spec/Shine", MATERIAL_BLUE_ADSS);\r
451 \r
452   // Construct light menu\r
453   int lightMenu = glutCreateMenu(processLightEvents);\r
454   glutAddMenuEntry("Move Light 1", LIGHT_MOVE_LIGHT_1);\r
455   glutAddMenuEntry("R/G/B/All Light 1", LIGHT_RGBALL_LIGHT_1);\r
456   glutAddMenuEntry("Move Light 2", LIGHT_MOVE_LIGHT_2);\r
457   glutAddMenuEntry("R/G/B/All Light 2", LIGHT_RGBALL_LIGHT_2);\r
458 \r
459   // Construct object menu\r
460   int objectMenuEntriesSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]);\r
461   int objectMenu = makeSubmenuFromArray( objectMenuEntries, objectMenuEntriesSize, processObjectEvents );\r
462 \r
463   // Construct texture / ground texture menus\r
464   int textureMenuEntriesSize = sizeof(textureMenuEntries) / sizeof(textureMenuEntries[0]);\r
465   int textureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processTextureEvents );\r
466   int gTextureMenu = makeSubmenuFromArray( textureMenuEntries, textureMenuEntriesSize, processGTextureEvents );\r
467 \r
468   // Construct main menu\r
469   glutCreateMenu(processMainEvents);\r
470   //glutAddMenuEntry("Rotate/Move Camera", ROTATE_MOVE_CAMERA);\r
471   //glutAddSubMenu("Add object", objectMenu);\r
472   //glutAddMenuEntry("Position/Scale", POSITION_SCALE);\r
473   //glutAddMenuEntry("Rotation/Texture Scale", ROTATION_TEXTURE_SCALE);\r
474   //glutAddSubMenu("Material", materialMenu);\r
475   //glutAddSubMenu("Texture", textureMenu);\r
476   //glutAddSubMenu("Ground texture", gTextureMenu);\r
477   //glutAddSubMenu("Lights", lightMenu);\r
478   glutAddMenuEntry("Exit", EXIT);\r
479 \r
480   // Bind to right mouse button\r
481   glutAttachMenu(GLUT_RIGHT_BUTTON);\r
482 }\r
483 \r
484 /**\r
485  * Called when window is resized\r
486  * @param w New width\r
487  * @param h New height\r
488  */\r
489 void windowReshape(int w, int h) {\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(1);\r
562   glutPostRedisplay();\r
563 }\r
564 \r
565 \r
566 int drawFloorRecurse = 5;\r
567 \r
568 void drawSquare(int recurseLevel, float x1, float y1, float x2, float y2) {\r
569 \r
570   if ( drawFloorRecurse != recurseLevel ) {\r
571     float xm = (x1 + x2) / 2.0;\r
572     float ym = (y1 + y2) / 2.0;\r
573     int rnew = recurseLevel + 1;\r
574 \r
575     // Split into four sub-quads\r
576     drawSquare(rnew, x1, y1, xm, ym);\r
577     drawSquare(rnew, x1, ym, xm, y2);\r
578     drawSquare(rnew, xm, ym, x2, y2);\r
579     drawSquare(rnew, xm, y1, x2, ym);\r
580 \r
581   } else {\r
582     glBegin(GL_QUADS);\r
583       glVertex3f(x1, 0.0, y1);\r
584       glVertex3f(x1, 0.0, y2);\r
585       glVertex3f(x2, 0.0, y2);\r
586       glVertex3f(x2, 0.0, y1);\r
587     glEnd();\r
588   }\r
589 \r
590 }\r
591 \r
592 /**\r
593  * Draw a floor.\r
594  */\r
595 void drawFloor() {\r
596  \r
597 drawSquare(0, -100.0, -100.0, 100.0, 100.0);\r
598 \r
599   /*if (useTexture) {\r
600     glDisable(GL_TEXTURE_2D);\r
601   }*/\r
602 \r
603 }\r
604 \r
605 /*void drawSquare(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {\r
606   drawSquare(0, x1, y1, x2, y2);\r
607 }*/\r
608 \r
609 /**\r
610  * Display function\r
611  */\r
612 void display() {\r
613   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
614   glLoadIdentity();\r
615   gluLookAt(\r
616     0.0, 0.0, 10.0,  /* eye is at (x,y,z) */\r
617     0.0, 0.0,  0.0,  /* center is at (x,y,z) */\r
618     0.0, 1.0,  0.0   /* up is in postivie Y direction */\r
619     );\r
620 \r
621   glRotatef(30.0, 1.0, 0.0, 0.0);\r
622 \r
623   /* Reposition the light source. */\r
624   lightPosition[0] = 12*cos(lightAngle);\r
625   lightPosition[1] = lightHeight;\r
626   lightPosition[2] = 12*sin(lightAngle);\r
627   lightPosition[3] = 0.0;\r
628 \r
629   glPushMatrix();\r
630       /* Perform scene rotations based on user mouse input. */\r
631     \r
632     glRotatef(angle, 0.0, 1.0, 0.0);\r
633 \r
634     glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);\r
635 \r
636     glEnable(GL_BLEND);\r
637     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
638     drawFloor();\r
639     glDisable(GL_BLEND);\r
640 \r
641     glPushMatrix();\r
642     \r
643       glTranslatef(0.0, 1.0, 0.0);\r
644       glutWireTeapot(1); // Draw teapot for test\r
645     glPopMatrix();\r
646 \r
647     glPushMatrix();\r
648       glDisable(GL_LIGHTING);\r
649       glColor3f(1.0, 1.0, 1.0);\r
650 \r
651       /* Draw a yellow ball at the light source. */\r
652       glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);\r
653       glutSolidSphere(1.0, 50, 50);\r
654 \r
655       glEnable(GL_LIGHTING);\r
656     glPopMatrix();\r
657 \r
658   glPopMatrix();\r
659 \r
660   glutSwapBuffers();\r
661 }\r
662 \r
663 /**\r
664  * init function; sets initial OpenGL state\r
665  */\r
666 void init() {\r
667   glMatrixMode(GL_PROJECTION);\r
668   glLoadIdentity();\r
669 \r
670   gluPerspective(\r
671        60.0,  /* field of view in degree */\r
672         1.0,  /* aspect ratio */\r
673      near,  /* Z near */\r
674      far   /* Z far */\r
675     );    \r
676 \r
677 \r
678 GLfloat diffuse0[] = {1.0, 0.0, 0.0, 1.0};\r
679 GLfloat ambient0[] = {1.0, 0.0, 0.0, 1.0};\r
680 GLfloat specular0[] = {1.0, 0.0, 0.0, 1.0};\r
681 GLfloat light0_pos[] ={ 1.0, 2.0, 3,0, 1.0};\r
682 \r
683 glEnable(GL_LIGHT0);\r
684 glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);\r
685 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);\r
686 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);\r
687 glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);\r
688   glEnable(GL_LIGHTING);\r
689 \r
690   glMatrixMode(GL_MODELVIEW);\r
691   glLoadIdentity();\r
692 }\r
693 \r
694 /**\r
695  * Main function\r
696  * @param argc Number of arguments\r
697  * @param argv Array of arguments\r
698  * @return Program exit code\r
699  */\r
700 int main(int argc, char **argv) {\r
701   if(argc>1)\r
702     strcpy(dataDir, argv[1]);\r
703   else if(opendir(dirDefault1))\r
704     strcpy(dataDir, dirDefault1);\r
705   else if(opendir(dirDefault2))\r
706     strcpy(dataDir, dirDefault2);\r
707   else fileErr(dirDefault1);\r
708 \r
709   for(int i=0; i<NMESH; i++) meshes[i]=NULL;\r
710   for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;\r
711 \r
712   glutInit(&argc, argv);\r
713 \r
714   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);\r
715 \r
716   glutInitWindowSize(500, 500);\r
717   glutCreateWindow("Scene Editor");\r
718 \r
719   glShadeModel(GL_SMOOTH); // Enables Smooth Shading\r
720   glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background\r
721   glClearDepth(1.0f); // Depth Buffer Setup\r
722   glEnable(GL_DEPTH_TEST); // Enables Depth Testing\r
723   glDepthFunc(GL_LEQUAL);  // the type\r
724   glEnable(GL_CULL_FACE);\r
725   glEnable(GL_TEXTURE_2D);\r
726   glLineWidth(1.0);\r
727 \r
728   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);\r
729 \r
730   glutReshapeFunc(windowReshape);\r
731   glutDisplayFunc(display);\r
732   glutMouseFunc(mouse);\r
733   glutMotionFunc(motion);\r
734   //glutIdleFunc(idle);\r
735 \r
736   makeMenu();\r
737 \r
738   init();\r
739 \r
740   glutMainLoop();\r
741 }\r

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