c09ac019f0c81d7140ab4a0fcb0f86b97c20e67f
[atyndall/cits2231.git] / scene.c
1 // compile this program using:\r
2 //   gcc -O3 -Wall -std=c99 -o scene scene.c bitmap.c -lglut\r
3 // Or, with cygwin:        (-mno-cygwin is only so the executable runs from windows)\r
4 //   gcc -mno-cygwin -O3 -Wall -std=c99 -o scene scene.c bitmap.c -lglut32 -lglu32 -lopengl32\r
5 // Or, use make via the supplied Makefile:     (For cygwin, install the package for make)\r
6 //   make\r
7 \r
8 #include <stdlib.h>\r
9 #include <stdio.h>\r
10 #include <dirent.h>\r
11 #include <string.h>\r
12 #include <math.h>\r
13 #include <GL/gl.h>\r
14 #include <GL/glut.h>\r
15 \r
16 #include "bitmap.h"\r
17 \r
18 // Type definitions for vertex-coordinates, normals, texture-coordinates, \r
19 // and triangles (via the indices of 3 vertices).\r
20 typedef GLfloat vertex[3];\r
21 typedef GLfloat normal[3];\r
22 typedef GLfloat texCoord[2];\r
23 typedef GLint vertexIndex;\r
24 typedef vertexIndex triangle[3];\r
25 \r
26 // A type for a mesh\r
27 typedef struct {         \r
28     int nVertices;           //  The number of vertices in the mesh\r
29     vertex* vertices;        //  Array with coordinates of vertices\r
30     normal* normals;         //  Array with normals of vertices\r
31     texCoord* texCoords;     //  Array with texture-coordinates of vertices\r
32     int nTriangles;          //  The number of triangles in the mesh\r
33     triangle* triangles;     //  Array of trangles via 3 indices into "vertices"\r
34 } mesh;\r
35 \r
36 #define NMESH 54       // The number of meshes (in the models-textures dir)\r
37 mesh* meshes[NMESH];   // An array of pointers to the meshes - see getMesh\r
38 \r
39 // A type for a 2D texture, with height and width in pixels\r
40 typedef struct {\r
41     int height;\r
42     int width;\r
43     GLubyte *rgbData;   // Array of bytes with the colour data for the texture\r
44 } texture;\r
45 \r
46 #define NTEXTURE 30     // The number of textures (in the models-textures dir)\r
47 texture* textures[NTEXTURE];   // An array of texture pointers - see getTexture\r
48 \r
49 typedef struct {  \r
50     // You'll need to add scale, rotation, material, mesh number, etc.,\r
51     // to this structure\r
52     float x,y,z;\r
53 } SceneObject;\r
54 \r
55 #define MAXOBJECTS 256\r
56 SceneObject sceneObjs[MAXOBJECTS];  // An array with details of the objects in a scene\r
57 int nObjects=0;                     // How many objects there are in the scene currently.\r
58 \r
59 void fileErr(char* fileName) {\r
60     printf("Error reading file: %s\n", fileName);\r
61     printf("If not in the CSSE labs, you will need to include the directory containing\n");\r
62     printf("the models on the command line, or put it in the same folder as the exectutable.");\r
63     exit(1);\r
64 }  \r
65 \r
66 texture* loadTexture(char *fileName) {\r
67     texture* t = malloc(sizeof (texture));\r
68     BITMAPINFO *info;\r
69 \r
70     t->rgbData = LoadDIBitmap(fileName, &info);\r
71     t->height=info->bmiHeader.biHeight;\r
72     t->width=info->bmiHeader.biWidth;\r
73 \r
74     return t;\r
75 }\r
76 \r
77 // The following works for the supplied .x files\r
78 // but probably not for .x files from other sources.\r
79 mesh* loadMesh(char* fileName) {\r
80     mesh* m = malloc(sizeof (mesh));\r
81     FILE* fp = fopen(fileName, "r");\r
82     char line[256] = "";\r
83     int lineBuffSize = 256;\r
84 \r
85     if(fp == NULL) fileErr(fileName);\r
86 \r
87     while(strcmp(line,"Mesh {\r\n") != 0 && strcmp(line,"Mesh {\n") != 0 )\r
88         fgets(line, lineBuffSize, fp);\r
89 \r
90     fscanf(fp, "%d;\n", &(m->nVertices));\r
91     m->vertices = malloc(m->nVertices * sizeof(vertex));\r
92     for(int i=0; i < m->nVertices; i++)\r
93         fscanf(fp, "%f; %f; %f;%*[,;]\n", &(m->vertices[i][0]), &(m->vertices[i][1]), &(m->vertices[i][2]) );\r
94 \r
95     fscanf(fp, "%d;\n", &(m->nTriangles));\r
96     m->triangles = malloc(m->nTriangles * sizeof(triangle));\r
97     for(int i=0; i < m->nTriangles; i++)\r
98         fscanf(fp, "%*d; %d, %d, %d;%*[;,]", m->triangles[i], m->triangles[i]+1, m->triangles[i]+2);\r
99 \r
100     while(strcmp(line,"  MeshNormals {\r\n") != 0 && strcmp(line,"  MeshNormals {\n") != 0)\r
101         fgets(line, lineBuffSize, fp);\r
102 \r
103     fgets(line, lineBuffSize, fp);\r
104     m->normals = malloc(m->nVertices * sizeof(normal));\r
105     for(int i=0; i < m->nVertices; i++)\r
106         fscanf(fp, "%f; %f; %f;%*[;,]\n",\r
107                &(m->normals[i][0]), &(m->normals[i][1]), &(m->normals[i][2]));\r
108 \r
109     while(strcmp(line,"MeshTextureCoords {\r\n") != 0 && strcmp(line,"MeshTextureCoords {\n") != 0)\r
110         fgets(line, lineBuffSize, fp);\r
111 \r
112     fgets(line, lineBuffSize, fp);\r
113     m->texCoords = malloc(m->nVertices * sizeof(texCoord));\r
114     for(int i=0; i < m->nVertices; i++)\r
115         fscanf(fp, "%f;%f;%*[,;]\n", &(m->texCoords[i][0]), &(m->texCoords[i][1]) );\r
116     fclose(fp);\r
117     \r
118     return m;\r
119 }\r
120 \r
121 char dataDir[200];  // Stores the directory name for the meshes and textures.\r
122 \r
123 // getMesh(i) loads mesh[i] if it isn't already loaded.  \r
124 // You must call getMesh(i) at least once before using mesh[i].\r
125 // [You may want to add to this function.]\r
126 void getMesh(int i) { // getMesh(i) loads mesh[i] if it isn't already loaded.  \r
127     char fileName[220];\r
128     if(i>=NMESH || i<0) {\r
129         printf("Error in getMesh - wrong model number");\r
130         exit(1);\r
131     }\r
132     if(meshes[i] != NULL)\r
133         return;\r
134     sprintf(fileName, "%s/model%d.x", dataDir, i+1);\r
135     meshes[i] = loadMesh(fileName);\r
136 }\r
137 \r
138 // getTexture(i) loads texture i if it isn't already loaded.\r
139 // After calling getTexture(i), you can make texture i the current texture using\r
140 //     glBindTexture(GL_TEXTURE_2D, i);    (Use i=0 to return to the default plain texture.)\r
141 // You can then scale the texture via:   (See the textbook, section 8.8.3.)\r
142 //      glMatrixMode(GL_TEXTURE);     \r
143 // You must call getTexture(i) at least once before using texture i.\r
144 void getTexture(int i) { // getTexture(i) loads texture i if it isn't already loaded.\r
145     char fileName[220];\r
146     if(i<1 || i>NTEXTURE) {\r
147         printf("Error in getTexture - wrong texture number");\r
148         exit(1);\r
149     }\r
150     if(textures[i-1] != NULL)\r
151         return;\r
152     sprintf(fileName, "%s/texture%d.bmp", dataDir, i);\r
153 \r
154     textures[i-1] = loadTexture(fileName);\r
155 \r
156     glBindTexture(GL_TEXTURE_2D, i);\r
157 \r
158     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textures[i-1]->width, textures[i-1]->height,\r
159                  0, GL_RGB, GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
160     gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, textures[i-1]->width, textures[i-1]->height, GL_RGB, \r
161                       GL_UNSIGNED_BYTE, textures[i-1]->rgbData);\r
162     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\r
163     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\r
164     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
165     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);\r
166 \r
167     glBindTexture(GL_TEXTURE_2D, 0);  // Back to default texture\r
168 }\r
169 \r
170 // Menu arrays\r
171 const char *textureMenuEntries[NTEXTURE] = {\r
172   "1 Plain", "2 Rust", "3 Concrete", "4 Carpet", "5 Beach Sand", \r
173   "6 Rocky", "7 Brick", "8 Water", "9 Paper", "10 Marble", \r
174   "11 Wood", "12 Scales", "13 Fur", "14 Denim", "15 Hessian",\r
175   "16 Orange Peel", "17 Ice Crystals", "18 Grass", "19 Corrugated Iron", "20 Styrofoam",\r
176   "21 Bubble Wrap", "22 Leather", "23 Camouflage", "24 Asphalt", "25 Scratched Ice",\r
177   "26 Rattan", "27 Snow", "28 Dry Mud", "29 Old Concrete", "30 Leopard Skin"\r
178 };\r
179 \r
180 const char *objectMenuEntries[NMESH] = {\r
181   "1 Thin Dinosaur","2 Big Dog","3 Saddle Dinosaur", "4 Dragon", "5 Cleopatra", \r
182   "6 Bone I", "7 Bone II", "8 Rabbit", "9 Long Dragon", "10 Buddha", \r
183   "11 Sitting Rabbit", "12 Frog", "13 Cow", "14 Monster", "15 Sea Horse", \r
184   "16 Head", "17 Pelican", "18 Horse", "19 Kneeling Angel", "20 Porsche I", \r
185   "21 Truck", "22 Statue of Liberty", "23 Sitting Angel", "24 Metal Part", "25 Car", \r
186   "26 Apatosaurus", "27 Airliner", "28 Motorbike", "29 Dolphin", "30 Spaceman", \r
187   "31 Winnie the Pooh", "32 Shark", "33 Crocodile", "34 Toddler", "35 Fat Dinosaur", \r
188   "36 Chihuahua", "37 Sabre-toothed Tiger", "38 Lioness", "39 Fish", "40 Horse (head down)", \r
189   "41 Horse (head up)", "42 Skull", "43 Fighter Jet I", "44 Toad", "45 Convertible", \r
190   "46 Porsche II", "47 Hare", "48 Vintage Car", "49 Fighter Jet II", "50 Winged Monkey", \r
191   "51 Chef", "52 Parasaurolophus", "53 Rooster", "54 T-rex"\r
192 };\r
193 \r
194 const char *materialMenuEntries[8] = {\r
195   "All R/G/B", "Ambient R/G/B", "Diffuse R/G/B", "Specular R/G/B",\r
196   "All Amb/Diff/Spec/Shine", "Red Amb/Diff/Spec/Shine", "Green Amb/Diff/Spec/Shine", "Blue Amb/Diff/Spec/Shine"\r
197 };\r
198 \r
199 void processMainEvents(int id) {\r
200    if(id == 99) exit(0);\r
201 }\r
202 \r
203 void processObjectEvents(int id) {\r
204 \r
205 }\r
206 \r
207 void processMaterialEvents(int id) {\r
208 \r
209 }\r
210 \r
211 void processTextureEvents(int id) {\r
212 \r
213 }\r
214 \r
215 void processGTextureEvents(int id) {\r
216 \r
217 }\r
218 \r
219 void processLightEvents(int id) {\r
220 \r
221 }\r
222 \r
223 void makeMenu() {\r
224   //int main, object, objectsize, material, texture, gtexture, light;\r
225 \r
226   glutCreateMenu(processMainEvents);\r
227   \r
228 \r
229   int objectSize = sizeof(objectMenuEntries) / sizeof(objectMenuEntries[0]);\r
230   int numMenus = objectSize/10 + 1;\r
231   int objectSubmenu[numMenus];\r
232 \r
233   for( int i = 0; objectSubmenu[i]; i++ ) {\r
234       objectSubmenu[i] = 0;\r
235   }\r
236 \r
237   // Create the n-(n+10) menus\r
238   for ( int i = 0; i < numMenus; i++ ) {\r
239 \r
240     objectSubmenu[i] = glutCreateMenu(processObjectEvents);\r
241 \r
242     for ( int j = 0; j < (i + 1) * 10; j++ ) {\r
243 \r
244       if ( objectMenuEntries[j] ) {\r
245         glutAddMenuEntry( objectMenuEntries[j], j + 1 );\r
246       } else { \r
247         break;\r
248       }\r
249 \r
250     }\r
251 \r
252   }\r
253 \r
254   // Create the overmenu\r
255   int objectMenu = glutCreateMenu(processObjectEvents);\r
256   for ( int i = 0; objectSubmenu[i]; i++ ) {\r
257     char name[10];\r
258     sprintf(name,"%d",(i + 1) * 10);\r
259     glutAddSubMenu( name, objectSubmenu[i] );\r
260   }\r
261 \r
262   glutAddSubMenu("Objects", objectMenu);\r
263   glutAddMenuEntry("Exit", 99);\r
264   \r
265   \r
266 \r
267 \r
268   glutAttachMenu(GLUT_RIGHT_BUTTON);\r
269 \r
270 }\r
271 \r
272     \r
273 /*void createGLUTMenus() {\r
274 \r
275         int menu,submenu;\r
276 \r
277         submenu = glutCreateMenu(processMenuEvents);\r
278         glutAddMenuEntry("Red",RED);\r
279         glutAddMenuEntry("Blue",BLUE);\r
280         glutAddMenuEntry("Green",GREEN);\r
281 \r
282         menu = glutCreateMenu(processMenuEvents);\r
283         glutAddMenuEntry("White",WHITE);\r
284         glutAddSubMenu("RGB Menu",submenu);\r
285         glutAttachMenu(GLUT_RIGHT_BUTTON);\r
286 */\r
287 \r
288 void display() {\r
289    // You probably want to change both of the following.\r
290    glClear(GL_COLOR_BUFFER_BIT);\r
291    glFlush();\r
292 }\r
293 \r
294 char *dirDefault1 = "models-textures"; \r
295 char *dirDefault2 = "/cslinux/examples/CITS2231/project-files/models-textures";\r
296 int main(int argc, char **argv) {\r
297 \r
298     if(argc>1)\r
299           strcpy(dataDir, argv[1]);\r
300     else if(opendir(dirDefault1))\r
301           strcpy(dataDir, dirDefault1);\r
302     else if(opendir(dirDefault2))\r
303       strcpy(dataDir, dirDefault2);\r
304     else fileErr(dirDefault1);\r
305 \r
306     for(int i=0; i<NMESH; i++) meshes[i]=NULL;\r
307     for(int i=0; i<NTEXTURE; i++) textures[i]=NULL;\r
308 \r
309     // The following is enough to run the program, but you'll\r
310     // need to change it significantly.\r
311 \r
312     glutInit(&argc, argv);\r
313     glutCreateWindow("Scene Editor");\r
314     glutDisplayFunc(display);\r
315 \r
316     makeMenu();\r
317     glutMainLoop();\r
318 }\r

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