OpenGL坐标转换场景到世界

Posted

技术标签:

【中文标题】OpenGL坐标转换场景到世界【英文标题】:OpenGL Coordinate Transformation Sceen to World 【发布时间】:2013-06-28 19:45:24 【问题描述】:

我正在编写一个使用 OpenGL 的 MFC c++ 应用程序。该程序允许在 3D 中绘制和操作对象。现在我想找到坐标,在我绘制对象的同一坐标空间中,我在屏幕上单击鼠标的任何位置。

到目前为止,我一直在使用 glReadPixels 和 gluUnProject 的组合,它一直在工作,但只有当我在已经绘制对象的地方单击鼠标时。如果我单击对象外部的任何位置,则获得的坐标将完全关闭。

所以我想知道如何更改我的代码,以便我可以在我的对象在屏幕上的任何位置的坐标空间中找到坐标。这是我一直在使用的代码:

GLint viewport[4];
GLdouble ox, oy, oz;//the coordinates I need
GLfloat winZ = 0.0;
::glGetIntegerv(GL_VIEWPORT, viewport);
::glGetDoublev(GL_PROJECTION_MATRIX,    projectionMatrix);
::glGetDoublev(GL_MODELVIEW_MATRIX, modelviewMatrix);
GLfloat winX = (float)point.x;//point.x and point.y are the mouse coordinates
GLfloat winY = (float)viewport[3] - (float)point.y;

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

gluUnProject((GLdouble)winX, (GLdouble)winY, (GLdouble)winZ, modelviewMatrix, projectionMatrix, viewport, &ox, &oy, &oz);

【问题讨论】:

你的屏幕是 2D,你的世界是 3D。屏幕上的每个 2D 位置对应的不是一个 3D 点,而是一条射线/线/线段。只是出于好奇,如果winZ 为1,gluUnProject 会返回什么? 即使 winZ 为 1,它仍然每次返回 1。您能否详细说明每个 2D 点如何对应于一条射线/线/线段?大小和方向是什么? 【参考方案1】:

gluUnProject 获取窗口空间坐标并使用与世界视图投影视口变换相反的方式对它们进行反投影。它不知道坐标是否对应于现有对象。

当您清除深度缓冲区时,它会在各处初始化一个值,该值使用glReadPixels 读取为 1.0。

当绘制对象的可见片段时,它们将通过深度测试,并为与这些片段相交的每个像素使用较小的值覆盖深度值。

这意味着每次您在深度缓冲区中读取值为 1.0 的像素时,这意味着在该像素中没有绘制任何可见的内容,这就是您获得的结果完全关闭的地方。

【讨论】:

是的,你是绝对正确的,当我从没有可见片段的点读取时,winZ 确实总是返回 1.0。那么在那种情况下,用我目前的方法不可能实现我想要做的事情吗?如果是这样,我应该使用哪些其他功能?我想我需要的是一个屏幕到世界的转换?

以上是关于OpenGL坐标转换场景到世界的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:如何将世界坐标转换为屏幕坐标?

openGL 坐标系的互相转换

窗口调整大小后将鼠标位置转换为 2D openGL 中的世界坐标

OpenGL入门(四)-- OpenGL坐标系与坐标变换

我的OpenGL学习进阶之旅OpenGL的坐标系的学习笔记

我的OpenGL学习进阶之旅OpenGL的坐标系的学习笔记