将3D矩形映射到2D屏幕

时间:2011-04-22 17:29:46

标签: wpf 3d mapping transform perspective

我搜索过但我无法弄清楚这一点。其他问题没有帮助,或者我不理解。

问题是,我在3D图像中有一堆点。这些点是一个矩形,由于透视,它看起来不像3D相机视图中的矩形。任务是将该矩形的点映射到屏幕。我已经看到了一些有些人称之为“四到四变换”的方法,但大多数都用于将二维四边形映射到另一个四边形。但是我在现实世界中得到了矩形的X,Y 和Z 坐标,所以我正在寻找一些更简单的方法。有谁知道这样做的任何实用算法或方法?

如果有帮助,我的3D相机实际上是一个带有OpenNI和NITE中间件的Kinect设备,我正在使用WPF。

提前致谢。

修改 我还发现维基百科上的3D投影页面使用了角度和余弦,但这似乎是一种困难的方式(在3d图像中找到角度),我不确定它是否是真正的解决方案。

5 个答案:

答案 0 :(得分:2)

您可能需要查看projection matrices

这就是任何3D光栅化器在2D屏幕上“展平”3D体积的方式。

答案 1 :(得分:2)

See this code获取给定WPF相机的投影矩阵:

private static Matrix3D GetProjectionMatrix(OrthographicCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixOrthoRH with the exception that in WPF only
    // the camera's width is specified.  Height is calculated
    // from width and the aspect ratio.
    double w = camera.Width;
    double h = w / aspectRatio;
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double m33 = 1 / (zn - zf);
    double m43 = zn * m33;
    return new Matrix3D(
        2 / w, 0, 0, 0,
        0, 2 / h, 0, 0,
        0, 0, m33, 0,
        0, 0, m43, 1);
}

private static Matrix3D GetProjectionMatrix(PerspectiveCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixPerspectiveFovRH with the exception that in
    // WPF the camera's horizontal rather the vertical
    // field-of-view is specified.
    double hFoV = MathUtils.DegreesToRadians(camera.FieldOfView);
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double xScale = 1 / Math.Tan(hFoV / 2);
    double yScale = aspectRatio * xScale;
    double m33 = (zf == double.PositiveInfinity) ? -1 : (zf / (zn - zf));
    double m43 = zn * m33;
    return new Matrix3D(
        xScale, 0, 0, 0,
        0, yScale, 0, 0,
        0, 0, m33, -1,
        0, 0, m43, 0);
}

/// <summary>
///     Computes the effective projection matrix for the given
///     camera.
/// </summary>
public static Matrix3D GetProjectionMatrix(Camera camera, double aspectRatio)
{
    if (camera == null)
    {
        throw new ArgumentNullException("camera");
    }
    PerspectiveCamera perspectiveCamera = camera as PerspectiveCamera;
    if (perspectiveCamera != null)
    {
        return GetProjectionMatrix(perspectiveCamera, aspectRatio);
    }
    OrthographicCamera orthographicCamera = camera as OrthographicCamera;
    if (orthographicCamera != null)
    {
        return GetProjectionMatrix(orthographicCamera, aspectRatio);
    }
    MatrixCamera matrixCamera = camera as MatrixCamera;
    if (matrixCamera != null)
    {
        return matrixCamera.ProjectionMatrix;
    }
    throw new ArgumentException(String.Format("Unsupported camera type '{0}'.", camera.GetType().FullName), "camera");
}

答案 2 :(得分:1)

你可以做一个基本的正交投影(我正在考虑光线追踪,所以这可能不适用于你正在做的事情):

enter image description here

代码非常直观:

for y in image.height:
  for x in image.width:
    ray = new Ray(x, 0, z, Vector(0, 1, 0)) # Pointing forward
    intersection = prism.intersection(ray) # Since you aren't shading, you can check only for intersections.

    image.setPixel(x, y, intersection) # Returns black and white image of prism mapped to plane

你只需将方向为(0, 1, 0)的向量直接射入太空并记录哪些被击中。

答案 3 :(得分:1)

我找到了this。使用直接的数学而不是matricies。

这称为透视投影,用于从3D顶点转换为2D屏幕顶点。我用它来帮助我完成我的3D程序。

HorizontalFactor = ScreenWidth / Tan(PI / 4)
VerticalFactor = ScreenHeight / Tan(PI / 4)

ScreenX = ((X * HorizontalFactor) / Y) + HalfWidth
ScreenY = ((Z * VerticalFactor) / Y) + HalfHeight

希望这可以提供帮助。我认为你在哪里寻找。抱歉格式化(此处新增)

答案 4 :(得分:0)

将3D世界中的点映射到2D屏幕是OpenGL和Direct3d等框架工作的一部分。它像希恩德尔所说的那样被称为光栅化。也许你可以使用Direct3d?