我有 2 个问题。一个是关于为什么我的代码没有按预期工作的具体问题,另一个是设计问题。
1(具体问题):我正在尝试将屏幕坐标映射到基于 2D 瓦片的引擎中的世界坐标(使用 x/y 轴,z = 0)。我已经使用了 Nehe 的教程端口来了解如何实现这一点,但我得到的结果并不像预期的那样。
我有一个名为 MouseController 的类。每当触发鼠标事件时(通过 swing 的 MouseListener),我将 MouseEvent 传递给我的 MouseController。
在我的 GLCanvas 的绘制函数中,我调用 MouseController.processClick(GL) 函数以便能够将当前 gl 上下文传递到 processClick 函数并获取模型视图、投影矩阵和视口。
当我单击屏幕上呈现的块时,返回给我的世界坐标几乎没有意义。一方面,我希望 z 值是 0,但它是 9(这是我的相机设置的高度),我的 x 和 y 值总是非常接近 0(偶尔会跳到 1-9 非常轻微的移动,然后回到一个非常接近于 0 的数字)。
任何人都知道为什么会这样?processClick 函数如下:
public void processClick(GL gl) {
int x = e.getX();
int y = e.getY();
if(e.getButton() == MouseEvent.BUTTON1) {
gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort, 0);
gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mvMatrix, 0);
gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, prMatrix, 0);
int realy = viewPort[3] - y;
glu.gluUnProject((double)x, (double)realy, 0, mvMatrix, 0, prMatrix, 0, viewPort, 0, wCoord, 0);
System.out.println(x + " " + y);
System.out.println(x + " " + realy);
System.out.println(wCoord[0] + " " + wCoord[1] + " " + wCoord[2]);
}
e = null;
}
当我单击在世界坐标 (4,5,0) 处渲染正方形的屏幕时,我从上述函数获得的示例输出:
878 56
878 636
0.0445182388817236 0.055475957454737095 8.900000001489369
谢谢!
编辑:使用 glReadPixels 读取深度缓冲区并将其用作 z(返回 1)得到的结果是正确的,但太大了 20 倍。
EDIT2:如果我将远裁剪平面设置为与相机高度相同的值,它似乎可以工作(但这并不适合)。
2(设计问题):我觉得在 OpenGL 画布的绘制函数中处理点击似乎没有意义。我似乎需要该函数中的 GL 才能检索 gluUnProject 运行所需的矩阵。大家会怎么设计这个?理想情况下,我觉得我应该能够让这个运行完全独立于绘图功能。将 gl 对象的引用存储到我的 MouseController 中,并在 MouseListener 接收到它时处理单击。
关于你们将如何处理它的输入也将不胜感激!