1

我在使用 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] 中。

我哪里错了?

4

1 回答 1

1

您是否希望在您的平面上看到该点的确切坐标?你不会以这种方式得到它。

当您渲染您的正方形时,坐标被转换为 3D,并且原始栅格化(即转换为 2D 和插值),生成屏幕 X、Y 和(通常)24 位深度值。这是相当大的精度损失(甚至不是线性的),所以如果你阅读它并反转变换,你只会得到原始值的近似值。

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

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

如果您想要更好的结果,您可以将实际模型空间 X、Y、Z 光栅化为带有着色器的(浮动)FBO,然后将其读回。或者,在软件中将射线与您的几何体相交。

于 2013-01-09T13:53:08.687 回答