我有问题或很好,我不知道如何将具有 x、y、z 值的 3d 点转换为 2d 点,我必须绘制投影,我确实有点的 x、y、z 值但我不知道如何将它们转换为 2d 以便我可以将它们移动到我的轴上。
我一直在寻找 wiki 和 google,但是我不太确定应该使用哪些矩阵转换来获得想要的结果。
我有问题或很好,我不知道如何将具有 x、y、z 值的 3d 点转换为 2d 点,我必须绘制投影,我确实有点的 x、y、z 值但我不知道如何将它们转换为 2d 以便我可以将它们移动到我的轴上。
我一直在寻找 wiki 和 google,但是我不太确定应该使用哪些矩阵转换来获得想要的结果。
让我们首先假设查看您的场景的相机以原点为中心,并查看-z
方向。然后:
透视投影由下式给出:
x' = x/z
y' = y/z
正交投影由下式给出:(
x' = x
y' = y
即,仅丢弃 z 分量)
现在您已经应用了上述步骤,您可能会获得一个位于 的点(x',y') = (-28.4, +134.5)
。您现在需要根据您的屏幕分辨率和相机“缩放因子”和纵横比来缩放和居中它们:例如,您可能想要乘以Zoom
并添加screen_center
到您的组件x
和y
组件(注意:大多数图形渲染系统都有y
方向指向向下,因此您可能需要为y
组件交换符号)。您可能仍然会得到具有负坐标或坐标大于画布大小的像素。只需丢弃它们:这意味着它们在您的视锥之外。
最后,您可能想知道如果您的相机未指向-z
原点或未以原点为中心该怎么办。对于后者,这很简单:只需在执行任何其他操作之前将相机坐标减去所有 3D 点的分量即可。对于相机旋转,它实际上也很容易:您只需要在执行其他任何操作之前以相机旋转的相反方式旋转您的点。这只是意味着您需要将所有 3D 坐标乘以相机旋转矩阵的转置。这一步背后的想法是,移动相机与在相反方向移动点完全相同(并且旋转矩阵的逆是同一矩阵的转置)。
I would highly recommend using an existing graphics package to do this rather trying to write your own libraries. I don't know what language you are working in but OpenGL is an open source graphics engine that can be used for 3D rendering and has cross-language comparability so it might be the place to start.
If you insist on doing it by hand there is very good example code in the answer to this question.
如果您打算在 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)
这对我有用:(它在 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)
我找到了一种将 3D 投影到Isometric 2D 的方法。
我假设等轴测视图的角度,当然还有一个要投影的 3D 点
Dim IsometricViewAngle As Integer = 30
Dim RowPoint As New Point3D(dx,dy,dz)
其中dx、dy和dz是您的自定义值。然后我必须计算 X 和 Y 增量和减量的增量值,例如
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 中效果最好。问候/