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

Ped*_*dro 4 c++ math 3d 2d

我想将3d位置转换为2d屏幕位置.我看了一个类似的问题:将3D点投影到2D屏幕坐标,但我完全不了解它.我想为了计算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); 
       }
Run Code Online (Sandbox Code Playgroud)

Jea*_*ean 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);
    }
Run Code Online (Sandbox Code Playgroud)

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

您需要"视图"矩阵,因为它定义了摄像机的位置和旋转位置.投影仅定义3D空间在2D空间上"展平"的方式.

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

  • 视场,FOV,即水平视角,以弧度表示;
  • 远平面,或farZ:这定义了一个点距摄像机的最大距离;
  • 近平面,近Z:一个点距摄像机的最小距离.

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


sko*_*lko 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);
}
Run Code Online (Sandbox Code Playgroud)