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

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