gluUnProject在某些条件下返回不准确的z坐标

时间:2013-01-09 12:54:21

标签: opengl rotation coordinate-systems depth glu

我在使用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轴上旋转整个场景,则检索到的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 个答案:

答案 0 :(得分:1)

您是否希望看到飞机上点的确切坐标?你不会这样做。

渲染正方形时,坐标转换为3D,并对图元进行光栅化(即转换为2D和插值),生成屏幕X,Y和(通常)24位深度值。这是相当精确的损失(并且它甚至不是线性的),所以如果你读它并反转变换,你只能获得原始值的近似值。

如果您的多边形恰好垂直于视图方向,则插值将至少在整个曲面上给出一致的z值(因为所有变换的Z值都相同),尽管它不一定是< em>正确 z值。因此,深度的任何变化都会导致误差发生变化,如果您的平面不垂直,它甚至会在多边形上保持一致。

深度基本上足以在没有太多错误的情况下进行绘制(即便如此,并非总是如此),但不能用于重建精确几何体。

如果想要更好的结果,可以使用着色器将实际模型空间X,Y,Z光栅化为(浮点)FBO,并将其读回。或者,在光线中将光线与几何体相交。

相关问题