user1240679
user1240679

Reputation: 6979

Change of coordinates with glFrustum

I am trying to use glFrustum for a perspective projection and as I understand glFrustum like glOrtho can be used to modify the mapping of our desired coordinate system to real screen coordinates (as read in Blue book). So, if I do
glFrustum(-1,1,-1,1,1,1000);, it changes the coordinates to
left = -1, right = 1, bottom = -1, top = 1 in the form of cartesian coordinates.

I tried to draw a simple room (with 2 side walls) in this coordinate system by calling the following function in my draw method and it comes out drawing appropriately on the screen.

void drawRoomWalls(){
    //Left wall
    glBegin(GL_QUADS);
    glVertex3f(-1.0, 1.0, 0.0);
    glVertex3f(-1.0, 1.0, -0.4);
    glVertex3f(-1.0, -1.0, -0.4);
    glVertex3f(-1.0, -1.0, 0.0);
    glEnd();

    //Right wall
    glBegin(GL_QUADS);
    glVertex3f(1.0, 1.0, 0.0);
    glVertex3f(1.0, 1.0, -0.4);
    glVertex3f(1.0, -1.0, -0.4);
    glVertex3f(1.0, -1.0, 0.0);
    glEnd();
}

The function was called as follows:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
    glFrustum(1.0, -1.0, -1.0, 1.0, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -1.0);
drawRoomWalls();

Subsequently, I tried to do an off-axis projection (by taking mouse as input instead of user's head). The code is as follows: glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix();

double fov, near, far;
double headX, headY, headZ;
float aspectRatio;

near = 0.5f; far = 1000.0f;  aspectRatio = ofGetWidth()/ofGetHeight();
fov = tan(DEG_TO_RAD * 30/2); //tan accepts angle in radians. tan of the half of the fov angle
fov = 0.5; //taken constant for now

double msX = (double)ofGetMouseX();
double msY = (double)ofGetMouseY();
double scrWidth = (double)ofGetWidth();
double scrHeight = (double)ofGetHeight();

headX = (msX / scrWidth) - 0.5; 
headY = ((scrHeight - msY) / scrHeight) - 0.5;
headZ = -2.0;

glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum( near * (-fov * aspectRatio + headX),
               near * (fov * aspectRatio + headX),
               near * (-fov + headY),
               near * (fov + headY),
               near,
               far);

leftValue = near * (-fov * aspectRatio + headX); //for printing out on screen
rightValue = near * (fov * aspectRatio + headX); //for printing out on screen
bottomValue = near * (-fov + headY); //for printing out on screen
topValue = near * (fov + headY); //for printing out on screen

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(headX * headZ, headY * headZ, 0, headX * headZ, headY * headZ, -1, 0, 1, 0);
glTranslatef(0.0, 0.0, headZ);
drawRoomWalls();


I printed the values of leftValue, rightValue, bottomValue, topValue and when the mouse is in the center of the screen (the call to glFrustum looks like glFrustum(-0.25,0.25,-0.25,0.25,1.0,1000.0)
As per the above call, I expected the coordinate system's left=-0.25, right=0.25, bottom=-0.25, top=0.25 and I was expecting the walls to disappear (since they are draw at (1.0,1.0,0.0) for an example). However, the walls keep on appearing on the sides of the screen (with the scene being skewed and at the center being essentially the same as with off-axis projection). Why is it that the walls are still at the place on the sides (even though the coordinates changed to -0.25,0.25) or there's something in glFrustum call that I am missing here about the coordinate system?

Upvotes: 3

Views: 765

Answers (1)

Nico Schertler
Nico Schertler

Reputation: 32607

I just realized that you also changed headZ to -2. That explains the behaviour.

If the camera is situated at z = 2 and you have a vertical half fov of 0.5, then at z = 0 you already see 1 unit in positive and negative y-direction. That's why you see the walls.

Visualization

Upvotes: 4

Related Questions