【问题标题】:Projection- Transforming 3d to 2d投影 - 将 3d 转换为 2d
【发布时间】:2013-03-28 11:15:23
【问题描述】:

我有问题或很好,我不知道如何将具有 x、y、z 值的 3d 点转换为 2d 点, 我必须绘制投影,其中我确实有点的 x、y、z 值,但我不知道如何将它们转换为 2d,因此我可以将它们移动到我的轴上。

我一直在浏览 wiki 和 google,但是我不太确定应该使用哪种矩阵转换来获得想要的结果。

【问题讨论】:

  • 您知道要将它们投影到哪个平面上吗?这架飞机将如何提供(以什么形式)?
  • 好吧,tbh 我不知道平面,但是我确实有函数,所以我计算 z 点取 xy 从 min max,然后我必须在轴上设置这些点,我上面已经画了,我什至不知道如何开始这样做,我一直在看几部关于绘图点的电影但是我确实必须绘制函数,所以我必须以某种方式连接这些点,我发现它必须这样做有矩阵的东西,但是不知道我应该应用什么矩阵变换
  • 您可能会发现有用的:en.wikipedia.org/wiki/3D_projection 以及与之相关的任何内容

标签: math graph matrix projection


【解决方案1】:

让我们首先假设看你的场景的相机以原点为中心,并且看向-z 方向。 那么:

  • 通过以下方式给出透视投影:
    x' = x/z
    y' = y/z

  • 一个正交投影由:
    x' = x
    y' = y
    (即,只丢弃 z 分量)

现在您已经应用了上述步骤,您可能会获得一个位于(x',y') = (-28.4, +134.5) 的点。您现在需要根据您的屏幕分辨率和相机“缩放系数”和纵横比对它们进行缩放和居中:例如,您可能想要乘以 Zoom 并将 screen_center 添加到您的 xy组件(请注意:大多数图形渲染系统的 y 方向指向下方,因此您可能需要为 y 组件交换符号)。您可能仍然会得到具有负坐标或坐标大于画布大小的像素。丢弃它们:这意味着它们不在您的视锥体之外。

最后,如果您的相机指向-z 或不在原点居中,您可能想知道该怎么办。对于后者,它很简单:只需在执行任何其他操作之前将相机坐标减去所有 3D 点的分量。对于相机旋转,它实际上也很容易:您只需要在执行其他任何操作之前以相机旋转的相反方式旋转您的点。这只是意味着您需要将所有 3D 坐标乘以相机旋转矩阵的转置。这一步背后的想法是,四处移动相机与在相反方向移动您的点完全相同(并且旋转矩阵的逆是同一矩阵的转置)。

【讨论】:

    【解决方案2】:

    我强烈建议使用现有的图形包来执行此操作,而不是尝试编写自己的库。我不知道您使用的是哪种语言,但 OpenGL 是一个开源图形引擎,可用于 3D 渲染并且具有跨语言可比性,因此它可能是开始的地方。

    如果您坚持手工操作,this 问题的答案中有很好的示例代码。

    【讨论】:

    • 谢谢,要读那个问题,但是我必须自己写,用画布
    【解决方案3】:

    如果您打算在 3 个维度上旋转您的形状,您只需要考虑相机角度。如果您对线性代数和三角函数有深入的了解,那么值得付出额外的努力,因为它使您的程序更加灵活,但如果您在数学上不太熟悉,我会推荐以下解决方案。

    要将 3D 图像投影到 2D 平面中,您需要做的是创建将映射的方程。

    (x,y,z) -> (x',y')
    

    您可以通过定义从 3D 点到 2D 点的三个映射来做到这一点。

    (1,0,0) -> (  1,  0)
    (0,1,0) -> (  0,  1)
    (0,0,1) -> (-.7,-.7)
    

    我将 (-.7,-.7) 用于 z 访问,因为该点距原点大约 1 个单位,位于 x 和 y 访问之间。

    有了这三个点之后,你就有足够的信息来计算任意点 x,y,z。

    (x,y,z) -> (1*x - .7*z, 1*y - .7*z)
    

    在计算机图形中,网格的原点不在屏幕中心,而是在左上角。为了使用我们刚刚在程序中生成的方程,我们必须定义一个偏移量以将原点移动到屏幕的中心。我们称这个偏移点(Ox, Oy)。

    有了偏移量,我们的等式变为以下。

    (x,y,z) -> (Ox + 1*x - .7*z, Oy + 1*y - .7*z)
    

    【讨论】:

      【解决方案4】:

      我找到了一种将 3D 投影到 等距 2D 的方法。

      我假设等轴测视图有一个角度,当然还有一个 3D 点来投影

      Dim IsometricViewAngle As Integer = 30
      Dim RowPoint As New Point3D(dx,dy,dz)
      

      dxdydz 是您的自定义值。 然后我必须计算 X 和 Y 增量和减量的 Delta 值,例如

      Dim XDelta = Math.Cos(IsometricViewAngle * Math.PI / 180)
      Dim YDelta = Math.Sin(IsometricViewAngle * Math.PI / 180)
      Dim ZDelta = 0.5
      

      好的,就是这样,现在我要将 3D 点投影到 2D 点:

      Dim X As Double = (RowPoint.X * XDelta) + (RowPoint.Y * YDelta)
      Dim Y As Double = (RowPoint.X * XDelta) + (RowPoint.Z * ZDelta)
      Dim ProjectedPoint As New Point(X,Y)
      

      最终结果在 RadDiagram 中效果最佳。 问候/

      【讨论】:

      • 如果 3D 值太大,例如 2565452 等,您可以将 X、Y 和 Z 除以 Dim ScaleValue As Ineger = 10000
      【解决方案5】:

      这对我有用:(它在 vb 中)。 f_nodes 是平面节点,a_nodes 是经过 alpha、beta 和 gamma 变换后的 3d 节点。 (x,y,z) 是一个点。还有更复杂的。

          ca = Cos(alpha)
          sa = Sin(alpha)
          cb = Cos(beta)
          sb = Sin(beta)
          cg = Cos(gamma)
          sg = Sin(gamma)
          q(1) = cg * (cb * X - sb * (sa * Y + ca * z)) - sg * (ca * Y - sa * z)
          q(2) = sg * (cb * X - sb * (sa * Y + ca * z)) + cg * (ca * Y - sa * z)
          q(3) = sb * X + cb * (sa * Y + ca * z)
      
          f_nodes(i, 1) = q(1)
          f_nodes(i, 2) = q(2)
      
          a_nodes(i, 1) = q(1)
          a_nodes(i, 2) = q(2)
          a_nodes(i, 3) = q(3)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-12
        • 2011-05-18
        • 1970-01-01
        • 2018-05-03
        相关资源
        最近更新 更多