Rokas
Rokas

Reputation: 157

(c++) openGL beginner: Unexpected camera behavior when translating along z

So I decided to learn OpenGL and the very first thing I want to do is get a solid understanding of the basics. In this case, I want to get familiar with OpenGL coordinate system and camera positioning.

Here are two relevant facts about OpenGL I know this far:

  1. its coordinate axes form a right-handed coordinate system

  2. by default, the camera is placed at the origin and it points down the negative direction of the z-axis:

enter image description here

First, a conceptual question: am I right by assuming that objects behind the camera won't be visible (meaning that object coordinates must satisfy at least z < 0)?

Second, the question about the strange camera behavior I mentioned in the title. I have written a simple OpenGL program that draws a cube with center at (0,0,0) and allows me to translate the camera in real-time. Here is what I've got:

OpenGL-related code in the int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) function:

    <...>    
    HGLRC openGLContext = wglCreateContext(hDC);
    wglMakeCurrent(hDC, openGLContext);

    if (Win32LoadOpenGLFunctions())//fragment-related additon
        initOpenGL();
    <...>

Code in the initOpenGL() function:

    static void initOpenGL()
    {
        glEnable(GL_DEPTH_TEST);
    }

Code in the draw() function:

void draw()
{
    glViewport(0, 0, width, height);
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glColor3f(1.0, 1.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1, 1, -1, 1, 5, -5);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(0.0, 0.0, test);//translate the camera along the z-axis

    glBegin(GL_TRIANGLES);
        Cube(1);
    glEnd();

    glFlush();
}

The parameter test in the draw() function is bound to keypresses so I can test how the output in the screen changes as I translate the camera along the z-axis.

The Cube() function looks like this:

void Cube(float a)
{
    float A = a * 0.5f;

    //red face
    glColor3f(1, 0, 0);
    glVertex3f(A, A, A);
    glVertex3f(-A, -A, A);
    glVertex3f(A, -A, A);

    glVertex3f(A, A, A);
    glVertex3f(-A, A, A);
    glVertex3f(-A, -A, A);

    //blue face
    glColor3f(0, 0, 1);
    glVertex3f(A, A, -A);
    glVertex3f(-A, -A, -A);
    glVertex3f(A, -A, -A);

    glVertex3f(A, A, -A);
    glVertex3f(-A, A, -A);
    glVertex3f(-A, -A, -A);

    //yellow face
    glColor3f(1, 1, 0);
    glVertex3f(A, A, A);
    glVertex3f(A, A, -A);
    glVertex3f(-A, A, A);

    glVertex3f(-A, A, A);
    glVertex3f(A, A, -A);
    glVertex3f(-A, A, -A);

    //cyan face
    glColor3f(0, 1, 1);
    glVertex3f(A, -A, A);
    glVertex3f(A, -A, -A);
    glVertex3f(-A, -A, A);

    glVertex3f(-A, -A, A);
    glVertex3f(A, -A, -A);
    glVertex3f(-A, -A, -A);

    //green face
    glColor3f(0, 1, 0);
    glVertex3f(A, A, A);
    glVertex3f(A, -A, A);
    glVertex3f(A, -A, -A);

    glVertex3f(A, A, A);
    glVertex3f(A, -A, -A);
    glVertex3f(A, A, -A);

    //orange face
    glColor3f(1, 0.67, 0);
    glVertex3f(-A, A, A);
    glVertex3f(-A, -A, A);
    glVertex3f(-A, -A, -A);

    glVertex3f(-A, A, A);
    glVertex3f(-A, -A, -A);
    glVertex3f(-A, A, -A);
}

Here is a picture which shows what I assume is happening:

enter image description here

In this picture, we're looking top-down on the cube. Since I specified an orthogonal projection with 5 and -5 as the near and far clipping values, the viewing volume is a box that extends from z = 5 to z = -5. The cube has its "red" face at z = 0.5 and its "blue" face at z = -0.5. The camera is initially at (0,0,0), which means insuide the cube. Since it's looking at the "blue" face, I should see a blue square.

If I translate the camera towards the "blue" face (test < 0), I expect the "blue" face disappear when test < -0.5 since it gets behind the camera. When translating towards the "red" face (test > 0) I expect the blue square on the screen turn red when test > 0.5 (because the camera is in front of the "red" face which is blocking the "blue" face and DEPTH_TEST is on). When test > 5.0 the screen should turn black because the camera is then outside the viewing volume.

But that's not what happens. The "blue" face is visible when test changes from 0 to 5.5, at which point it disappears. Decreasing test from 0 to about -4.5 shows the "blue" face, then it switches to "red", which disappears at about -5.5.

Any thoughts?

--

And a related question - why does it look like a rectangle and not a square? I don't see where I introduce such a perspective in my code. Orthogonal should not make squares look like rectangles afaik.enter image description here

Upvotes: 1

Views: 106

Answers (1)

Cornelis de Mooij
Cornelis de Mooij

Reputation: 94

(full disclosure, I'm not an OpenGL expert, I have only played around with it a little bit)

1st question: your intuition is correct, objects behind the camera will not be visible. So with the default camera, objects located at z > 0 will not be visible.

2nd question: your interpretation of where the camera is located relative to the orthogonal viewing volume is incorrect. By defining the viewing volume, you effectively move the camera. The camera is at the back of the viewing volume, in this case, at z = 5.0.

By changing the value of test, you are moving the viewing volume along the z axis. When test < -4.5, you have moved the viewing volume beyond the red surface, so the blue surface becomes visible. When test < 5.5, you have moved the viewing volume beyond the blue surface as well, so both surfaces are no longer visible.

Related question: the rear side of your viewing volume, where the camera is located, is a square. But the window in which you are displaying what the camera is seeing is a rectangle, so it stretches the image from the camera. If you change the size of the viewing volume or the size of the window so that the width and the height match, then the surfaces will appear as perfect squares.

Upvotes: 0

Related Questions