/* * perspcube: static cube with perspective camera * * P Flynn 021703: based on Angel's cube.c * * * This program displays a wireframe cube in perspective. * By default, an isometric view is provided, with reasonable defaults. * * The initial perspective frustum has a large distance between the * front and rear clipping planes. * * Interaction: left and middle mouse buttons rotate the view if it started * out in the isometric mode (that's the way it runs by default) * * keyboard commands: * 'i' or 'I': toggle isometric mode. If you leave isometric mode, only * the keyboard commands will work. * * 'a', 'A': decrease, or increase, the aspect ratio by 5% * 'f', 'F': decrease, or increase, the FOV by 5 degrees * 'n', 'N': move the near clipping plane nearer to, or farther from, * the camera * 'm', 'M': move the far clipping plane nearer to, or farther from, * the camera. * */ #include #include #include #include GLfloat vertices[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}}; GLfloat colors[][3] = {{0.3,0.6,0.7},{1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}}; void polygon(int a, int b, int c , int d) { /* draw a polygon via list of vertices */ //glBegin(GL_POLYGON); glBegin(GL_LINE_LOOP); glColor3fv(colors[a]); glVertex3fv(vertices[a]); glColor3fv(colors[b]); glVertex3fv(vertices[b]); glColor3fv(colors[c]); glVertex3fv(vertices[c]); glColor3fv(colors[d]); glVertex3fv(vertices[d]); glEnd(); } void colorcube(void) { /* map vertices to faces */ polygon(0,3,2,1); polygon(2,3,7,6); polygon(0,4,7,3); polygon(1,2,6,5); polygon(4,5,6,7); polygon(0,1,5,4); } /* * The camera: * - looks at the origin always * - is located on a sphere of radius r * - theta and phi control eye point and view-up vector * * Note: tune "r" and front/rear clipping planes * to make sure geometry fits (by default) */ static GLfloat fovy=90.0, aspect=1.0, near=1.0,far=30.0; static int isometric=1; static GLfloat theta = 45.0, phi=45.0; static GLfloat r = 5; void display(void) { float xeye,yeye,zeye; /* display callback, clear frame buffer and z buffer, rotate cube and draw, swap buffers */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fovy,aspect,near,far); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (isometric) { xeye = r * cos(phi*M_PI/180.0) * cos(theta*M_PI/180.0); yeye = r * cos(phi*M_PI/180.0) * sin(theta*M_PI/180.0); zeye = r * sin(phi*M_PI/180.0); gluLookAt(xeye,yeye,zeye, // eye 0.0,0.0,0.0, // at 0.0,0.0,1.0); // vup } else { glTranslatef(0.0,0.0,-5.0); // back up along z axis } glLineWidth(3.0); glBegin(GL_LINES); glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(1.5,0.0,0.0); glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,1.5,0.0); glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,1.5); glEnd(); colorcube(); glFlush(); glutSwapBuffers(); } void keyboard(unsigned char key,int x,int y) { switch(key) { case 'a': aspect /= 1.05; break; //5% deflate aspect case 'A': aspect *= 1.05; break; case 'f': fovy -= 5.0; break; // 5 degree deinflate fov case 'F': fovy += 5.0; break; case 'n': near -= 0.05; break; case 'N': near += 0.05; break; case 'm': far -= 0.05; break; case 'M': far += 0.05; break; case 'q': exit(0); break; case 'r': // reset aspect = 1.0; fovy = 90.0; near = 1.0; far = 30.0; isometric=1; break; case 'i': case 'I': isometric = 1-isometric; break; default: break; // nothing } glutPostRedisplay(); } void mouse(int btn, int state, int x, int y) { if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) { theta += 2; if (theta >= 360.0) theta -= 360.0; }; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { phi += 2; if (phi >= 360.0) phi -= 360.0; }; glutPostRedisplay(); } /* pjf note: this function is called prior to first display, so can be used as an init function as well... I think that's what Angel did here */ void myReshape(int w, int h) { glViewport(0, 0, w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0); else glOrtho(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } void main(int argc, char **argv) { glutInit(&argc, argv); /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow("colorcube"); glutReshapeFunc(myReshape); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */ /* pjf this should be in a separate init function! */ //glShadeModel(GL_FLAT); glutMainLoop(); }