通过读取Z Buffer深度值将屏幕2D坐标转化为场景3D坐标(含程序和源码)

时间:2022-06-06 04:18:37

如需转载请注明出处:http://blog.csdn.net/skyman_2001

主要有2种方法来实现屏幕2D坐标转化为场景3D坐标:一种是通过拣选射线,我的《APRG Demo》就是这样做的,有兴趣的可以查看源代码:http://blog.csdn.net/skyman_2001/archive/2005/10/06/495938.aspx;另一种是通过读取Z Buffer深度值。相比较而言后者要简单些。这里专门讲如何用后者来实现。

1. 使用双缓存,打开深度测试:

 glClearDepth(1.0f);         //  深度缓存设置
 glEnable(GL_DEPTH_TEST);       //  打开深度测试
 glDepthFunc(GL_LEQUAL);        //  设置深度测试类型

2. 绘制场景:

3. 在WM_MOUSE消息下:

   mouse_x=LOWORD(lParam);//鼠标的x坐标
   mouse_y=HIWORD(lParam);//鼠标的y坐标
   glGetDoublev(GL_MODELVIEW_MATRIX, modelview);//视图矩阵
   glGetDoublev(GL_PROJECTION_MATRIX, projection);//投影矩阵
   glGetIntegerv(GL_VIEWPORT, viewport);//视口
   winX=(float)mouse_x;//OGL中的窗口x坐标
   winY=(float)viewport[3]-(float)mouse_y;//OGL中的窗口y坐标
   glReadPixels(mouse_x,//x坐标
                     int(winY),//y坐标
                    1,1,//读取一个像素
                    GL_DEPTH_COMPONENT,//获得深度信息
                    GL_FLOAT,//数据类型为浮点型
                    &winZ);//获得的深度值保存在winZ中
   gluUnProject((GLdouble)winX,(GLdouble)winY,(GLdouble)winZ,modelview,projection,viewport,&object_x,&object_y,&object_z);
//获得OGL中的x,y,z坐标值

注:深度值winZ的范围为0.0~1.0,近截面处为0.0,远截面处为1.0,其他介于0.0和1.0之间。

下面我们来验证一下:

(由于抓图时没法抓鼠标,所以看不到鼠标位置,我只能用文字说明)

1.下图是鼠标点在黑色背景区域时的场景点坐标(见标题栏):

通过读取Z Buffer深度值将屏幕2D坐标转化为场景3D坐标(含程序和源码)

由图中可以看出:深度值winz=1.0,场景坐标ox=38.3,oy=12.9,oz=-100.0。

黑色背景区域是远截面,所以其深度值为1.0;而视见体我们是这样设置的:

gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

所以远截面上的点的z坐标为-100.0f。所以是正确的。

2.下图是鼠标点在球的中心处时的场景点坐标(见标题栏):

通过读取Z Buffer深度值将屏幕2D坐标转化为场景3D坐标(含程序和源码)

由图中可以看出,深度值winz=0.93,场景坐标ox=0.0,oy=0.0,oz=-1.5。

2个球是这么绘制的:

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 glLoadIdentity();  
 glPushMatrix();
   glTranslatef(0.0f,0.0f,-2.0f);
      auxSolidSphere(0.5f);
      glPushMatrix();
          glTranslatef(0.04f,0.04f,-0.04f);
          auxSolidSphere(0.5f);
      glPopMatrix();
 glPopMatrix();
 glFlush();

所以第一个球的正朝我们的面的中心点(就是我们这个鼠标点)的z坐标为-2.0+0.5=-1.5,吻合!

所以,这个程序是正确的!

程序和源代码下载(需glaux.dll ):

ReadDepth.rar