#include "graphics.h" //Function declarations
#include "nbody.h" //The simulation
-#include <GL/freeglut.h>
+
// --- Variable definitions --- //
double previousTime, eyeTheta, eyePhi, eyeRho;
*/
void Graphics_Run(int argc, char ** argv)
{
+
if (options.draw_graphics == false)
{
// This message is left here for when I inevitably accidentally call the function
glutCreateWindow("N-Body : Multi-Threaded (pthread)");
#elif defined OMP_THREADED
glutCreateWindow("N-Body : Multi-Threaded (OpenMP)");
+ #elif defined BARNES_HUT
+ glutCreateWindow("N-Body : Barnes Hut Algorithm");
#else
glutCreateWindow("N-Body");
#endif
gluPerspective(VIEW_ANGLE, (double)WIDTH/(double)HEIGHT, WORLD_NEAR, WORLD_FAR);
#ifdef FLYING_CAMERA
- eye.x[0] = 1; eye.x[1] = 0; eye.x[2] = 0;
+ eye.x[0] = 0; eye.x[1] = 0; eye.x[2] = 1;
eye.y[0] = 0; eye.y[1] = 1; eye.y[2] = 0;
- eye.z[0] = 0; eye.z[1] = 0; eye.z[2] = 1;
+ eye.z[0] = 1; eye.z[1] = 0; eye.z[2] = 0;
+ eye.p[0] = 0; eye.p[1] = 0; eye.p[2] = -50;
#endif //FLYING_CAMERA
- glutMainLoop();
+
+ //This option must be set, or when glut leaves the main loop. the exit(3) function is called... annoying
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
+
+
+ #ifndef OMP_THREADED
+ #ifndef BARNES_HUT
+ glutMainLoop(); // the mthread and single-thread versions can just start the loop here
+ // In OpenMP, because barriers have to be within the #pragma, need glutMainLoopEvent in the #pragma
+ #endif //BARNS_HUT
+ #endif //OMP_THREADED
}
/**
//Check whether the graphics thread should exit for any reason
if (ExitCondition())
{
+ QuitProgram(false);
glutLeaveMainLoop(); // original glut does not have this, which makes "nicely" exiting a bit annoying
return;
}
glLoadIdentity();
#ifdef FLYING_CAMERA
+
gluLookAt(eye.p[0], eye.p[1], eye.p[2],
eye.p[0] + eye.x[0], eye.p[1] + eye.x[1], eye.p[2] + eye.x[2],
eye.z[0], eye.z[1], eye.z[2]);
for (int i = 0; i < universe.N; ++i)
{
+
Body * b = universe.body+i;
glColor3f(0.0f, b->mass/1e11*100, 0.0f);
//glColor3f(1.0f, 0.0f, 0.0f);
glutSolidSphere (BALL_SIZE, 10, 10);
glPopMatrix(); // restore the previous matrix
}
- glFlush();
+
AfterDraw(); // Stuff to do after graphics is done drawing
// Single-thread - Nothing at all
// Multiple threads - signal threads it is safe to change position variables
-
+ glFlush();
}
/**
{
if (theKey == 'x' || theKey == 'X')
{
+
QuitProgram(false);
+ glutLeaveMainLoop();
return;
}
#ifdef FLYING_CAMERA
+ float s = 10;
switch (theKey)
{
+ // Translate in direction of camera
case 'W':
case 'w':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] += eye.x[i];
+ eye.p[i] += s * eye.x[i];
break;
+ // Translate backwards from camera direction
case 'S':
case 's':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] -= eye.x[i];
+ eye.p[i] -= s * eye.x[i];
break;
+ // Translate left from camera direction
case 'A':
case 'a':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] += eye.y[i];
+ eye.p[i] -= s * eye.y[i];
break;
+ // Translate right from camera direction
case 'D':
case 'd':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] -= eye.y[i];
+ eye.p[i] += s * eye.y[i];
break;
- case 'Z':
- case 'z':
+ // Translate up from camera direction
+ case 'Q':
+ case 'q':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] += eye.z[i];
+ eye.p[i] += s * eye.z[i];
break;
- case 'C':
- case 'c':
+ // Translate down from camera direction
+ case 'E':
+ case 'e':
for (unsigned i = 0; i < DIMENSIONS; ++i)
- eye.p[i] -= eye.z[i];
+ eye.p[i] -= s * eye.z[i];
break;
+ // Rotate camera direction "down"
+ // (pitch control)
case 'I':
case 'i':
{
}
break;
}
+ // Rotate camera direction "up"
+ // (pitch control)
case 'K':
case 'k':
{
}
break;
}
-
+ // Rotate camera direction "left"
+ // (yaw control)
case 'J':
case 'j':
{
- float theta = -M_PI/80.0;
+ float theta = +M_PI/80.0;
Camera old = eye;
for (unsigned i = 0; i < DIMENSIONS; ++i)
}
break;
}
-
+ // Rotate camera direction "right"
+ // (yaw control)
case 'L':
case 'l':
{
- float theta = M_PI/80.0;
+ float theta = -M_PI/80.0;
Camera old = eye;
for (unsigned i = 0; i < DIMENSIONS; ++i)
}
break;
}
-
- case 'Q':
- case 'q':
+ // Rotate camera direction CCW about its axis
+ // (roll control)
+ case 'U':
+ case 'u':
{
- float theta = M_PI/80.0;
+ float theta = -M_PI/80.0;
Camera old = eye;
for (unsigned i = 0; i < DIMENSIONS; ++i)
}
break;
}
- case 'E':
- case 'e':
+ // Rotate camera direction CW about its axis
+ // (roll control)
+ case 'O':
+ case 'o':
{
- float theta = -M_PI/80.0;
+ float theta = +M_PI/80.0;
Camera old = eye;
for (unsigned i = 0; i < DIMENSIONS; ++i)
}
}
- /*
- float x = 0; float y = 0; float z = 0;
- for (unsigned i = 0; i < DIMENSIONS; ++i)
- {
- x += eye.x[i] * eye.x[i];
- y += eye.y[i] * eye.y[i];
- z += eye.z[i] * eye.z[i];
- }
- for (unsigned i = 0; i < DIMENSIONS; ++i)
- {
- eye.x[i] /= sqrt(x);
- eye.y[i] /= sqrt(y);
- eye.z[i] /= sqrt(z);
- }
- */
+ /* Code used for debugging the camera
system("clear");
printf("Camera status:\n");
printf("Position: %f %f %f\n", eye.p[0], eye.p[1], eye.p[2]);
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]));
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]));
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]));
-
- #else
-
+ */
+ #else // The original view code
+ // I like how 'I' is used three times.
if (theKey == 'i' || theKey == 'I') {
eyePhi -= M_PI / 20;