将3d位置转换为2d屏幕位置

时间:2011-10-13 01:10:27

标签: c++ math 3d 2d

我想将3d位置转换为2d屏幕位置。我看了一个类似的问题:Projecting a 3D point to a 2D screen coordinate,但我完全不明白。我想为了计算2d位置我需要投影矩阵,但我不知道如何使用它,除了将点转换为位置坐标空间。另外,cam.FieldOfView在OpenGL中等于farZ吗?

有人可以帮我完成这个功能。参数是否足以计算2d位置? Pos已经是相对于相机位置的矢量。

       Vector2* convert(Vector3& pos, Matrix4& projectionMatrix, int screenWidth, int screenHeight)
       {
            float ratio = screenWidth / screenHeight; 

            ...

            screenX = screenWidth * ( 1.0f - screenX); 
            screenY = screenHeight * ( 1.0f - screenY);    

            return new Vector2(screenX, screenY); 
       }

3 个答案:

答案 0 :(得分:10)

在我看来会是这样的:

    Vector2 Convert(Vector3 pos, const Matrix& viewMatrix, const Matrix& projectionMatrix, int screenWidth, int screenHeight)
    {
        pos = Vector3::Transform(pos, viewMatrix);
        pos = Vector3::Transform(pos, projectionMatrix);

        pos.X = screenWidth*(pos.X + 1.0)/2.0;
        pos.Y = screenHeight * (1.0 - ((pos.Y + 1.0) / 2.0));

        return Vector2(pos.X, pos.Y);
    }

我们在这里做的只是通过两个转换矩阵传递Vector:视图,然后是投影。在投影之后,你得到一个Y和X在-1和1之间的向量。我们进行适当的变换以获得真实的像素坐标并返回一个新的Vector2。请注意,'pos'的Z分量也会在屏幕空间中存储该点的深度。

您需要'view'矩阵,因为它定义了相机的位置和旋转位置。投影仅定义3D空间在2D空间上“展平”的方式。

视野不是farZ。投影矩阵有一些参数,其中包括:

  • 视野,FOV,即水平视角,以弧度为单位;
  • 远平面或farZ:这定义了一个点离相机的最大距离;
  • 近平面,靠近Z:点可以离相机的最小距离。

除了数学问题,您可以直接使用Vector2而不是堆分配(返回指针)。 Vector2是一个轻量级结构,指针很可能在这种情况下引起头痛(你要删除它的位置,依此类推)。还要注意我使用'const'引用,因为除了vector之外我们不修改它们。对于这个我们想要一个本地副本,这就是为什么它根本不是一个参考。

答案 1 :(得分:5)

以前的代码仅在您不进行任何轮换时才有效(例如。GL.Rotate(rotation_x, 1.0, 0.0, 0.0))。 但如果你这里做的是代码:

private Vector2 Convert(Vector3 pos, Matrix4 viewMatrix, Matrix4 projectionMatrix, int screenWidth, int screenHeight)
{
    pos = Vector3.Transform(pos, viewMatrix);
    pos = Vector3.Transform(pos, projectionMatrix);
    pos.X /= pos.Z;
    pos.Y /= pos.Z;
    pos.X = (pos.X + 1) * screenWidth / 2;
    pos.Y = (pos.Y + 1) * screenHeight / 2;

    return new Vector2(pos.X, pos.Y);
}

答案 2 :(得分:0)

我认为您正在寻找的是gluLookAt的替代品。给定位置和方向,它将场景几何转换为屏幕坐标以进行渲染。正如文章所说,它依赖于OpenGL的许多不赞成使用的功能,但它确实提供了一个可以使用矢量/矩阵库实现的代码示例。有关投影矩阵的更多详细信息,请参见here

一旦你有了投影矩阵,你只需将它应用到矢量(通过投影矩阵对场景的矢量进行后乘),然后只删除结果矢量的Z分量......也就是说,只需使用X和结果向量的Y分量。