如需转载请注明出处: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.下图是鼠标点在黑色背景区域时的场景点坐标(见标题栏):
由图中可以看出:深度值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.下图是鼠标点在球的中心处时的场景点坐标(见标题栏):
由图中可以看出,深度值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 ):