【问题标题】:Mapping a 3D rectangle to a 2D screen将 3D 矩形映射到 2D 屏幕
【发布时间】:2011-08-11 02:50:39
【问题描述】:

我已经搜索过,但我就是想不通。其他问题没有帮助,或者我不明白。

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

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

提前致谢。

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

【问题讨论】:

  • 您是否尝试将其投影到二维平面上?没有透视失真?
  • 我想映射它,让您看起来像是在直视对象,如果这就是您所说的投影。

标签: wpf 3d mapping transform perspective


【解决方案1】:

您可能想查看projection matrices

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

【讨论】:

  • +1 但请记住,投影矩阵(以及大多数与图形相关的矩阵)不适合轻松愉快的人,也不适合那些不注意数学的人。它们是非常严肃的东西。我会留意你可以使用的为你完成这项工作的库。 (我想到了OpenGL,但我已经太久不记得你是否必须在那里手工制作矩阵......)编辑:点击链接,恐怖又如火如荼地复活了。啊!!
  • 我无法忍受矩阵。真正的绅士从不选择自己的基础;)
  • @Heandel,谢谢,我正在寻找的投影不是正交的。我说的对吗?
  • 正交不考虑透视失真; 20 英里外的人与 10 英尺外的人看起来一样。有点像这样(他们不“看”3D):en.wikipedia.org/wiki/…
  • @Heandel,谢谢,我明白了。所以在那种情况下,我正在寻找透视投影。
【解决方案2】:

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

【讨论】:

  • 那么,您是说通过在现实世界中提供矩形的四个坐标或向 Direct3D 提供此类输入,它可以映射我给它的任何其他点?我试试看。
【解决方案3】:

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

代码很直观:

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) 的矢量直接射入太空并记录命中的矢量。

【讨论】:

    【解决方案4】:

    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");
    }
    

    【讨论】:

      【解决方案5】:

      我找到了this。使用直截了当的数学而不是矩阵。

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

      HorizontalFactor = ScreenWidth / Tan(PI / 4)
      VerticalFactor = ScreenHeight / Tan(PI / 4)
      
      ScreenX = ((X * HorizontalFactor) / Y) + HalfWidth
      ScreenY = ((Z * VerticalFactor) / Y) + HalfHeight
      

      希望这会有所帮助。我认为它是你在哪里寻找的。对格式表示抱歉(此处为新)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-03
        • 1970-01-01
        相关资源
        最近更新 更多