JuanGM
JuanGM

Reputation: 23

Getting ModelView and Projection matrices in Opengl 2.x [C++]

I know that StackOverflow is full of similar questions (Like this one or that one) but the solutions given don't seem to work for me. My goal is to use gluProject to get the screen coordinates of some point from the 3D-space. Before that, I'm expected to get the matrices by doing the following:

GLint view[4]={0};
GLdouble proj[16]={0};
GLdouble model[16]={0};

glGetDoublev(GL_PROJECTION_MATRIX,proj);
glGetDoublev(GL_MODELVIEW_MATRIX,model);
glGetIntegerv(GL_VIEWPORT,view);

Knowing these three allows to compute the screen coordinates of the point. However, when I call these functions I get weird results:

VIEWPORT
       0                0                1366               768

PROJECTION
-536 870 912     1 073 460 858           0                  0
      0                0           -536 870 912       1 073 460 858
      0                0                 0                  0
      0                0                 0                  0

MODELVIEW
    1 073 741 824     1 073 741 824       -1 073 741 824         1 071 119 123
          0                0               1 073 741 824         1 072 511 075
   -1 073 741 824     1 072 523 682              0              -1 077 637 615
   -2 147 483 648    -1 069 923 613              0              -1 071 413 844

The matrices are generated using gluPerspective and gluLookAt. The Viewport is obviously correct but the matrices are wrong, not only because of their values which don't seem very normal to me but because of the value's distribution across the elements of the matrices (see that the [1,2] element of the Projection matrix should be zero but it isn't, while the [3,3] element is zero, and it shouldn't).

These strange values point to some problem in the call of the glGet() functions, but I can't figure it out. I have checked that I'm not calling glGet() between glBegin() and glEnd(). Actually, I call glGet() just after correctly drawing some points and just before correctly drawing some spheres by using the same ModelView and Projection matrices. There's the a bigger snippet of my code (the calling sequence is main->CheckForPlanetPosition->Planet::GetScreenLocation):

typedef struct position {
  int x,y,z;
};

int main()
{
    glEnable(GL_DEPTH_TEST);
    glViewport(0,0,1366,768);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,16.0f/9.0f,1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(Camera.x,Camera.y,Camera.z,Camera.cx,Camera.cy,Camera.cz,0,1,0);

    //calls to glEnable

    //some drawing
    glBegin(GL_LINES);
    for(float i=1;i<15;i++)
    {
        glColor4f(0,120.0f/255.0f,210.0f/255.0f,1.0f);

        glVertex3f(0,0.5f,i*100.0f/15.0f);
        glVertex3f(100,0.5f,i*100.0f/15.0f);
        glVertex3f(i*100.0f/15.0f,0.5f,0);
        glVertex3f(i*100.0f/15.0f,0,100);
    }
    glEnd();

    CheckForPlanetsLocation();
    //other stuff...
   return 0;
  }

bool CheckForPlanetsLocation()
{
    position pos;
    pos=SomePlanet.GetScreenLocation();
    //check that the mouse is over the returned region...
}

position Planet::GetScreenLocation()
{
        GLint view[4]={0};
        GLdouble proj[16]={0};
        GLdouble model[16]={0};
        GLdouble x,y,z;

        glGetDoublev(GL_PROJECTION_MATRIX,proj);
        glGetDoublev(GL_MODELVIEW_MATRIX,model);
        glGetIntegerv(GL_VIEWPORT,view);

        gluProject(pos.x,pos.y,pos.z,model,proj,view,&x,&y,&z);
        position res;

        res.x=(int)x;
        res.y=(int)y;
        res.z=(int)z;
        return res;
}

Hope you can help me this time! Thanks in advance for your answers :)

Upvotes: 0

Views: 1458

Answers (1)

Tasos Stamadianos
Tasos Stamadianos

Reputation: 124

The problem is that gluProject expects an array of type double while you're passing it a float. When it goes to iterate, it'll iterate using the size of a double, which is twice the size of a float! Therefore, it'll skip over some elements and give you garbage for others. Swap out those float arrays with double and use glGetDoublev to get the values you want.

Also, your gluPerspective code has a small error in it -- the 16/9 will integer truncate to 1 before it's passed into the function. It's not the cause of your projection problems, but it's good to remember that integer truncation is a thing that will screw up your floating point calculations.

Finally, I'm gonna be that guy and say in this day and age learning OldenGL(as I call it) does more harm than good. There are plenty of great online tutorials for modern OpenGL, such as these:

Open.GL

LearnOpenGL

Anything that mentions OpenGL 2 and above is what you want.

Upvotes: 2

Related Questions