屏幕坐标到2D世界 [英] Screen Coordinates to 2D World

查看:74
本文介绍了屏幕坐标到2D世界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这更像是数学性质,但无论如何.我需要能够检测到我在OpenGl中以四边形显示的图像中单击的位置.四边形的尺寸为5000x5000,并以0,0渲染.现在,从我所看到的开始,这是从窗口中间渲染的.这将在轴的左下角渲染四边形.为了解决这个问题,而不是更改四边形的顶点,并且由于我也需要平移,所以在绘制四边形之前先进行变换.

This more of a mathy nature but anyway. I need to be able to detect where I click in an image displayed in a quad in OpenGl. The quad is 5000x5000 in size and is rendered at 0,0. Now from what I have seen this is rendered from the middle of the window. This renders the quad in the bottom left corner of the axis's. To counter this, rather than change the vertex's of the quad, and since I need to pan as well I transform before I draw the quad.

因此,要使四边形在启动时居中,我可以通过GL.Translate(-2500,-2500),0)进行平移.

So to make the quad centered at startup, I pan by GL.Translate(-2500, -2500), 0).

现在,鼠标坐标是相对于窗口的左上角的,所以我将它们分成一个小部分,例如Mouse.X/宽度Mouse.Y/高度

Now the mouse coordinates are relative to the top left corner of the window, so I break them into a fraction e.g. Mouse.X / Width Mouse.Y / Height

这就是它引起怀疑的地方.我知道我需要乘以5000,但是我还需要以某种方式合并平底锅.

This is where it gets iffy. I know I need to multiply by 5000 but I also need to incorporate the pan somehow.

我不确定这是否重要,但这是我的正交矩阵的设置方式:

Im not sure if this is important but this is how my Ortho matrix is setup:

GL.Ortho(-G_.MapSize * 1.5 ^ ZoomFactor, G_.MapSize * 1.5 ^ ZoomFactor, G_.MapSize * 1.5 ^ ZoomFactor, -G_.MapSize * 1.5 ^ ZoomFactor, -1, 1)

推荐答案

GL具有清晰的对象空间,剪辑空间,规范化的设备坐标和窗口空间. glOrtho()glTranslate()的用法表示您使用的是旧的固定函数,在该函数中,眼睛空间也得到了很好的定义.

The GL has clear conecpets of object space, clip space, normalized device coords and window space. Your usage of glOrtho() and glTranslate() implies that you use the old fixed function, where also the eye-space is well-defined.

要将窗口的顶点点(如鼠标坐标)映射回对象空间时,需要反转gl所做的计算.顶点的转换管道如下:

When you want to map window sapce points (like mouse coords) back into object space, you need to invert the calculations the gl does. The transformation pipeline for vertices is the following:

  1. 将模型视图矩阵MV与对象空间顶点位置相乘以获得眼空间坐标(仅在固定功能GL中,在可编程管线中,此步骤完全由用户定义)
  2. 将投影矩阵P与眼部空间位置相乘以获得剪辑空间位置(仅在固定功能GL中,在可编程管线中,此步骤完全由用户定义)
  3. 通过片段空间w分量除以得到笛卡尔标准化设备坐标.在此空间中,查看体积是沿每个轴在[-1,1]范围内的轴对齐立方体. z = -1代表近平面,z = 1代表远平面
  4. 通过将视口放入accout将NDC转换为窗口空间.点(-1,1)映射到视口的左下角像素(左下角),(1,1)映射到右上角像素(右上角)视口. Z从[-1,1]转换为[0,1],并且可能由指定的glDepthRange进一步转换,后来又可能转换为某种整数表示形式.
  1. multiply modelview matrix MV by object space vertex position to get eye space coords (only in fixed-function GL, in the programmable pipeline, this step is completely user-defined)
  2. multiply projection matrix P by eye space position to get clip-space position (only in fixed-function GL, in the programmable pipeline, this step is completely user-defined)
  3. divide by by clip space w component to get cartesian normalized device coords. In this space, the viewing volume is an axis-aligne cube in the range [-1,1] along each axis. whit z=-1 reprensenting the near plane and z=1 the far plane
  4. transform the NDCs to window space by taking the viewport into accout. the point (-1,1) is to be mapped to the (bottom left corner of the) bottom-left pixel of the viewport, (1,1) is mapped to the (top-right corner of the) top-right pixel of the viewport. Z is transformed from [-1,1] to [0,1] and might be further transfrom by the specified glDepthRange, and later might by converted to some integer representation.

如果您具有给定的2D鼠标位置,则可以简单地反转该方案:

If you have a given 2D mouse position, you can simply invert that scheme:

  1. 查找视口坐标(如果使用全窗口,这是微不足道的,请注意,GL使用原点在左下角,而大多数窗口系统将原点放在左上角).
  2. 撤消视口变换,以将x和y置于[-1,-1]的范围内.
  3. 现在,您可以通过assuimg w = 1直接将它们用作剪辑空间坐标.通常,每个2d鼠标位置代表一条光线,因此您可以使用两个点将光线投射回去,例如z = -1和z = 1.但是,在正交投影的情况下,一个点就足够了.因此,将逆投影P ^ -1乘以您的点的剪辑空间坐标.
  4. 您现在有了眼部空间位置.将模型模型逆矩阵MV ^ -1乘以眼睛空间坐标以返回到对象空间(一般情况下,您应该意识到必须将最终结果除以w分量,因为您处于投影状态使用正交投影,并且只有在ModelView中进行仿射变换,w将为1,因此您可以忽略它).
  1. Find the viewport coords (which is trivial if you use the full window, just be aware that GL uses the origin at bottom-left, while most window systems put the origin at top-left corner).
  2. Undo the viewport transform to put x and y in the range of [-1,-1].
  3. Now you can directly use these as clip space coords by assuimg w=1. In the general case, each 2d mouse position represents a ray, so you can use two points to project the ray back, like z=-1 and z=1. However, in your orthogonal projection case, one point is enough. So multiply the inverse Projection P^-1 by the clip space coords of your point(s).
  4. You now have the eye space position. Multiply the inverse modelview matrix MV^-1 by the eye space coords to get back to object space.(In the general case, you should be aware that you have to divide the final result by the w component, since you were in a projective space. With orthogonal projection, and only affine transformations in ModelView, w will be 1 so you can ignore it).

编辑

由于该操作很常见,因此也有一些实用程序功能可以实现此功能.当您使用GL的矩阵堆栈时,最简单的解决方案就是使用 gluUnproject() (来自GLu库).您所需要的只是该点的3D窗口坐标,以及绘制对象时在其中使用的矩阵和视口设置,可以使用glGetDoublev()使用各种glGet函数查询该设置.在旧的NeHe网站上有一个完整示例.

Since that operation is common, there are also some utility functions implementing this. As you are using the matrix stack of the GL, the easiest solution is just to use gluUnproject() from the GLu library. All you need are the 3D window coords of the point, and the matrices adn viewport setting which where used when you did draw the object, which can be queried using glGetDoublev() using the various glGet functions. There is a full example at the old NeHe site.

使用现代GL,您必须自己完成所有这一切.但是,流行的GLM库还具有 glm::unProject 方法GLU之一.

With modern GL, you have to do this all by yourself. However, the popular GLM library also has a glm::unProject method similiar to the GLU one.

这篇关于屏幕坐标到2D世界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