Question

I've been able to use modelview matrix and functions like glTranslatef() and gluLookAt() to transform an object or the perspective of the entire scene, but when I try to do both I run into problems.

It seems that regardless of the parameters I use for gluLookAt(), the objects I draw are displayed from the same angle. I've tried calling functions in different others different uses of glPushMatrix() and glPopMatrix based on what I've read in other threads with no luck. Here is what I have now. The objects move they are supposed to, but I can only get them to appear from one viewpoint.

For instance, since they should be moving in the xy plane, and are circling counterclockwise, I would think that changing z_0 to -30 would make them appear to be moving clockwise, but it doesn't seem to make any difference. There is a long list of constants preceding it that I'm leaving out. The eventual goal is to make a simple model of our solar system.

    GLfloat time = 0.0;
GLfloat inc = 0.01;

// viewing parameters
GLint winWidth = 600, winHeight = 600;
GLfloat x_0 = 0.0, y_0 = 0.0, z_0 = 30.0;
GLfloat xref = 0.0, yref = 0.0, zref = 0.0;
GLfloat Vx = 0.0, Vy= 1.0, Vz = 0.0;
GLfloat xwMin = -50.0, ywMin = -50.0, xwMax = 50.0, ywMax = 50.0;
GLfloat dnear = .3, dfar = 10.0;

void view(void) {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(xwMin, xwMax, ywMin, ywMax, dnear, dfar);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(x_0, y_0, z_0, xref, yref, zref, Vx, Vy, Vz);
}

void init(void) {
    view();
    glEnable(GL_DEPTH_TEST);
}

void drawPlanet(GLfloat maj, GLfloat min, GLfloat x0, GLfloat theta,
        GLfloat size) {
    GLfloat x = maj * cosf(theta) + x0;
    GLfloat y = min * sinf(theta);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glTranslatef(x, y, 0);
    glutSolidSphere(size, 25, 25);
    glPopMatrix();
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1.0, 1.0, 1.0);

    drawPlanet(MERCURY_MAJOR, MERCURY_MINOR, MERCURY_CENTER,
        time / MERCURY_YEAR, MERCURY_SIZE);

    drawPlanet(MARS_MAJOR, MARS_MINOR, MARS_CENTER,
        time / MARS_YEAR, MARS_SIZE);

    drawPlanet(URANUS_MAJOR, URANUS_MINOR, URANUS_CENTER,
        time / URANUS_YEAR, URANUS_SIZE);

    glFlush();
}

void idle(void) {
    time += inc;
    display();
    glutSwapBuffers();
}

int main (int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(0,0);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("");

    init();

    glutDisplayFunc(display);
    glutIdleFunc(idle);

    glutMainLoop();
}

If anyone sees what I'm missing I'd really appreaciate an explanation or direction to some additional reading that will help me fix the problem.

Was it helpful?

Solution

You make the typical OpenGL newbie mistake and scatter your matrix manipulations all around the place. You never initialize OpenGL matrix state. Always set it up fresh when entering the display function. This makes things much easier to spot.

Also you may mistake OpenGL for a scene graph with glPush/PopMatrix "magically" establishing a transformation hierachy.

glPushMatrix – as you probably know – makes a copy of the current top of the stack matrix and pushes it on the stack. The idea is to make temporary copies which further transformations can be multiplied onto.

Now let's look at your code in slightly different form:

void display(void) {
    glViewport(…);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(xwMin, xwMax, ywMin, ywMax, dnear, dfar);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(x_0, y_0, z_0, xref, yref, zref, Vx, Vy, Vz);

    glColor3f(1.0, 1.0, 1.0);

    {
        GLfloat x = maj * cosf(theta) + x0;
        GLfloat y = min * sinf(theta);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity(); // <<<<<<<<<

        glTranslatef(x, y, 0);
        glutSolidSphere(size, 25, 25);
        glPopMatrix();
    }

You see what's happening here? You're resetting your modelview matrix to identity, then translate that. The look-at matrix you create previously is completely discarded, and has no effect on the sphere drawing.

Remove that glLoadIdentity() I marked and things should work just fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top