【问题标题】:gluProject Converting 3D coordinates to 2D coordinates does not convert the 2D Y Coordinate correctlygluProject 将 3D 坐标转换为 2D 坐标不会正确转换 2D Y 坐标
【发布时间】:2015-01-01 11:58:25
【问题描述】:

经过两个小时的谷歌搜索(hereherehereherehere,还有一大堆我懒得找的其他东西),我想我终于学会了将 3D 坐标转换为 2D 坐标的理论。但它不起作用。想法是将飞船的 3D 坐标转换为屏幕上的 2D 坐标,以呈现控制该飞船的玩家的用户名。

但是,文本呈现在错误的位置:

文本是“测试 || 2DXCoordinate || 2DZCoordinate”。

这是我的getScreenCoords() - 它将 3D 坐标转换为 2D。

public static int[] getScreenCoords(double x, double y, double z) {
    FloatBuffer screenCoords = BufferUtils.createFloatBuffer(4);
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);
    GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
    GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
    boolean result = GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);
    if (result) {
        return new int[] { (int) screenCoords.get(0), (int) screenCoords.get(1) };
    }
    return null;
}

screenCoords.get(0) 返回一个完美的 X 坐标。但是, screenCoords.get(1) 会根据我离船的距离而升高或降低。经过数小时的调试,我将其范围缩小到这一行不正确:

GLU.gluProject((float) x, (float) y, (float) z, modelView, projection, viewport, screenCoords);

但是,我不知道出了什么问题。船的X坐标很好……为什么不是Y?

根据 BDL 的回答,我向 gluProject() 提供了“错误的矩阵”。但我不明白这是怎么可能的,因为我在渲染我的船后立即调用了该方法(这显然是在绘制船的任何矩阵中)。

我就是不知道哪里出了问题。

注意:BDL 的答案是完全足够的,只是它没有解释为什么 Y 坐标不正确。

注意:这个问题过去更长,也更模糊。经过数小时的调试,我在上面发布了缩小范围的问题。

【问题讨论】:

  • 1.您是否在代码中的某处设置了 GL_MODELVIEW 矩阵?对我来说,它看起来好像是一个单位矩阵。 2. orthographicProjectionMatrix 是否包含您用来渲染飞船的透视投影?
  • @BDL orthographicProjectionMatrix 包含我用来渲染文本的投影。不是船。
  • 在您发布的第二个代码块中,您正在将 orthographicProjectionMatrix 加载到投影矩阵中。这个矩阵的内容是什么?对我来说,好像您从未设置过模型视图矩阵。画船的时候从不调用 glTranslatef/glRotatef 吗?
  • @BDL 添加了更多代码。我可以添加整个类,但我认为人们不想筛选 2000 行代码。

标签: java opengl lwjgl glu


【解决方案1】:

您必须在 gluProject 中使用与渲染飞船相同的投影矩阵。在您的情况下,船是使用透视投影渲染的,但是当您调用 gluProject 时,使用的是正交投影。

关于 OpenGL 中坐标系的一般理论

在大多数情况下,场景中模型(例如船)的几何形状是在模型坐标系中给出的。这是您的顶点坐标存在的空间。现在将模型放置在您的场景中时,我们将模型矩阵应用于每个顶点以获取船舶在场景中的坐标。这个坐标系被称为世界空间。当从给定的视点和观察方向查看场景时,再次需要对场景进行变换,以使视点位于原点 (0,0,0) 并且视图方向沿负 z 轴。这是视图坐标系。最后一步是将视图坐标转换为 ndc,这是通过投影矩阵完成的。

总的来说,我们得到一个顶点到屏幕的变换:

 v_screen = Projection * View * Model * v_model

在古老的 OpenGL(当你使用它时)中,View 和 Model 一起存储在 ModelView 矩阵中。

(我这里跳过了一些问题,因为视角划分,但理解问题应该足够了。)

您的问题

您已经在飞船的世界空间 (x,y,z) 中拥有一个位置。因此,与 Model 的转换已经发生。剩下的是

v_screen = Projection * View * v_worldspace

为此,我们看到,在我们的例子中,输入到 gluProject 的 ModelView 矩阵必须完全是 View 矩阵。

我不能告诉你在你的代码中从哪里得到视图矩阵,因为我不知道你的这部分代码。

【讨论】:

  • 我用新代码更新了 OP。它确实使它变得更好,非常感谢您的建议,但由于某种原因,代码仍然不完美并且无法正常工作。
  • 很可能是因为您对 MODELVIEW 矩阵有同样的问题。如果 (x,y,z) 在世界坐标中,您的 MODELVIEW 矩阵应该只包含视图矩阵,而不是模型矩阵。
  • 什么?我不明白,对不起。我在船舶渲染后将 2D 坐标设置在准确的线上。这不正确吗?我怎样才能让它没有模型矩阵而只有视图矩阵?
  • 获取太多文本。我会在几秒钟内更新答案。
  • gluProject 正在返回它应该返回的内容。问题很可能是您提供给它的矩阵。只有当有人检查您的完整代码时,才能找出这个矩阵中的确切内容。
【解决方案2】:

我找到了问题的答案!

我用过

font.drawString(drawx - offset, drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);

应该是什么时候

font.drawString(drawx - offset, Display.getHeight() - drawy, (sh.username + " || " + drawx + " | " + drawy), Color.orange);

【讨论】:

    猜你喜欢
    • 2018-05-25
    • 1970-01-01
    • 2012-03-06
    • 2015-06-29
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多