/* * Logo_fly.c * * draws a letter 'L' * add interactive controls & animation */ /* #include */ #include #include #include #include #include #include /* Constant values */ const double PI = 3.14159265; /* Screen window parameters */ int windType; GLint windW, windH; /* Display list parameters */ GLuint letterL; // display list speeds up rendering /* camera parameters */ struct camera { float ex, ey, ez; /* eye position */ float ux, uy, uz; /* u axis */ float vx, vy, vz; /* v axis */ float nx, ny, nz; /* n axis */ } myCamera; GLdouble spin_angle = 0.0; GLdouble spin_increment = 0.05; GLboolean animate = FALSE; /* camera functions */ void init_camera (float ex, float ey, float ez, // eye or camera coordinates (origin of view) float ux, float uy, float uz, // u axis (points to right of origin) float vx, float vy, float vz, // v axis (points up from origin) float nx, float ny, float nz) // n axis (points opposite of view direction) { myCamera.ex = ex; myCamera.ey = ey; myCamera.ez = ez; myCamera.ux = ux; myCamera.uy = uy; myCamera.uz = uz; myCamera.vx = vx; myCamera.vy = vy; myCamera.vz = vz; myCamera.nx = nx; myCamera.ny = ny; myCamera.nz = nz; } void setModelViewMatrix(struct camera C) { float m[16]; m[0] = C.ux; m[1] = C.vx; m[2] = C.nx; m[3] = 0; m[4] = C.uy; m[5] = C.vy; m[6] = C.ny; m[7] = 0; m[8] = C.uz; m[9] = C.vz; m[10] = C.nz; m[11] = 0; m[12] = -((C.ex * C.ux) + (C.ey * C.uy) + (C.ez * C.uz)); m[13] = -((C.ex * C.vx) + (C.ey * C.vy) + (C.ez * C.vz)); m[14] = -((C.ex * C.nx) + (C.ey * C.ny) + (C.ez * C.nz)); m[15] = 1; glMatrixMode (GL_MODELVIEW); glLoadMatrixf (m); } void slide_camera (float dx, float dy, float dz) { myCamera.ex += (dx * myCamera.ux) + (dy * myCamera.vx) + (dz * myCamera.nx); myCamera.ey += (dx * myCamera.uy) + (dy * myCamera.vy) + (dz * myCamera.ny); myCamera.ez += (dx * myCamera.uz) + (dy * myCamera.vz) + (dz * myCamera.nz); } /* FILL IN THESE FUNCTIONS TO CHANGE YAW OR PITCH ANGLE: Yaw rotates about v axis, Pitch rotates about u axis. For Roll, you would rotate by angle A about n axis: n' = n u' = cos(A)*u - sin(A)*v v' = sin(A)*u + cos(A)*v */ /* Rotate about u (left-right) axis of camera */ /* Hint: let angle be in degrees, but use radians to calculate sin & cos) */ void pitch_camera (double angle) { /* PUT YOUR CODE HERE */ } /* Rotate about v (up-down) axis of camera */ /* Hint: let angle be in degrees, but use radians to calculate sin & cos) */ void yaw_camera (double angle) { /* PUT YOUR CODE HERE */ } /* FILL IN THIS FUNCTION TO INCREMENTALLY CHANGE POSITION / ORIENTATION / SIZE OF LOGO */ /* Hint: change global rotation or position value(s) by a small amount, then use the value(s) as parameters in the Draw function */ void fly (void) { /* PUT YOUR CODE HERE */ glutPostRedisplay(); /* force update of the display */ } /* draw the letter L in a display list called L */ void drawL (void) { #define NPOINTS 12 #define NPOLYGONS 10 /* define all the points on the letter */ GLdouble point[NPOINTS][3] = { {0.0, 0.0, 1.0}, {2.0, 0.0, 1.0}, {2.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 3.0, 1.0}, {0.0, 3.0, 1.0}, {0.0, 0.0, 0.0}, {2.0, 0.0, 0.0}, {2.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, {1.0, 3.0, 0.0}, {0.0, 3.0, 0.0}}; /* each polygonal face references 4 points */ int polygon[NPOLYGONS][4] = { {0, 1, 2, 3}, /* front faces */ {0, 3, 4, 5}, {9, 8, 7, 6}, /* back faces */ {11, 10, 9, 6}, {0, 5, 11, 6}, /* side faces */ {1, 0, 6, 7}, {2, 1, 7, 8}, {3, 2, 8, 9}, {4, 3, 9, 10}, {5, 4, 10, 11}}; /* color array defines a different color for each face */ GLdouble color[NPOLYGONS][3] = { {1.0, 1.0, 1.0}, /* front faces */ {1.0, 1.0, 1.0}, {0.2, 0.2, 0.2}, /* back faces */ {0.2, 0.2, 0.2}, {0.4, 0.4, 0.4}, /* side faces */ {0.5, 0.5, 0.5}, {0.6, 0.6, 0.6}, {0.7, 0.7, 0.7}, {0.8, 0.8, 0.8}, {0.9, 0.9, 0.9}}; int face, pt; /* Setup display list */ letterL = glGenLists(1); glNewList (letterL, GL_COMPILE); /* Draw the letter */ for (face = 0; face < NPOLYGONS; face++) { glColor3dv(color[face]); /* set the color of the face */ glBegin(GL_POLYGON); for (pt = 0; pt < 4; pt++) /* draw all points on the face */ glVertex3dv (point[polygon[face][pt]]); glEnd(); } /* Finish the display list */ glEndList(); } /* Setup OpenGL state machine */ static void Init(void) { /* Set background color */ glClearColor(0.0, 0.0, 0.0, 0.0); /* Enable depth buffer */ glEnable(GL_DEPTH_TEST); /* Enable back-face culling */ glCullFace(GL_BACK); glEnable(GL_CULL_FACE); /* Set polygon attributes */ glPolygonMode (GL_FRONT, GL_FILL); /* Set shading & lighting values*/ glShadeModel (GL_FLAT); } /* Window size has changed: adjust viewport and perspective transformations */ static void Reshape(int width, int height) { float aspect; // aspect ratio = w/h windW = (GLint)width; windH = (GLint)height; aspect = (float)windW / (float)windH; /* Viewport fills the entire window */ glViewport(0, 0, width, height); /* Use orthographic projection to set visibility boundaries relative to viewing coordinates */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (90.0, aspect, 1.0, 100.0); /* fovy, aspect, near, far */ /* Return to modelview mode */ glMatrixMode(GL_MODELVIEW); } /* Arrow keys change yaw and pitch */ static void Key2(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: /* decrease angle about Y axis */ yaw_camera(-5.0); break; case GLUT_KEY_RIGHT: /* increase angle about Y axis */ yaw_camera(5.0); break; case GLUT_KEY_UP: /* decrease angle about X axis */ pitch_camera(-5.0); break; case GLUT_KEY_DOWN: /* increase angle about X axis */ pitch_camera(5.0); break; default: return; } glutPostRedisplay(); /* force update of the display */ } /* Handle other keys */ static void Key(unsigned char key, int x, int y) { switch (key) { case 27: /* ESC to quit */ exit(1); case 'r': case 'R': slide_camera (1.0, 0.0, 0.0); /* move camera right */ break; case 'l': case 'L': slide_camera (-1.0, 0.0, 0.0); /* move camera left */ break; case 'u': case 'U': slide_camera (0.0, 1.0, 0.0); /* move camera up */ break; case 'd': case 'D': slide_camera (0.0, -1.0, 0.0); /* move camera up */ break; case 'b': case 'B': slide_camera (0.0, 0.0, 1.0); /* move camera back */ break; case 'f': case 'F': slide_camera (0.0, 0.0, -1.0); /* move camera forward */ break; case 'a': case 'A': if (animate) glutIdleFunc(NULL); else glutIdleFunc(fly); animate = !animate; /* move camera forward */ break; case '+': /* Add code to make the logo spin faster */ break; case '-': /* Add code to make the logo spin slower */ break; default: return; } glutPostRedisplay(); /* force update of the display */ } /* Set modeling and viewing transformations, then draw the letter polygons */ static void Draw(void) { // int face, pt; /* clear the screen AND the depth buffer */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Set the viewing transformation(s) */ /* First, set the eye/camera position */ glLoadIdentity(); setModelViewMatrix (myCamera); /* Load transformation for camera view */ /* Transform the letter to the correct position (using global values set by "fly") */ /* PUT YOUR CODE HERE */ /* Draw the 1st letter */ glCallList(letterL); glFlush(); /* force all changes to be applied to buffer */ glutSwapBuffers(); /* display what you just drew */ } void main(int argc, char **argv) { /* Setup the window that logo will appear in */ windW = 300; windH = 300; glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH); /* Window uses depth buffer, full color, and double buffering */ windType = GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE; glutInitDisplayMode((GLenum)windType); if (glutCreateWindow("Logo") == GL_FALSE) { exit(1); } Init(); drawL(); /* Create display list letterL */ /* Initially center camera on world system, & step back 8 */ init_camera (0.0, 0.0, 8.0, // camera position in world coordinates 1.0, 0.0, 0.0, // u vector (points to the right) 0.0, 1.0, 0.0, // v vector (points up) 0.0, 0.0, 1.0); // n vector (points opposite to line-of-sight) glutReshapeFunc(Reshape); glutKeyboardFunc(Key); glutSpecialFunc(Key2); glutDisplayFunc(Draw); glutMainLoop(); }