// OpenGL main program // ==================================================================== // STANDARD INCLUDES #include #include #include // LAB SPECIFIC #include "lab1.h" // =================================================================== // STANDARD DEFINES #define FPS 30 // frames per second - for 'timed display' #define STEP 1 // mode flag #define RUN 2 // mode flag // =================================================================== // TYPEDEFS // CAMERA typedef struct camera_struct { float distance; // distance from coi float x,y,z; // location float cx,cy,cz; // center of interest float theta; // y-axis angle from positive x-axis (0:360) float phi; // angle up from x-z plane (-180:+180) float tilt; // rotation around view direction } camera_td; // ================================================================ // PROTOTYPE FUNCTIONS void reshape(int w, int h); void setLights(); void initDisplay(void); void initView(); void initRender(); void display(void); void setCamera(); void parse_key(unsigned char key, int x, int y); void parse_special_key(int key, int x, int y); void processMouse(int button, int state, int x, int y); void processMouseActiveMotion (int x,int y); // =============================================================== // GLOBALS for display and interactiion camera_td camera; static int mode = STEP; static int debug = 0; // ================================================================ // DEFINES #define LEFT 1 #define MIDDLE 2 #define RIGHT 3 #define PI 3.14159 #define EPSILON 0.0001 // ================================================================ // MAIN // ================================================================ int main(int argc, char** argv) { // initialize glut and window glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowPosition(40, 40); glutInitWindowSize(640, 480); glutCreateWindow("Animate"); // setup callbacks glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(parse_key); glutSpecialFunc(parse_special_key); glutMouseFunc(processMouse); glutMotionFunc(processMouseActiveMotion); initDisplay(); // init display OpenGl parameters Animation_init(); // init animation initView(); // init view parameters glutMainLoop(); return EXIT_SUCCESS; } // ================================================================== // ================================================================== // ROUTINES to MANAGE DISPLAY // ------------------------------------------------------------------ // DISPLAY // ------------------------------------------------------------------ void display(void) { if (debug == 1) printf("display\n"); if (mode == STEP) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear buffer initRender(); // init OpenGL rendering Animation_render(); // render current state // force out and swap buffers glFlush(); glutSwapBuffers(); } } // --------------------------------------------------------------------------- // TIMED DISPLAY // --------------------------------------------------------------------------- void timedDisplay(int n) { if (debug == 1) printf("timed display\n"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear buffer initRender(); // init OpenGL rendering Animation_update(); // update animation and render // force out and swap buffers glFlush(); glutSwapBuffers(); if (mode == RUN) glutTimerFunc(1000/FPS,timedDisplay,0); } // -------------------------------------------------------------------- // INIT RENDER // to set camera and lights in OpenGL // -------------------------------------------------------------------- void initRender() { glLoadIdentity(); gluLookAt(camera.x,camera.y,camera.z,camera.cx,camera.cy,camera.cz, 0.0,1.0,0.0); setLights(); } // -------------------------------------------------------------------- // RESHAPE // -------------------------------------------------------------------- void reshape(int width, int height) { glViewport(0, 0, width, height); } // ==================================================================== // ==================================================================== // ROUTINES to setup RENDERING ENVIRONMENT // -------------------------------------------------------------------- // INITIALIZE DISPLAY // only needs to be done once at beginning of program // -------------------------------------------------------------------- void initDisplay (void) { glShadeModel (GL_SMOOTH); glFrontFace(GL_CCW); glEnable(GL_DEPTH_TEST); glClearColor(0.8,0.8,0.8,1.0); glColor3f(1.0, 1.0, 1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum (-0.1, 0.1, -0.1, 0.1, 0.2, 550.0); glMatrixMode(GL_MODELVIEW); } // --------------------------------------------------------------------- // SET CAMERA // should be called any time a camera parameter changes // --------------------------------------------------------------------- void setCamera(void) { float radiusOut; // rotate up radiusOut = cos(camera.theta); camera.y = camera.distance*sin(camera.theta); // rotate around y-axis camera.x = camera.distance*cos(camera.phi)*radiusOut; camera.z = camera.distance*sin(camera.phi)*radiusOut; } // ---------------------------------------------------------- // INIT VIEW // initialize view parameters for camera // only needs to be done once at begining or if a 'reset' is requested // ---------------------------------------------------------- void initView () { camera.distance = 100.0; camera.phi = PI/2.0; camera.theta = PI/2.0; camera.tilt = 0.0; camera.x = 1.0; camera.y = 3.0; camera.z = 4.0; camera.cx = 0.0; camera.cy = 0.0; camera.cz = 0.0; setCamera(); glutPostRedisplay(); } // ---------------------------------------------------------------- // SET LIGHTS // ---------------------------------------------------------------- #define AMBIENT0 0.5 #define DIFFUSE0 0.5 #define SPECULAR0 0.4 #define AMBIENT1 0.5 #define DIFFUSE1 0.5 #define SPECULAR1 0.4 void setLights() { GLfloat light0_ambient[] = { AMBIENT0,AMBIENT0,AMBIENT0,1.0 }; GLfloat light0_diffuse[] = { DIFFUSE0,DIFFUSE0,DIFFUSE0,1.0 }; GLfloat light0_specular[] = { SPECULAR0,SPECULAR0,SPECULAR0,1.0 }; GLfloat light0_position[] = { 0.0, 10.0, 3.0, 1.0 }; GLfloat light1_ambient[] = { AMBIENT1,AMBIENT1,AMBIENT1,1.0 }; GLfloat light1_diffuse[] = { DIFFUSE1,DIFFUSE1,DIFFUSE1,1.0 }; GLfloat light1_specular[] = { SPECULAR1,SPECULAR1,SPECULAR1,1.0 }; GLfloat light1_position[] = { -5.0,-10.0,2.0,1.0 }; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR,light0_specular); glLightfv(GL_LIGHT0, GL_POSITION,light0_position); glEnable(GL_LIGHT1); glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR,light1_specular); glLightfv(GL_LIGHT1, GL_POSITION,light1_position); } // ================================================================= // ================================================================= // CALLBACK ROUTINES to MANAGE INTERACTION // ----------------------------------------------------------------- // PARSE KEY // ----------------------------------------------------------------- void parse_key(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); // cntrl-Q case 118: // v: reset view initView(); setCamera(); glutPostRedisplay(); break; case 105: // i: zoom In camera.distance /= 1.5; setCamera(); glutPostRedisplay(); break; case 111: // o: zoom Out camera.distance *= 2.0; setCamera(); glutPostRedisplay(); break; case 114: // r: reset Animation_init(); glutPostRedisplay(); break; case 115: // s: step mode mode = STEP; if (debug == 1) printf("mode = STEP\n"); Animation_update(); glutPostRedisplay(); break; case 99: // c: continuous run mode mode = RUN; if (debug == 1) printf("mode = RUN\n"); glutTimerFunc(1000/FPS,timedDisplay,0); break; default: printf("%d\n",key); } } // ------------------------------------------------------------------ // PARSE SPECIAL KEY // ------------------------------------------------------------------ void parse_special_key(int key, int x, int y) { switch (key) { case GLUT_KEY_UP: camera.theta -= 0.25; break; case GLUT_KEY_DOWN: camera.theta += 0.25; break; case GLUT_KEY_RIGHT: camera.phi += 0.25; break; case GLUT_KEY_LEFT: camera.phi -= 0.25; break; } setCamera(); glutPostRedisplay(); } int mousex,mousey; float eyeD,eyeA,eyeT; int buttonDown; // ------------------------------------------------------------------ // PROCESS MOUSE // when down, use to control rotation of camera around origin // ------------------------------------------------------------------ void processMouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { if (button == GLUT_LEFT_BUTTON) { buttonDown = LEFT; eyeA = camera.phi; eyeT = camera.theta; } else { if (button == GLUT_MIDDLE_BUTTON) { buttonDown = MIDDLE; eyeD = camera.distance; } else { buttonDown = RIGHT; } } mousex = x; mousey = y; } } // ------------------------------------------------------------------ // PROCESS MOUSE ACTIVE MOTION // ------------------------------------------------------------------ void processMouseActiveMotion (int x,int y) { if (buttonDown == LEFT) { // angle around camera.phi = eyeA + 0.005*(x - mousex); // angle up and down camera.theta = eyeT + 0.005*(y - mousey); if (camera.theta >= PI/2) camera.theta = PI/2 - EPSILON; if (camera.theta <= -PI/2) camera.theta = -(PI/2 - EPSILON); } else { if (buttonDown == MIDDLE) camera.distance = eyeD*(1.0 + (y - mousey)/500.0); } setCamera(); glutPostRedisplay(); }