Java OpenGL屏幕到世界的转换使用gluUnProject+设计讨论



我有两个问题。一个是关于为什么我的代码不能按预期工作的具体问题,另一个是设计问题。

1(具体问题):我正在尝试在基于2D平铺的引擎中将屏幕坐标映射到世界坐标(使用x/y轴,z=0)。我使用了Nehe的教程端口来说明如何实现这一点,但我得到的结果并不像预期的那样。

我有一门课叫鼠标控制器。每当鼠标事件被触发时(通过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运行所需的矩阵。你们会怎么设计这个?理想情况下,我觉得我应该能够让这个运行完全独立于draw函数。将gl对象的引用存储到我的MouseController中,并在MouseListener找到它时处理点击。

关于你们将如何处理它的意见也将不胜感激!

我决定只使用gluOrtho2D来设置投影,以简化解决此问题的过程。

唯一"棘手"的事情是将实际屏幕分辨率传递给gluOrtho2D,它可以通过检索(并存储)

getContentPane().getSize()

来自我使用的JFrame。

在面板上设置首选尺寸,然后包装框架,取得了很好的效果,但面板本身仍然有点偏离。

最新更新