Sign in to follow this  
Amablue

Drawing a 3D world and 2D HUD

Recommended Posts

I can't seem to get this to work right. I want to be able to draw my terrain followed by a flat HUD. I can get one or the other to draw, but I can't get the 2D stuff to draw on top of the 3D stuff. Here's basically what I've got:
drawStuff()
{
    glClearColor(clearColor[0], clearColor[1], clearColor[2], 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawWorld(); // Just draws some random terrain
    drawHUD(); // Just draws a black square for now

    SDL_GL_SwapBuffers();
}

// Draw some hills
drawWorld()
{
    // This section may be wrong. I don't totally understand what's going on.
    // It was copied and pasted from a project I did last semester, and I 
    // just sort of fumbled around until I got it to work. 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45, windowManager->getAspectRatio(), camera->getClipNear(), camera->getClipFar());
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // Should I have to call this twice? if I take it out nothing gets drawn
    gluLookAt(camera->x, camera->y, camera->z, 0, 50, 0, 0, 1, 0);

    // draw some hills
    glColor3f(.2f, .8f, .3f); 
    glBegin(GL_TRIANGLES);
    for (int i=0; i<MAP_SIZE; ++i)
    {
        for (int j=0; j<MAP_SIZE; ++j)
        {
            // draw a bunch of triangles
        }
    }
    glEnd();
}

// Draw a black square centered on the screen
drawHUD()
{
    // This too was copied from a project from a few semesters ago. 
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    gluOrtho2D(-400, 400, -300, 300);
    glTranslatef(-camera->x, -camera->y, 0);

    // Draw a black square
    glColor3f(0, 0, 0);
    glBegin(GL_QUADS);
        glVertex3f(-20, -20, 0);
        glVertex3f(20, -20, 0);
        glVertex3f(20, 20, 0);
        glVertex3f(-20, 20, 0);
    glEnd();
}


I'm betting it's a problem having to do with setting up the translation matrix. Or more precisely, switching between them. I don't fully understand how that math works, or why it won't work when I reset the identity matrix and attempt to continue drawing. (also, if it matters, this is being used from within an SDL program)

Share this post


Link to post
Share on other sites
drawWorld is setting up the projection and view matrices, but drawHUD is only setting up the view matrix.

Interestingly, it's putting an ortho projection into the view matrix, which means your HUD is using the world's 3D perspective projection matrix *and* it's also using a 2D ortho projection matrix at the same time.

Try replacing the first 4 lines of drawHUD with something like this instead:
    glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-400, 400, -300, 300);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-camera->x, -camera->y, 0);

[EDIT]
As for "Should I have to call this twice? if I take it out nothing gets drawn":
glMatrixMode selects the currently active matrix. There are two - GL_PROJECTION is used to transform 3D points into a particular 2D view, and GL_MODELVIEW is used to move 3D points around within the world.

When you call glLoadIdentity, glTranslatef, gluOrtho2D, gluPerspective, etc, they modify the currently active matrix. So that means that in drawWorld, the first call to glLoadIdentity is loading an identity-matrix into GL_PROJECTION, and the second call is doing it for GL_MODELVIEW.
I hope that makes this code make more sense ;)

Share this post


Link to post
Share on other sites
Thanks, that works exactly how I want it to.

It sounds like I misunderstand how this all works a bit. I thought that there was one matrix that verticies were multiplied against to get the location they should show up on the screen, and when you call things like glTranslate and glScale you are altering that matrix. However, you mention two, the view matrix and the projection matrix. I think there's a gap in my understanding here.

EDIT: Awesome, my question was preemptively answered.

Share this post


Link to post
Share on other sites
you should also try using GL matrix stacks with glPushMatrix() and glPopMatrix() pairs. In the case, you dont use glLoadIdentity() before calling a view transform, in each redrawing of your window, the view matrices will get concatenated and this does not give the correct view transform that you're trying to achieve. I hope this helps.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this