Sen*_*ful 10
注意:我将使用Fletcher Dunn 的 3D Math Primer for Graphics and Game Development 所定义的约定“航向、俯仰、倾斜”,而不是“偏航、俯仰、横滚”定义的约定“航向、俯仰、倾斜”,而不是“偏航、俯仰、横滚” 。
\n\n首先,请注意,在 2D 坐标系中,您只需要一个角度 + 大小即可“指向”2D 中的任何点。
\n\n同样,在3D坐标系中,只需要两个角度+ 大小即可“指向”3D 中的任何点。最后一个角度(“倾斜”或“滚动”)不会影响 3D 中点的位置。相反,它会“旋转”指向它的箭头。如果对象是 360 度对称,则根本不会看到旋转对对象产生影响。如果物体不对称(例如飞机),则会影响物体(例如,一侧机翼向地面倾斜,另一侧机翼向天空倾斜)。
\n\n因此,最初的问题实际上变成了“如何找到“指向”3D 空间中任意点的航向角、俯仰角和幅度?”
\n\n您可以使用三角函数轻松计算出这一点。想象一下我们有这样的观点(1,2,3)
,并且正在尝试计算航向、俯仰、幅度。
对于下面的示例,我们使用此图,其中左轴为 X,上轴为 Y,右轴为 Z。(1,2,3)
, then 由蓝色球体表示。
\n \n\n\n
首先,让我们找到最简单的值,即幅度。幸运的是,无论我们有多少维,只要使用毕达哥拉斯定理,就可以轻松找到任意两点之间的大小(长度) 。由于我们处于 3D 环境中并且正在计算从原点到我们的点的距离,因此我们的距离公式变为:
\n\nmagnitude = sqrt(x*x + y*y + z*z)\n
Run Code Online (Sandbox Code Playgroud)\n\n代入我们的实际值:
\n\nmagnitude = sqrt(1*1 + 2*2 + 3*3)\n = 3.7416573868\n
Run Code Online (Sandbox Code Playgroud)\n\n所以我们的大小(或长度)是 ~ 3.741
。
接下来,为了找到航向,请注意我们只关心绕 XZ 平面的旋转,而根本不关心 Y 轴。如果我们将 3D 空间“展平”为 2D,那么找到标题就变得微不足道了。
\n\n我们可以画一个与 X 轴形成 90 度角的三角形(红色三角形),然后计算该角度。回忆一下三角学 tan(angle) = opposite / adjacent
,并求解angle
,我们得到angle = arctan(opposite / adjacent)
。
在这种情况下,“相邻”是已知量 ( redAdjacent = x = 1
),“相反”也是已知量 ( redOpposite = z = 3
)。不过,我们不想使用 arctan 来求解方程,而是使用atan2,因为它会为我们处理 x 和 y 的所有不同情况。
所以我们有:
\n\nheading = atan2(redOpposite, redAdjacent)\n
Run Code Online (Sandbox Code Playgroud)\n\n代入我们的实际值:
\n\nheading = atan2(3, 1)\n = 1.249045772398\n
Run Code Online (Sandbox Code Playgroud)\n\n所以我们的标题是1.249
rad 或 ~ 72\xc2\xb0
。
最后我们需要找到球场。与我们对标题所做的类似,我们可以沿着包含这三个点的平面将 3D 空间展平为 2D:(A) 原点(0,0,0)
、(B) 我们的点(1,2,3)
和 (C) 我们的点,因为它将投影到XZ 平面(1,0,3)
(例如,通过将 Y 值设置为 0)。
如果我们在这三个点之间画一个三角形,您会发现它们再次形成一个直角三角形(绿色三角形)。我们可以简单地再次使用来计算角度arctan2
。
我们已经在步骤 1 中计算了绿色斜边(即向量的大小):
\n\ngreenHypotenuse = sqrt(x*x + y*y + z*z)\n = 3.7416573868\n
Run Code Online (Sandbox Code Playgroud)\n\n我们还知道绿色三角形的相反方向与 y 值相同:
\n\ngreenOpposite = y\n = 2\n
Run Code Online (Sandbox Code Playgroud)\n\n利用毕达哥拉斯定理,我们可以求出邻角的长度:
\n\ngreenOpposite^2 + greenAdjacent^2 = greenHypotenuse^2\ny*y + greenAdjacent^2 = x*x + y*y + z*z\ngreenAdjacent^2 = x*x + z*z\ngreenAdjacent = sqrt(x*x + z*z)\n
Run Code Online (Sandbox Code Playgroud)\n\n请注意,计算绿色三角形相邻长度的另一种方法是注意redHypotenuse == greenAdjacent
,我们可以发现redHypotenuse
使用:
redHypotenuse^2 = redAdjacent^2 + redOpposite^2\n = x*x + z*z\nredHypotenuse = sqrt(x*x + z*z)\n
Run Code Online (Sandbox Code Playgroud)\n\n代入实际值,我们得到:
\n\ngreenAdjacent = sqrt(1*1 + 3*3)\n = 3.1622776602\n
Run Code Online (Sandbox Code Playgroud)\n\n现在我们知道了绿色三角形的相邻和相反的长度,我们可以使用arctan2
再次使用:
pitch = atan2(greenOpposite, greenAdjacent)\n = atan2(2, 3.1622776602)\n = 0.563942641356\n
Run Code Online (Sandbox Code Playgroud)\n\n所以我们的音高是0.5634
弧度,或者大约32\xc2\xb0
。
如果你要从原点画一条线,长度为3.741
,航向1.249
rad ,螺距0.564
rad ,它会从 延伸(0,0,0)
到(1,2,3)
。