我在使用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周围有什么旋转,它都能正常工作。
例如,在这里我创建了一个小方形平面,两个点的高度相同(一个被标签遮挡):
世界坐标P1:(0.019062456,0.03357359,0.08333321,1)
世界坐标P2:(0.025983132,0.028048635,0.08333321,1)
但如果我在整个X轴上旋转整个场景,则检索到的Z坐标会改变:
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]中。
我哪里错了?
答案 0 :(得分:1)
您是否希望看到飞机上点的确切坐标?你不会这样做。
渲染正方形时,坐标转换为3D,并对图元进行光栅化(即转换为2D和插值),生成屏幕X,Y和(通常)24位深度值。这是相当精确的损失(并且它甚至不是线性的),所以如果你读它并反转变换,你只能获得原始值的近似值。
如果您的多边形恰好垂直于视图方向,则插值将至少在整个曲面上给出一致的z值(因为所有变换的Z值都相同),尽管它不一定是< em>正确 z值。因此,深度的任何变化都会导致误差发生变化,如果您的平面不垂直,它甚至会在多边形上保持一致。
深度基本上足以在没有太多错误的情况下进行绘制(即便如此,并非总是如此),但不能用于重建精确几何体。
如果想要更好的结果,可以使用着色器将实际模型空间X,Y,Z光栅化为(浮点)FBO,并将其读回。或者,在光线中将光线与几何体相交。