2013-01-09 41 views
1

我得到gluUnProject一些麻煩,因爲我檢索一個不準確的Z座標。gluUnProject在某些條件下返回不準確的z座標

涉及的程序本質上是一個3d查看器。我實現了一個小功能,允許用戶點擊加載模型並檢索兩點之間的距離。

這是代碼:

// Declare variables for viewport, modelview and projection matrix 
int viewport[] = new int[4]; 
float modelview[] = new float[16]; 
float projection[] = new float[16]; 
// GL y-coordinate position 
int realY; 
// Returned [wx, wy, wz, 1] coordinates 
float worldCoordinates[] = new float[4]; 

gl2.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0); 
gl2.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, modelview, 0); 
gl2.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projection, 0); 

// Retrive the Y coordinate, note viewport[3] is height of window in pixels 
realY = viewport[3] - click.y - 1; 

// Allocate a buffer to store the result 
FloatBuffer fb = FloatBuffer.allocate(1); 

// Retrieve the Z coordinate, read a block of pixels from the frame buffer 
gl2.glReadPixels(click.x, realY, 1, 1, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, fb); 

System.out.println("Depth: "+fb.get(0)); 

// Avoid centering if the click is on nothing 
if (fb.get(0) == 1.0f) { 
    return null; 
} 
// Map window coordinates to object coordinates, retrieve the world coordinates 
glu.gluUnProject(click.x, realY, fb.get(0), modelview, 0, projection, 0, 
      viewport, 0, worldCoordinates, 0); 

當我躺在測量表面上兩點之間的距離垂直於用戶的一切工作正常。如果我們拍攝一個3軸系統,z指向用戶,y指向頂部,兩個點位於XY平面上。它的工作原理,無論什麼周圍Z.旋轉

enter image description here

例如,在這裏,我創建了一個小正方形平面且兩分具有相同的高度(一個由標籤遮擋):

世界座標P1:(0.019062456,0.03357359,0.08333321,1)

世界座標P2:(0.025983132,0.028048635,0.08333321,1)

但是,如果我在全局X軸旋轉整個場景,然後將R etrieved Z軸座標,變化:

enter image description here

X和Y座標並不重要,重要的是Z之一。它不多0.08333321。

世界座標P1:(0.026863147,0.027185505,0.0831252,1)

世界座標P2:(0.020072304,0.034560144,0.08312501,1)

而且之後在全球X旋轉也變焦影響點的Z座標。

Ps:我正在使用JOGL。放大和縮小是通過放大/縮小glOrtho平行六面體來完成的。由glReadPixels生成的Z深度fb.get(0)包含在[0,1]中。

我在哪裏錯了?

回答

1

您是否期望看到您飛機上該點的確切座標?你不會這樣做。

當您渲染正方形時,座標轉換爲3D,並將原始圖像(即轉換爲2D並插值),生成屏幕X,Y和(通常)24位深度值。這是相當的精度損失(甚至不是線性的),所以如果你閱讀它並反轉變換,你只能得到原始值的近似值。

如果您的多邊形恰好與視圖方向垂直,則插值將至少在整個曲面上給出一致的z值(因爲所有變換後的Z值都是相同的),但它不一定是right z值。因此,深度的任何變化都會導致誤差發生變化,如果您的飛機不是垂直的,它甚至會停止在多邊形上保持一致。

深度對於繪製沒有太多錯誤(甚至是並非總是)基本上足夠好,但不適用於重建準確的幾何圖形。

如果你想得到更好的結果,你可以將實際的模型空間X,Y,Z用着色器柵格化爲(float)FBO,然後讀回。或者,用軟件將光線與幾何圖形相交。

+0

感謝JasonD的回答,它證實了我的主要擔心:近似/插值錯誤。然而,只是一個浮動的FBO足以改善這種情況?我該如何檢查我目前使用的是哪一個? – elect

+0

如果你還沒有明確地創建一個FBO,你只需要渲染到窗口。所以可能只是一個8位的每通道緩衝區。無論如何,我建議一個額外的緩衝區,它可以將您需要的信息直接存儲在更合適的格式和空間中。是否值得做(或者是否足夠)取決於您的確切要求。 – JasonD

+0

不,我使用opengl的默認FBO ..所以你建議我創建一個具有特定格式(浮點數)的附加FBO。我現在正在Google上搜索,但我無法找到對我的目的有用/具體的東西,你有沒有關於此的任何好鏈接? (浮動FBO的創建) – elect