【问题标题】:How to get Screen coordinates from a 3D Point? Opengl如何从 3D 点获取屏幕坐标?开放式
【发布时间】:2010-09-25 04:18:56
【问题描述】:

我见过很多屏幕坐标到世界坐标的帖子,但没有看到相反的情况。有没有一种简单的方法可以从我查看的任何角度从 3d 点获取屏幕坐标?我正在使用 C++ 和 opengl

【问题讨论】:

  • 这是stackoverflow.com/questions/724219/…的完全相同的副本
  • @Mads Elvheim:几乎完全一样。这个问题特定于 C++ 和 OpenGL。另一个问题不是。事实上,另一个问题被标记为“Java”。

标签: c++ opengl


【解决方案1】:

erjot 的回答不完整。

还有 2 件额外的事情需要考虑。

  1. 对于homogeneous = P . M . worldhomogeneous 向量是齐次空间中的 4 维向量。特别是,要将其带回 [-1:1]^3 立方体,您需要将其前 3 个坐标除以 homogeneous.wcube.x = homogeneous.x / homogeneous.w(有些人称之为投影鸿沟)。
  2. 然后,您需要通过对其应用视口变换将 [-1:1]^3 立方体变换为窗口坐标。 window.x = viewport.x + viewport.width * (cube.x+1)/2

如果您关心最终的 Z,则转换不会通过视口,而是通过 DepthRange。

【讨论】:

    【解决方案2】:

    一个顶点的屏幕坐标只是这个顶点乘以其投影和模型视图矩阵的结果:

    screen_coordinates = projection_matrix * modelview_matrix * world_coordinates

    您可以手动完成(特别是如果您使用一些数学库对矩阵进行运算)或使用 gluProject,例如:

    std::array<GLfloat, 16> projection;
    std::array<GLfloat, 16> modelview;
    std::array<GLfloat, 3>  screen_coords;
    
    glGetFloatv(GL_PROJECTION_MATRIX, projection.data());
    glGetFloatv(GL_MODELVIEW_MATRIX, modelview.data());
    
    gluProject(world_coords[0], world_coords[1], world_coords[2],
        modelview.data(), projection.data(),
        screen_coords.data(), screen_coords.data() + 1, screen_coords.data() + 2);
    

    【讨论】:

    • 投反对票。 gluProject 做正确的事,但你的解释没有。仅将一个点与模型视图矩阵和投影矩阵相乘即可​​得到剪辑空间坐标,但 除以 w 之前。它不会为您提供屏幕空间坐标。请参阅 bahbar 的回答。
    • 要判断它是否给出了正确的空间坐标,你需要更多关于 OP 世界设置的细节,例如我几乎从不为我的 2D 游戏使用视口设置。但看起来你的水晶球完美无瑕,所以请投反对票:)
    • ps。 OpenGL的(固定功能管道)投影矩阵不是包含视口的设置吗?您需要明确除以 w 的情况是什么? GLSL 默认会这样做。
    • 无论您是否知道,您都使用 Viewport。这就是确保您绘制到整个窗口的原因(通常,如果您的窗口改变大小,您会改变一些东西)。 gluProject 需要 9 个参数,而不是 8 个。您删除了一个视口……不,投影不包含视口变换。它为 [-1:1] 多维数据集带来了原语,如我的帖子中所述。这就是 剪辑 发生的时候。在视口变换之前。 GLSL(我假设你的意思是生成的着色器?)当然不是在做 w-divide,因为它也需要在裁剪之后发生(裁剪器在齐次坐标上工作)。
    【解决方案3】:

    另一件事。请记住,gluProject 给出了坐标系起点从左下角开始的坐标。屏幕坐标从左上角开始。为了获得适当的屏幕坐标值,必须从 OpenGL 设备的高度中减去 y 值。

    例如在 Qt GLWidget 中以 (0,1,2) 世界坐标绘制文本:

    gluProject(0,1,2,modelMatrix,projMatrix,sc.x,sc.y,sc.z); renderText(sc.x,height()-sc.y,"(0,1,2)");

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2015-08-01
      • 1970-01-01
      • 2012-02-02
      • 1970-01-01
      • 2019-08-22
      • 2016-02-29
      相关资源
      最近更新 更多