Parallel Programming - Improve camera UI
[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 #include <GL/freeglut.h>
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] = 1; eye.x[1] = 0; eye.x[2] = 0;
103         eye.y[0] = 0; eye.y[1] = 1; eye.y[2] = 0;
104         eye.z[0] = 0; eye.z[1] = 0; eye.z[2] = 1;
105         #endif //FLYING_CAMERA
106
107         glutMainLoop();   
108 }
109
110 /**
111  * @function Graphics_Display
112  * @purpose This function redraws the screen after the positions of particles 
113  *              have been updated.
114  *      It also calls System_Compute, and checks for exit conditions, in the single-threaded version only
115  */
116 void Graphics_Display() 
117 {
118
119         if (options.draw_graphics == false)
120         {
121                 // This message is left here for when I inevitably accidentally call the function
122                 fprintf(stderr, "Graphics_Display should not be called if graphics are disabled!\n");
123                 exit(EXIT_FAILURE);
124         }
125
126         //Check whether the graphics thread should exit for any reason
127         if (ExitCondition())
128         {
129                 glutLeaveMainLoop();    // original glut does not have this, which makes "nicely" exiting a bit annoying
130                 return;
131         }
132
133         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
134         glMatrixMode(GL_MODELVIEW);
135         glLoadIdentity();
136
137         #ifdef FLYING_CAMERA
138         gluLookAt(eye.p[0], eye.p[1], eye.p[2], 
139                 eye.p[0] + eye.x[0], eye.p[1] + eye.x[1], eye.p[2] + eye.x[2],
140                 eye.z[0], eye.z[1], eye.z[2]);
141         #else
142         gluLookAt(eyeRho * sin(eyePhi) * sin(eyeTheta), eyeRho * cos(eyePhi),
143                 eyeRho * sin(eyePhi) * cos(eyeTheta),look[0], look[1], look[2], 0, upY, 0);
144         #endif //FLYING_CAMERA
145
146         BeforeDraw(); // Stuff to do before graphics is allowed to draw
147                         // Single-thread - perform a computation step, obviously! It's not done anywhere else
148                         // Multiple threads - ensure that all body positions are updated (ie: not halfway through step).
149                         //      (We don't care about the force and velocity variables though)
150
151         for (int i = 0; i < universe.N; ++i) 
152         {
153                 Body * b = universe.body+i;
154                 glColor3f(0.0f, b->mass/1e11*100, 0.0f);
155                 //glColor3f(1.0f, 0.0f, 0.0f);
156                 glPushMatrix(); // to save the current matrix
157                 glTranslated(scale*b->x[0], scale*b->x[1], scale*b->x[2]);
158                 glutSolidSphere (BALL_SIZE, 10, 10);
159                 glPopMatrix(); // restore the previous matrix
160         }
161         glFlush();
162
163         AfterDraw(); // Stuff to do after graphics is done drawing
164                         // Single-thread - Nothing at all
165                         // Multiple threads - signal threads it is safe to change position variables
166
167 }
168
169 /**
170  * @function Graphics_Keyboard
171  * @purpose This function is to manipulate with the image
172  * @param theKey key pressed
173  * @param mouseX, mouseY position of the mouse in the window
174  */
175 void Graphics_Keyboard(unsigned char theKey, int mouseX, int mouseY) 
176 {
177         if (theKey == 'x' || theKey == 'X') 
178         {
179                 QuitProgram(false);
180                 return;
181         }
182
183         #ifdef FLYING_CAMERA
184         switch (theKey)
185         {
186                 case 'W':
187                 case 'w':
188                         for (unsigned i = 0; i < DIMENSIONS; ++i)
189                                 eye.p[i] += eye.x[i];
190                         break;
191                 case 'S':
192                 case 's':
193                         for (unsigned i = 0; i < DIMENSIONS; ++i)
194                                 eye.p[i] -= eye.x[i];
195                         break;
196                 case 'A':
197                 case 'a':
198                         for (unsigned i = 0; i < DIMENSIONS; ++i)
199                                 eye.p[i] += eye.y[i];
200                         break;
201                 case 'D':
202                 case 'd':
203                         for (unsigned i = 0; i < DIMENSIONS; ++i)
204                                 eye.p[i] -= eye.y[i];
205                         break;
206                 case 'Z':
207                 case 'z':
208                         for (unsigned i = 0; i < DIMENSIONS; ++i)
209                                 eye.p[i] += eye.z[i];
210                         break;
211                 case 'C':
212                 case 'c':
213                         for (unsigned i = 0; i < DIMENSIONS; ++i)
214                                 eye.p[i] -= eye.z[i];
215                         break;
216
217                 case 'I':
218                 case 'i':
219                 {
220                         float theta = M_PI/80.0;
221                         Camera old = eye;
222
223                         for (unsigned i = 0; i < DIMENSIONS; ++i)
224                         {
225                                 eye.z[i] = old.z[i] * cos(theta) + old.x[i] * sin(theta);
226                                 eye.x[i] = old.x[i] * cos(theta) - old.z[i] * sin(theta);
227                         }
228                         break;
229                 }
230                 case 'K':
231                 case 'k':
232                 {
233                         float theta = -M_PI/80.0;
234                         Camera old = eye;
235
236                         for (unsigned i = 0; i < DIMENSIONS; ++i)
237                         {
238                                 eye.z[i] = old.z[i] * cos(theta) + old.x[i] * sin(theta);
239                                 eye.x[i] = old.x[i] * cos(theta) - old.z[i] * sin(theta);
240                         }
241                         break;
242                 }
243                 
244                 case 'J':
245                 case 'j':
246                 {
247                         float theta = -M_PI/80.0;
248                         Camera old = eye;
249
250                         for (unsigned i = 0; i < DIMENSIONS; ++i)
251                         {
252                                 eye.y[i] = old.y[i] * cos(theta) + old.x[i] * sin(theta);
253                                 eye.x[i] = old.x[i] * cos(theta) - old.y[i] * sin(theta);
254                         }
255                         break;
256                 }
257
258                 case 'L':
259                 case 'l':
260                 {
261                         float theta = M_PI/80.0;
262                         Camera old = eye;
263
264                         for (unsigned i = 0; i < DIMENSIONS; ++i)
265                         {
266                                 eye.y[i] = old.y[i] * cos(theta) + old.x[i] * sin(theta);
267                                 eye.x[i] = old.x[i] * cos(theta) - old.y[i] * sin(theta);
268                         }
269                         break;
270                 }
271
272                 case 'Q':
273                 case 'q':
274                 {
275                         float theta = M_PI/80.0;
276                         Camera old = eye;
277
278                         for (unsigned i = 0; i < DIMENSIONS; ++i)
279                         {
280                                 eye.z[i] = old.z[i] * cos(theta) + old.y[i] * sin(theta);
281                                 eye.y[i] = old.y[i] * cos(theta) - old.z[i] * sin(theta);
282                         }
283                         break;
284                 }
285                 case 'E':
286                 case 'e':
287                 {
288                         float theta = -M_PI/80.0;
289                         Camera old = eye;
290
291                         for (unsigned i = 0; i < DIMENSIONS; ++i)
292                         {
293                                 eye.z[i] = old.z[i] * cos(theta) + old.y[i] * sin(theta);
294                                 eye.y[i] = old.y[i] * cos(theta) - old.z[i] * sin(theta);
295                         }
296                         break;
297                 }       
298         }
299
300         /*
301         float x = 0; float y = 0; float z = 0;
302         for (unsigned i = 0; i < DIMENSIONS; ++i)
303         {
304                 x += eye.x[i] * eye.x[i];
305                 y += eye.y[i] * eye.y[i];
306                 z += eye.z[i] * eye.z[i];
307         }
308         for (unsigned i = 0; i < DIMENSIONS; ++i)
309         {
310                 eye.x[i] /= sqrt(x);
311                 eye.y[i] /= sqrt(y);
312                 eye.z[i] /= sqrt(z);
313         }
314         */
315         system("clear");
316         printf("Camera status:\n");
317         printf("Position: %f %f %f\n", eye.p[0], eye.p[1], eye.p[2]);
318         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]));
319         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]));
320         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]));
321
322         #else
323         
324         
325
326                 if (theKey == 'i' || theKey == 'I') {
327                         eyePhi -= M_PI / 20;
328                 if (eyePhi == 0)
329                                 eyePhi = 2 * M_PI;
330                 } else if (theKey == 'm' || theKey == 'I') {
331                         eyePhi += M_PI / 20;
332                 } else if (theKey == 'j' || theKey == 'J') {
333                         eyeTheta -= M_PI / 20;
334                 } else if (theKey == 'k' || theKey == 'K') {
335                         eyeTheta += M_PI / 20;
336                 } else if (theKey == ',') {
337                         eyeRho += 0.5;
338                 } else if (theKey == '.' || theKey == 'I') {
339                         eyeRho -= 0.5;
340                 } else if (theKey == 'w' || theKey == 'W') {
341                         look[1] += 0.5;
342                 } else if (theKey == 'z' || theKey == 'Z') {
343                         look[1] -= 0.5;
344                 } else if (theKey == 'a' || theKey == 'A') {
345                         look[0] -= 0.5;
346                 } else if (theKey == 's' || theKey == 'S') {
347                         look[0] += 0.5;
348                 } else if (theKey == '+') {
349                         scale *= 1.1;
350                 } else if (theKey == '-') {
351                         scale *= 0.9;
352                 }
353                 if (sin(eyePhi) > 0) upY = 1;
354                 else upY = 1;
355         #endif //FLYING_CAMERA
356 }
357
358 /**
359  * @function Graphics_Reshape
360  * @purpose Resize the view window
361  * @param width, height - New size of the window
362  */
363 void Graphics_Reshape(int width, int height) 
364 {
365         double displayRatio = 1.0 * width / height;
366         windowWidth = width;
367         windowHeight = height;
368         glMatrixMode(GL_PROJECTION);
369         glLoadIdentity();
370         gluPerspective(VIEW_ANGLE, displayRatio, WORLD_NEAR, WORLD_FAR);
371         glViewport(0, 0, windowWidth, windowHeight);
372 }
373
374
375

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