我画了一个四边形,把相机移到一个位置,然后点取四边形,根据点取的坐标,
我想获得它在世界坐标系的坐标,但是对返回的值有点疑惑。
代码如下:#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>int MOUSE_BUTTON = -1;
int MOUSE_POS_X = 0;
int MOUSE_POS_Y = 0;void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();             /* clear the matrix */
glColor3f (1.0, 1.0, 1.0);        glTranslatef(0.0f, 0.0f, -3.0f);
glPushMatrix();
{
glTranslatef(0.0f, 0.0f, -2.0f);
glBegin( GL_QUADS );
{
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glVertex3f( 0.0f, 1.0f, 0.0f );
}
glEnd();
}
glPopMatrix(); if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
{
GLint   viewport[ 4 ];
GLdouble projection[ 16 ];
GLdouble modelview[ 16 ];
GLfloat winX,winY,winZ;
GLdouble posX,posY,posZ; glGetIntegerv( GL_VIEWPORT, viewport );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); winX = (GLfloat)MOUSE_POS_X;
winY = (GLfloat)( viewport[3] - MOUSE_POS_Y );

glReadBuffer(GL_BACK);
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ ); printf( "screen = %f,%f,%f\n",  winX, winY, winZ );
printf( "world  = %f,%f,%f\n",  posX, posY, posZ ); MOUSE_BUTTON = -1;
}

glutSwapBuffers();
}void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_FLAT);
   glEnable( GL_DEPTH_TEST );
}
void mouse_func(int button, int state, int x, int y)
{
if ( state == GLUT_UP )
{
MOUSE_BUTTON = button;
MOUSE_POS_X = x;
MOUSE_POS_Y = y;
display();
}
}
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective( 45.0f, w/h, 0.1, 100.0 );
   glMatrixMode (GL_MODELVIEW);
}void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 400); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutMouseFunc(mouse_func);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;

 从上面看,我觉得四边形的z值应该是-5吧,
但是得到的是-2,第一个translate的z值无论怎么改,得到的值都是-2,
如果把glPushMatrix和glPopMatrix去掉,取得的永远是0
应该怎么理解呢?谢谢

