Parallel Programming - Finished pthreads
[matches/honours.git] / course / semester2 / pprog / assignment1 / single-thread / graphics.c
1 /**
2  * @file graphics.c
3  * @author Sam Moore (20503628) 2012 
4  *      - Adapted from template program provided by UWA
5  * @purpose Definition of graphics related functions
6  * NOTE: This file is identical for both the single-threaded and multi-threaded versions of the program
7  */
8
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <time.h> // Needed for clock
13 #include <math.h> // Maths functions (sin, cos)
14
15 #include "graphics.h" //Function declarations
16 #include "nbody.h" //The simulation
17
18
19 // --- Variable definitions --- //
20 double previousTime, eyeTheta, eyePhi, eyeRho;
21 float look[3];
22 int windowWidth, windowHeight, upY;
23 double scale = 1.0;
24
25 #ifdef FLYING_CAMERA
26 Camera eye;
27 #endif //FLYING_CAMERA
28
29 /**
30  * @function Graphics_Run
31  * @purpose Setup and start the graphics engine
32  * @param argc - Number of arguments to main function, passed to glutInit
33  * @param argv - Argument strings for main function, passed to glutInit
34  */
35 void Graphics_Run(int argc, char ** argv) 
36 {
37         if (options.draw_graphics == false)
38         {
39                 // This message is left here for when I inevitably accidentally call the function
40                 fprintf(stderr, "Graphics_Run should not be called if graphics are disabled!\n");
41                 exit(EXIT_FAILURE);
42         }       
43
44         glutInit(&argc, argv);  
45         glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
46         glutInitWindowSize(WIDTH, HEIGHT);
47         glutInitWindowPosition(POSITION_X, POSITION_Y);
48
49         //Set window title based on version of program
50         #ifdef SINGLE_THREADED
51                 glutCreateWindow("N-Body : Single-Threaded");
52         #elif defined PTHREADED
53                 glutCreateWindow("N-Body : Multi-Threaded (pthread)");
54         #elif defined OMP_THREADED
55                 glutCreateWindow("N-Body : Multi-Threaded (OpenMP)");   
56         #else
57                 glutCreateWindow("N-Body");
58         #endif 
59         glutDisplayFunc(Graphics_Display);
60         glutIdleFunc(Graphics_Display);
61         glutKeyboardFunc(Graphics_Keyboard);
62         glutReshapeFunc(Graphics_Reshape);
63          
64
65         glClearColor(1.0,1.0,1.0,0.0);
66         glColor3f(0.0f, 0.0f, 0.0f);
67         glPointSize(POINT_SIZE);
68         glMatrixMode(GL_PROJECTION);
69         glLoadIdentity();
70
71         /*init lighting */
72
73         GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
74         GLfloat mat_shininess[] = { 50.0 };
75         GLfloat light_position[] = { 1.0, 1.0, 0.0, 0.0 };
76         glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
77         glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
78         glLightfv(GL_LIGHT0, GL_POSITION, light_position);
79
80         glColorMaterial(GL_FRONT,GL_DIFFUSE);                // Set Color Capability
81     
82         glEnable(GL_LIGHTING);
83         glEnable(GL_LIGHT0);
84         glEnable(GL_DEPTH_TEST);
85     
86         glEnable(GL_COLOR_MATERIAL);                   // Enable color
87
88         
89         windowWidth = WIDTH;
90         windowHeight = HEIGHT;
91         previousTime = clock();
92         eyeTheta = 0;
93         eyePhi = 0.5 * M_PI;
94         eyeRho = RHO;
95         upY = 1;
96         look[0] = 0;
97         look[1] = 0;
98         look[2] = 0;
99         gluPerspective(VIEW_ANGLE, (double)WIDTH/(double)HEIGHT, WORLD_NEAR, WORLD_FAR);  
100
101         #ifdef FLYING_CAMERA
102         eye.x[0] = 0; eye.x[1] = 0; eye.x[2] = 1;
103         eye.y[0] = 0; eye.y[1] = 1; eye.y[2] = 0;
104         eye.z[0] = 1; eye.z[1] = 0; eye.z[2] = 0;
105         eye.p[0] = 0; eye.p[1] = 0; eye.p[2] = -50;
106         #endif //FLYING_CAMERA
107
108
109         //This option must be set, or when glut leaves the main loop. the exit(3) function is called... annoying
110         glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
111
112         glutMainLoop();
113         
114 }
115
116 /**
117  * @function Graphics_Display
118  * @purpose This function redraws the screen after the positions of particles 
119  *              have been updated.
120  *      It also calls System_Compute, and checks for exit conditions, in the single-threaded version only
121  */
122 void Graphics_Display() 
123 {
124
125         if (options.draw_graphics == false)
126         {
127                 // This message is left here for when I inevitably accidentally call the function
128                 fprintf(stderr, "Graphics_Display should not be called if graphics are disabled!\n");
129                 exit(EXIT_FAILURE);
130         }
131
132         //Check whether the graphics thread should exit for any reason
133         if (ExitCondition())
134         {
135                 glutLeaveMainLoop();    // original glut does not have this, which makes "nicely" exiting a bit annoying
136                 return;
137         }
138
139         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
140         glMatrixMode(GL_MODELVIEW);
141         glLoadIdentity();
142
143         #ifdef FLYING_CAMERA
144
145         gluLookAt(eye.p[0], eye.p[1], eye.p[2], 
146                 eye.p[0] + eye.x[0], eye.p[1] + eye.x[1], eye.p[2] + eye.x[2],
147                 eye.z[0], eye.z[1], eye.z[2]);
148         #else
149         gluLookAt(eyeRho * sin(eyePhi) * sin(eyeTheta), eyeRho * cos(eyePhi),
150                 eyeRho * sin(eyePhi) * cos(eyeTheta),look[0], look[1], look[2], 0, upY, 0);
151         #endif //FLYING_CAMERA
152
153         BeforeDraw(); // Stuff to do before graphics is allowed to draw
154                         // Single-thread - perform a computation step, obviously! It's not done anywhere else
155                         // Multiple threads - ensure that all body positions are updated (ie: not halfway through step).
156                         //      (We don't care about the force and velocity variables though)
157
158         for (int i = 0; i < universe.N; ++i) 
159         {
160         
161                 Body * b = universe.body+i;
162                 glColor3f(0.0f, b->mass/1e11*100, 0.0f);
163                 //glColor3f(1.0f, 0.0f, 0.0f);
164                 glPushMatrix(); // to save the current matrix
165                 glTranslated(scale*b->x[0], scale*b->x[1], scale*b->x[2]);
166                 glutSolidSphere (BALL_SIZE, 10, 10);
167                 glPopMatrix(); // restore the previous matrix
168         }
169         glFlush();
170
171         AfterDraw(); // Stuff to do after graphics is done drawing
172                         // Single-thread - Nothing at all
173                         // Multiple threads - signal threads it is safe to change position variables
174
175 }
176
177 /**
178  * @function Graphics_Keyboard
179  * @purpose This function is to manipulate with the image
180  * @param theKey key pressed
181  * @param mouseX, mouseY position of the mouse in the window
182  */
183 void Graphics_Keyboard(unsigned char theKey, int mouseX, int mouseY) 
184 {
185         if (theKey == 'x' || theKey == 'X') 
186         {
187                 QuitProgram(false);
188                 return;
189         }
190
191         #ifdef FLYING_CAMERA
192         switch (theKey)
193         {
194                 // Translate in direction of camera
195                 case 'W':
196                 case 'w':
197                         for (unsigned i = 0; i < DIMENSIONS; ++i)
198                                 eye.p[i] += eye.x[i];
199                         break;
200                 // Translate backwards from camera direction
201                 case 'S':
202                 case 's':
203                         for (unsigned i = 0; i < DIMENSIONS; ++i)
204                                 eye.p[i] -= eye.x[i];
205                         break;
206                 // Translate left from camera direction
207                 case 'A':
208                 case 'a':
209                         for (unsigned i = 0; i < DIMENSIONS; ++i)
210                                 eye.p[i] -= eye.y[i];
211                         break;
212                 // Translate right from camera direction
213                 case 'D':
214                 case 'd':
215                         for (unsigned i = 0; i < DIMENSIONS; ++i)
216                                 eye.p[i] += eye.y[i];
217                         break;
218                 // Translate up from camera direction
219                 case 'Q':
220                 case 'q':
221                         for (unsigned i = 0; i < DIMENSIONS; ++i)
222                                 eye.p[i] += eye.z[i];
223                         break;
224                 // Translate down from camera direction
225                 case 'E':
226                 case 'e':
227                         for (unsigned i = 0; i < DIMENSIONS; ++i)
228                                 eye.p[i] -= eye.z[i];
229                         break;
230
231                 // Rotate camera direction "down"
232                 // (pitch control)
233                 case 'I':
234                 case 'i':
235                 {
236                         float theta = M_PI/80.0;
237                         Camera old = eye;
238
239                         for (unsigned i = 0; i < DIMENSIONS; ++i)
240                         {
241                                 eye.z[i] = old.z[i] * cos(theta) + old.x[i] * sin(theta);
242                                 eye.x[i] = old.x[i] * cos(theta) - old.z[i] * sin(theta);
243                         }
244                         break;
245                 }
246                 // Rotate camera direction "up"
247                 // (pitch control)
248                 case 'K':
249                 case 'k':
250                 {
251                         float theta = -M_PI/80.0;
252                         Camera old = eye;
253
254                         for (unsigned i = 0; i < DIMENSIONS; ++i)
255                         {
256                                 eye.z[i] = old.z[i] * cos(theta) + old.x[i] * sin(theta);
257                                 eye.x[i] = old.x[i] * cos(theta) - old.z[i] * sin(theta);
258                         }
259                         break;
260                 }
261                 // Rotate camera direction "left"
262                 // (yaw control)
263                 case 'J':
264                 case 'j':
265                 {
266                         float theta = +M_PI/80.0;
267                         Camera old = eye;
268
269                         for (unsigned i = 0; i < DIMENSIONS; ++i)
270                         {
271                                 eye.y[i] = old.y[i] * cos(theta) + old.x[i] * sin(theta);
272                                 eye.x[i] = old.x[i] * cos(theta) - old.y[i] * sin(theta);
273                         }
274                         break;
275                 }
276                 // Rotate camera direction "right"
277                 // (yaw control)
278                 case 'L':
279                 case 'l':
280                 {
281                         float theta = -M_PI/80.0;
282                         Camera old = eye;
283
284                         for (unsigned i = 0; i < DIMENSIONS; ++i)
285                         {
286                                 eye.y[i] = old.y[i] * cos(theta) + old.x[i] * sin(theta);
287                                 eye.x[i] = old.x[i] * cos(theta) - old.y[i] * sin(theta);
288                         }
289                         break;
290                 }
291                 // Rotate camera direction CCW about its axis
292                 // (roll control)
293                 case 'U':
294                 case 'u':
295                 {
296                         float theta = -M_PI/80.0;
297                         Camera old = eye;
298
299                         for (unsigned i = 0; i < DIMENSIONS; ++i)
300                         {
301                                 eye.z[i] = old.z[i] * cos(theta) + old.y[i] * sin(theta);
302                                 eye.y[i] = old.y[i] * cos(theta) - old.z[i] * sin(theta);
303                         }
304                         break;
305                 }
306                 // Rotate camera direction CW about its axis
307                 // (roll control)
308                 case 'O':
309                 case 'o':
310                 {
311                         float theta = +M_PI/80.0;
312                         Camera old = eye;
313
314                         for (unsigned i = 0; i < DIMENSIONS; ++i)
315                         {
316                                 eye.z[i] = old.z[i] * cos(theta) + old.y[i] * sin(theta);
317                                 eye.y[i] = old.y[i] * cos(theta) - old.z[i] * sin(theta);
318                         }
319                         break;
320                 }       
321         }
322
323         /*  Code used for debugging the camera
324         system("clear");
325         printf("Camera status:\n");
326         printf("Position: %f %f %f\n", eye.p[0], eye.p[1], eye.p[2]);
327         printf("x: %f %f %f (%f)\n", eye.x[0], eye.x[1], eye.x[2], sqrt(eye.x[0]*eye.x[0] + eye.x[1]*eye.x[1] + eye.x[2]*eye.x[2]));
328         printf("y: %f %f %f (%f)\n", eye.y[0], eye.y[1], eye.y[2], sqrt(eye.y[0]*eye.y[0] + eye.y[1]*eye.y[1] + eye.y[2]*eye.y[2]));
329         printf("z: %f %f %f (%f)\n", eye.z[0], eye.z[1], eye.z[2], sqrt(eye.z[0]*eye.z[0] + eye.z[1]*eye.z[1] + eye.z[2]*eye.z[2]));
330         */
331         #else // The original view code
332         
333                 // I like how 'I' is used three times.
334
335                 if (theKey == 'i' || theKey == 'I') {
336                         eyePhi -= M_PI / 20;
337                 if (eyePhi == 0)
338                                 eyePhi = 2 * M_PI;
339                 } else if (theKey == 'm' || theKey == 'I') {
340                         eyePhi += M_PI / 20;
341                 } else if (theKey == 'j' || theKey == 'J') {
342                         eyeTheta -= M_PI / 20;
343                 } else if (theKey == 'k' || theKey == 'K') {
344                         eyeTheta += M_PI / 20;
345                 } else if (theKey == ',') {
346                         eyeRho += 0.5;
347                 } else if (theKey == '.' || theKey == 'I') {
348                         eyeRho -= 0.5;
349                 } else if (theKey == 'w' || theKey == 'W') {
350                         look[1] += 0.5;
351                 } else if (theKey == 'z' || theKey == 'Z') {
352                         look[1] -= 0.5;
353                 } else if (theKey == 'a' || theKey == 'A') {
354                         look[0] -= 0.5;
355                 } else if (theKey == 's' || theKey == 'S') {
356                         look[0] += 0.5;
357                 } else if (theKey == '+') {
358                         scale *= 1.1;
359                 } else if (theKey == '-') {
360                         scale *= 0.9;
361                 }
362                 if (sin(eyePhi) > 0) upY = 1;
363                 else upY = 1;
364         #endif //FLYING_CAMERA
365 }
366
367 /**
368  * @function Graphics_Reshape
369  * @purpose Resize the view window
370  * @param width, height - New size of the window
371  */
372 void Graphics_Reshape(int width, int height) 
373 {
374         double displayRatio = 1.0 * width / height;
375         windowWidth = width;
376         windowHeight = height;
377         glMatrixMode(GL_PROJECTION);
378         glLoadIdentity();
379         gluPerspective(VIEW_ANGLE, displayRatio, WORLD_NEAR, WORLD_FAR);
380         glViewport(0, 0, windowWidth, windowHeight);
381 }
382
383
384

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