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

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