解决方案 »

  1.   

    glTranslatef(0.0f, 0.0f, -3.0f);根本没有被应用.
    你把glTranslatef(0.0f, 0.0f, -3.0f);放到glPushMatrix();里面试试
      

  2.   

    你怎么得到的值,我改变了glTranslatef(0.0f, 0.0f, -10.0f);的值,图形会向里面移动,你试试看
      

  3.   

    得到什么的效果我知道,我想搞清楚gluUnProject的实现原理,
    看过它的源码,看不懂,
      

  4.   

    上面的代码太长了,看着费劲,我重发一下,void display(void)
    {
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity ();  glColor3f (1.0, 1.0, 1.0);
    glPointSize(3.0f);        //第一次位移,得到矩阵M1
            glTranslatef(0.0f, 0.0f, -5.0f);        //绘制一个点
    glPushMatrix();
    {
    glTranslatef(1.0f, 2.0f, -2.0f);//第二次位移,得到矩阵M2 glBegin( GL_POINTS );
    glVertex3f( 0.0f, 0.0f, 0.0f );
    glEnd();
    }
    glPopMatrix();        //鼠标单击上面绘制的点,由屏幕坐标转化为世界坐标,有一下几点疑惑:
            //1. 无论我怎么改第一个glTranslate的z值,这个地方取得的世界坐标都是(0.0, 0.0, -2.0),
            //2. 如果去掉glPushmatirx和glpopmatrix,得到的结果是(0.0, 0.0, 0.0)
            //3. 为什么gluUnProject要用M1才能得到正确的结果?而且M1任意改变都不会影响结果
            //请给我讲讲这里面的原理,谢谢 if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
    {
    double posX,posY,posZ;
    screen2world( MOUSE_POS_X, MOUSE_POS_Y, &posX, &posY, &posZ );
    MOUSE_BUTTON = -1;
    }

    glutSwapBuffers();
    }
    void screen2world( int x, int y, double * posX, double * posY, double * posZ )
    {
    GLint   viewport[ 4 ];
    GLdouble projection[ 16 ];
    GLdouble modelview[ 16 ];
    GLfloat winX,winY,winZ;

    glGetIntegerv( GL_VIEWPORT, viewport );
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );

    winX = (GLfloat)x;
    winY = (GLfloat)( viewport[3] - y );

    glReadBuffer(GL_BACK);
    glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

    gluUnProject( winX, winY, winZ, modelview, projection, viewport, posX, posY, posZ );

    printf( "screen = %f,%f,%f\n",  winX, winY, winZ );
    printf( "world  = %f,%f,%f\n",  *posX, *posY, *posZ );}
      

  5.   

    很显然,glTranslate操作是针对栈顶的矩阵进行操作的,你的第一次操作是在矩阵进栈之前,这个时候栈为空所以根本就没有任何操作,第二次glTranslate操作正确所以怎么改只有第二次操作生效.如果去掉glPushmatirx和glpopmatrix由于栈是空的,所以glTranslate得任何操作都不会成功,所以最终获得的结果就是顶点的初始化值
      

  6.   


    GLint GLAPIENTRY
    gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
    const GLdouble modelMatrix[16], 
    const GLdouble projMatrix[16],
                    const GLint viewport[4],
            GLdouble *objx, GLdouble *objy, GLdouble *objz)
    {
        double finalMatrix[16]; //最终矩阵
        double in[4];
        double out[4];    __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);  //finalMatrix = 世界变换*相机变换*投影变换
        if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 逆矩阵(从投影坐标到世界坐标)    in[0]=winx;//客户区窗口坐标x
        in[1]=winy;//客户区窗口坐标y
        in[2]=winz;//坐标z(深度)
        in[3]=1.0; //w分量
        //viewport[0] = 窗口左端坐标(在以ScreenCoordinate作坐标系的时候有用)viewport[2] = width viewport[3] = height
        /* Map x and y from window coordinates */
        in[0] = (in[0] - viewport[0]) / viewport[2]; // x([-1,+1]) = 2 *(screenPosX - screenLeft) / screenWidth - 1
        in[1] = (in[1] - viewport[1]) / viewport[3]; // x([-1,+1]) = 2 *(screenPosY - screenTop) / screenHeight - 1
        /* Map to range -1 to 1 */
        in[0] = in[0] * 2 - 1; 
        in[1] = in[1] * 2 - 1;
        in[2] = in[2] * 2 - 1;    __gluMultMatrixVecd(finalMatrix, in, out); //将已经转化到标准设备空间的坐标*逆矩阵 = 世界空间坐标
        if (out[3] == 0.0) return(GL_FALSE);
        out[0] /= out[3];  out[3]为w分量,除w分量投影到三维空间
        out[1] /= out[3];
        out[2] /= out[3];
        *objx = out[0]; //[objx,objy,objz]  =[x,y,z]
        *objy = out[1];
        *objz = out[2];
        return(GL_TRUE);
    }
      

  7.   

    经过两次translate,感觉上点的相对于世界坐标系的坐标应该是(0.0, 0.0,-7.0),但是取得的值是(0.0, 0.0, -2.0)
      

  8.   


    任何时刻都有个当前矩阵,pushmatrix是把当前矩阵压入栈,popmatrix把栈顶弹出替换当前矩阵,
    变换函数gltranslate是把当前矩阵M * trans_V,它不会去操作栈。
      

  9.   

    谁说任何时候都有当前矩阵?
    MSDN: glPopMatrixError Codes
    It is an error to push a full matrix stack, or to pop a matrix stack that contains only a single matrix. In either case, the error flag is set and no other change is made to the OpenGL state.The following are the error codes generated and their conditions.Error code Condition 
    GL_STACK_OVERFLOW  glPushMatrix was called while the current matrix stack was full. 
    GL_STACK_UNDERFLOW  glPopMatrix was called while the current matrix stack contained only a single matrix. 
    GL_INVALID_OPERATION  glPushMatrix was called between a call to glBegin and the corresponding call to glEnd. 
    弹出栈的时候有下溢错误
      

  10.   

    我说的当前矩阵不是在栈里,栈里只有push才会有,我的意思是虽然栈空,但可以
    用glGetDoublef( GL_MODELVIEW_MATRIX, modelview )取得当前矩阵。glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity (); glTranslatef(0.0f, 0.0f, -5.0f); 
    //得到矩阵1如下:
    1.0, 0.0,  0.0,  0.0
    0.0, 1.0,  0.0,  0.0
    0.0, 0.0,  1.0,  0.0
    0.0, 0.0, -5.0, 1.0//绘制一个点 
    //glPushMatrix(); 

           glTranslatef(0.0f, 0.0f, -2.0f);
    //得到矩阵2如下:
    1.0, 0.0,  0.0,  0.0
    0.0, 1.0,  0.0,  0.0
    0.0, 0.0,  1.0,  0.0
    0.0, 0.0, -7.0, 1.0       glBegin( GL_POINTS ); 
           glVertex3f( 0.0f, 0.0f, 0.0f ); 
           glEnd(); 

    //glPopMatrix(); //鼠标单击上面绘制的点,由屏幕坐标转化为世界坐标 
    //屏蔽push和pop后,这里取得的modelview_matrix是矩阵2,
    //但是unproject的z值一直是0.0
    if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON ) 

    double posX,posY,posZ; 
    screen2world( MOUSE_POS_X, MOUSE_POS_Y, &posX, &posY, &posZ ); 
    MOUSE_BUTTON = -1; 
      

  11.   

    http://blog.csdn.net/gisfarmer/archive/2009/02/20/3911506.aspx