#include #include #include #include GLfloat Left, Right, Near, Far, Top, Bottom; GLfloat MinX, MaxX, MinY, MaxY; GLfloat TeaX, TeaY, TeaZ; GLfloat FrustumRotate; int WindowID[2]; void NewFrustum(); using namespace std; void DisplayString(void * font, string s) { int i; for(i=0; i < s.size(); i++) { glutStrokeCharacter(font, s[i]); } return; } void DrawFrustum(); void DrawScene(); void DrawAxis(); void display() { glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glScalef(.25, .25, .25); glTranslatef(0,0,6); glScalef(1,1,-1); glRotatef(FrustumRotate, 0,1,0); DrawAxis(); DrawFrustum(); glScalef(1,1,-1); glTranslatef(0,0,-6); DrawScene(); glFlush(); return; } void display1() { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glTranslatef(0,0,-6); DrawScene(); glFlush(); return; } void DrawAxis() { glBegin(GL_LINES); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(1,0,0); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(0,1,0); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,0,1); glEnd(); } void DrawScene() { glPushMatrix(); glTranslatef(TeaX,TeaY,TeaZ); glColor3f(1,0,0); glutWireTeapot(0.5); glPopMatrix(); return; } void DrawFrustum() { glColor3f(0,0,0); // draw the eye glutWireSphere(0.125,10,10); // draw the front and rear clipping planes glBegin(GL_POLYGON); glVertex3f(Left, Bottom, Near); glVertex3f(Left, Top, Near); glVertex3f(Right, Top, Near); glVertex3f(Right, Bottom, Near); glEnd(); glBegin(GL_POLYGON); glVertex3f(MinX, MinY, Far); glVertex3f(MaxX, MinY, Far); glVertex3f(MaxX, MaxY, Far); glVertex3f(MinX, MaxY, Far); glEnd(); // draw the edges of the frustum glEnable(GL_LINE_STIPPLE); glBegin(GL_LINES); glVertex3f(0,0,0); glVertex3f(MinX, MinY, Far); glVertex3f(0,0,0); glVertex3f(MinX, MaxY, Far); glVertex3f(0,0,0); glVertex3f(MaxX, MaxY, Far); glVertex3f(0,0,0); glVertex3f(MaxX, MinY, Far); glEnd(); glDisable(GL_LINE_STIPPLE); return; } void reset() { Left = -1.0; Right = 1.0; Top = 1.0; Bottom = -1.0; Near = 1.0; Far = 5.0; TeaX = 0; TeaY = 0; TeaZ = 3; FrustumRotate = -90; return; } void setup() { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glClearColor(1,1,1,0); glEnable(GL_DEPTH_TEST); glLineStipple(2,0xAAAA); return; } void setup1() { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glClearColor(1,1,1,0); return; } void NewFrustum() { GLfloat scale = Far/Near; MinX = Left * scale; MaxX = Right * scale; MinY = Bottom * scale; MaxY = Top * scale; glutSetWindow(WindowID[0]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-2.0, 2.0, -2.0, 2.0, -10, 10); glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); glutSetWindow(WindowID[1]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(Left,Right, Bottom, Top, Near, Far); glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); return; } void resize(int w, int h) { glViewport(0, 0, w, h); NewFrustum(); return; } void resize1(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(Left, Right, Bottom, Top, Near, Far); glMatrixMode(GL_MODELVIEW); return; } void keypress (unsigned char key, int x, int y) { const float MOVE_AMOUNT = 0.25; switch(key) { case 'H': TeaX += MOVE_AMOUNT; break; case 'J': TeaY += MOVE_AMOUNT; break; case 'K': TeaZ += MOVE_AMOUNT; break; case 'h': TeaX -= MOVE_AMOUNT; break; case 'j': TeaY -= MOVE_AMOUNT; break; case 'k': TeaZ -= MOVE_AMOUNT; break; case 'N': Near *= 1.10; NewFrustum(); break; case 'F': Far *= 1.10; NewFrustum(); break; case 'T': Top *= 1.10; NewFrustum(); break; case 'B': Bottom *= 1.10; NewFrustum(); break; case 'L': Left *= 1.10; NewFrustum(); break; case 'R': Right *= 1.10; NewFrustum(); break; case 'n': Near *= .90; NewFrustum(); break; case 'f': Far *= .90; NewFrustum(); break; case 't': Top *= .90; NewFrustum(); break; case 'b': Bottom *= .90; NewFrustum(); break; case 'l': Left *= .90; NewFrustum(); break; case 'r': Right *= .90; NewFrustum(); break; case '!': // shift of the 1 FrustumRotate -= 5; break; case '1': FrustumRotate += 5; break; case '2': reset(); NewFrustum(); break; case 'q': exit(0); } glutSetWindow(WindowID[0]); glutPostRedisplay(); glutSetWindow(WindowID[1]); glutPostRedisplay(); return; } int main(int argc, char * argv[]) { reset(); glutInit(&argc, argv); glutInitContextVersion(3, 0); glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(500, 500); WindowID[0] = glutCreateWindow("Frustrum"); glutDisplayFunc(display); glutReshapeFunc(resize); glutKeyboardFunc(keypress); setup(); WindowID[1] = glutCreateWindow("Frustrum View"); glutDisplayFunc(display1); glutReshapeFunc(resize1); glutKeyboardFunc(keypress); setup1(); glewExperimental = GL_TRUE; glewInit(); glutMainLoop(); }