我们把OpenGL里模型的三维坐标往二维坐标的转化称为投影,则屏幕上的二维坐标往三维坐标转化则可以称为反投影,下面我们来介绍一下反投影的方法。
主要是gluUnProject函数的使用,下面是代码:
注:(x, y )是屏幕坐标,(winX,,winY,winZ)是视景体坐标和深度坐标,(posx,posy,posz)是openGL坐标
网上有的文章说还要考虑模型的旋转、平移与缩放,即反投影的时候也要进行反旋转、反平移与反缩放,但是经过我的实验,这个是不用考虑的,因为反投影的时候导出的三个矩阵就包含旋转、平移与缩放的矩阵信息。
但是,glReadPixels((int)winx, (int)winy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winz); 经常会出现winZ值为1.0的情况。就像我所做的,功能是移动物体,如果winZ的值为1.0之后,物体就跑的没影了。
我们可以使用TRACE("point:%f, %f, %f \t", winX, winY, winZ);
TRACE("pos :%f, %f, %f \n", posX, posY, posZ);
跟踪一下,居然发现如下的输出:
point:633.000000, 301.000000, 0.963236
pos :0.318562, -9.291403, 0.769923
point:633.000000, 298.000000, 1.000000
pos :39.343056, -1186.848810, -9917.619793
注意这里:当winZ的值变成1.0的时候就出现错误了
经过多方查找资料,发现了一个重大的问题:
glRealPixels的定义是什么?
——The glReadPixels function reads a block of pixels from the framebuffer.
问题就出现在这里。如果framebuffer里面没有东西,当然就读取不出来了啊。所以就会出现上面的错误。
经验证,果不然,如果鼠标点在空白的位置 point:439.000000, 356.000000, 1.000000 pos :-2504.841247, -426.216424, -9799.354916
其实上述代码并不保险,只针对一种特殊情况才好使,即glViewport(0, 0, screenWidth, screenHeight),screenWidth、screenHeight分别是客户区的宽和高,视口左下角坐标恰好是(0,0),并且未经过任何模型变换。
从屏幕坐标向OpenGL坐标要经过两步,第一步是屏幕坐标向视景体坐标转换,第二步是视景体坐标向OpenGL坐标转换。上述代码中winX = (float)x; winY = viewport[3] - (float)y;反映第一步,gluUnProject是第二步。一般说来,gluUnProject的转换是不会出问题的。
更多OpenGL章,请参考该博客: http://blog.csdn.net/augusdi/article/details/38596253