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

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