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

4
我想将一个3D位置转换成2D屏幕位置。我看了一个类似的问题:将3D点投影到2D屏幕坐标,但我并不完全理解它。我认为为了计算2D位置,我需要投影矩阵,但我不知道它是如何使用的,除了将一个点转换成位置坐标空间之外。此外,在OpenGL中,cam.FieldOfView是否等于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个回答

12

看起来这应该是这样的:

    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);
    }
我们在这里做的就是将向量通过两个变换矩阵进行传递:视图,然后投影。投影后,您将获得一个Y和X值在-1到1之间的向量。我们进行适当的变换以获得实际像素坐标,并返回一个新的Vector2。请注意,'pos'的Z分量还存储了点的深度,在函数结束时在屏幕空间中。
您需要'view'矩阵,因为它定义了相机的位置和旋转。投影仅定义了3D空间在2D空间上被“压扁”的方式。
视野范围不是远端Z。投影矩阵具有一些参数,其中包括:
- 视野(FOV),即水平的视角,用弧度表示; - 远平面或farZ:这定义了点可以从相机处最远的距离; - 近平面或nearZ:点可以从相机处的最小距离。
除了数学问题外,您可以直接使用Vector2而不是堆分配(返回指针)。 Vector2是一个轻量级结构,指针在这种情况下很可能会引起头痛(您要在哪里删除它等等)。还请注意,我使用了 'const' 引用,因为我们不修改它们,除了向量。对于这个向量,我们想要一个局部副本,这就是为什么它根本不是引用的原因。

7

之前的代码只适用于没有进行旋转的情况(例如 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);
}

据我所知:请注意,此示例不是C++,而是C#。这一点非常重要,因为原始问题是关于C++的。 - Jean

0

我认为你正在寻找的是gluLookAt的替代品。它可以将场景几何转换为渲染屏幕坐标,基于位置和方向。正如文章所说,它依赖于OpenGL的一些已弃用的特性,但它提供了一个代码示例,你可以使用自己的向量/矩阵库来实现。更详细的投影矩阵信息可以从这里获得。

一旦你有了投影矩阵,你只需要将其应用于你的向量(通过投影矩阵后乘以场景向量),然后只需丢弃结果向量的Z分量...也就是只使用结果向量的X和Y分量。


不要忘记你必须“除以W分量”!这一步让投影矩阵实际进行投影... - comingstorm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接