OpenGL:gluUnProject的结果不是预期的结果

时间:2015-03-17 13:42:54

标签: c++ opengl

我正在绘制z = 0的纹理,如下图所示:

enter image description here

我的近平面和远平面设置为0.001和120.0。我可以使用键盘四处移动并放大和缩小。

我想要的是在使用gluunproject时识别鼠标光标位置的世界位置(例如图像中的红色)。

问题:结果posX,posY和posZ有些接近但不正确。例如。对于可见视图的中心(蓝色)我得到posX = 8.90000和posY = 53.80000。但是,如果我将鼠标向左移动,我会得到posX = 8.89894(应该是3.xx)。如果我将光标向右移动,我得到8.90103而不是大约。 14-16。

这是我的代码:

glMatrixMode (GL_PROJECTION);
glLoadIdentity();

perspectiveGL(65.0,(GLdouble)width()/(GLdouble)height(), 0.001, 120.0); 

glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Go to current World-Position
glTranslated(-m_posWorld.x(), -m_posWorld.y(), -m_posWorld.z());


// Try to project Screen(Mouse)-Coordinates to World Coordinates
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;

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

winX = (float)m_lastPos.x(); // m_lastPos is a Point storing the last Mouse Cursor Position within the OpenGL-Widget (without borders)
winY = (float)viewport[3]-(float)m_lastPos.y();
winZ = -m_posWorld.z();

GLdouble posX, posY, posZ;
int success = glhUnProjectf( winX, winY, -m_posWorld.z(), modelview, projection, viewport, &posX, &posY, &posZ);

这可能是什么问题?

1 个答案:

答案 0 :(得分:2)

“取消投影”某些内容,您需要窗口空间xy z

m_posWorld.z几乎肯定不在窗口空间。

窗口空间z是深度缓冲区存储的值,它是[ 0.0 1.0 ]之间的值(假设默认深度范围)。因为深度缓冲区为您提供了这个值,所以您可以通过在(winX, winY)处读取深度缓冲区来轻松找出它(尽管性能会受到影响)。

您可以将世界空间坐标转换为窗口空间:

vec4 posClip  = projectionMatrix * viewMatrix * m_posWorld; // Project to clip-space
vec4 posNDC   = posClip / posClip.w;                        // Perspective Divide
float winZ    = (posNDC * vec4 (0.5) + vec4 (0.5)).z;       // Adjust for Depth Range

上面讨论的方法会更快,但需要一些矩阵数学。您目前完全依赖OpenGL来为您进行矩阵数学运算,如果您想继续这样做,您唯一的选择就是读取深度缓冲区:

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