#include #include #include #include "geometry.h" inline double deg2Rad(double x){return 3.14159 * x/360.0;} using namespace std; // function prototypes void display(void); void reshape(int width, int height); void keyboard(unsigned char key, int x, int y); void arrowKeys(int key, int x, int y); void init(void); // viewpoint // Let v be the vector from center (of focus) to the eye. // Let v' be the projection of v onto the x-z plane. // Then theta is the angle in degrees v // makes with the x-z plane // And phi is the angle in degrees v' // makes with the z-axis // d = ||v|| // The user controls the eye position by adjusting // theta, phi, d, and center. double theta=0.5, phi=0, d=150; Tuple center(0,0,0); // window int width = 400; int height = 400; int main(int argc, char **argv) { // set up window glutInitWindowSize(400, 400); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Camera Demo"); // register callback functions glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(arrowKeys); // initalize opengl parameters init(); // loop until something happens glutMainLoop(); return 0; } void init() { // initialize viewing system glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, 1.0, 1.0, 1000.0); glMatrixMode(GL_MODELVIEW); // shading model glEnable(GL_SMOOTH); // initialize background color to black glClearColor(0.0,0.0,0.0,0.0); // enable depth buffering glEnable(GL_DEPTH_TEST); } void reshape(int newWidth, int newHeight) { width = newWidth; height = newHeight; // preserve aspect ratio if (width < height) glViewport(0,0,width,width); else glViewport(0,0,height,height); } void display() { // Redraw scene glLoadIdentity(); // compute eye position Tuple eye(0,0,0); eye[0] = center[0] + (float) d * cos(deg2Rad(theta)) * sin(deg2Rad(phi)); eye[1] = center[1] + (float) 2*d * sin(deg2Rad(theta)); eye[2] = center[2] + (float) d * cos(deg2Rad(theta)) * cos(deg2Rad(phi)); // compute up vector // we use (0,1,0) as the default up position // this doesn't work if the eye is on the y-axis // but we just won't let the user do that Tuple up(0,1,0); gluLookAt(eye[0],eye[1],eye[2], center[0],center[1],center[2],up[0], up[1], up[2]); // clear buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // now draw axis in x,y,z directions from origin glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINES); glVertex3f(0,0,0); glVertex3f(100,0,0); glEnd(); glBegin(GL_LINES); glVertex3f(0,0,0); glVertex3f(0,100,0); glEnd(); glBegin(GL_LINES); glVertex3f(0,0,0); glVertex3f(0,0,100); glEnd(); // now draw axis in x,y,z directions from center glColor3f(0.0f, 1.0f, 1.0f); glBegin(GL_LINES); glVertex3f(center[0],center[1],center[2]); glVertex3f(center[0]+100,center[1],center[2]); glEnd(); glBegin(GL_LINES); glVertex3f(center[0],center[1],center[2]); glVertex3f(center[0],center[1]+100,center[2]); glEnd(); glBegin(GL_LINES); glVertex3f(center[0],center[1],center[2]); glVertex3f(center[0],center[1],center[2]+100); glEnd(); // draw to screen glutSwapBuffers(); } void keyboard(unsigned char key, int mouseX, int mouseY) { switch (key) { case 'h': cout << "Use '-' and '+' to zoom in and out." << endl; cout << "Use 'c' to reset center."; break; case '-': if (d>1) d--; break; case '+': d++; break; case 'c': case 'C': { float x,y,z; cout << "Enter x,y,z position of center of focus." << endl; cin >> x >> y >> z; center[0]=x; center[1]=y; center[2]=z; break; } } glutPostRedisplay(); } /* * This routine reads arrow keys and adjusts * camera position/orientation. */ void arrowKeys(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: phi -=2; // change break; case GLUT_KEY_RIGHT: phi +=2; break; case GLUT_KEY_UP: if (theta < 85) theta +=2; break; case GLUT_KEY_DOWN: if (theta >-85) theta -=2; break; default: break; } glutPostRedisplay(); }