通過讀取Z Buffer深度值將屏幕2D坐標轉化為場景3D坐標(含程序和源碼)
主要有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 ):
工程師必備
- 項目客服
- 培訓客服
- 平臺客服
TOP




















