2

我这里有点生疏了。

我有一个向量 (camDirectionX, camDirectionY, camDirectionZ) 代表我的相机视图方向。我有一个 (camX, camY, camZ) 这是我的相机位置。

然后,我在 (objectX, objectY, objectZ) 放置了一个对象

如何从相机的角度计算我的对象的方位角和仰角?

4

1 回答 1

4

为了简化问题,我要做的第一件事是转换坐标空间,使相机位于 (0, 0, 0) 并直接指向其中一个轴(所以方向是 (0, 0, 1) )。翻译使相机位于 (0, 0, 0) 非常简单,所以我不会深入讨论。旋转以使相机方向为 (0, 0, 1) 有点棘手...

一种方法是构建相机的完整正交基础,然后将其粘贴在旋转矩阵中并应用它。相机的“标准正交基”是指从相机指向前方、上方和右侧的三个向量的一种奇特方式。它们都应该彼此成 90 度(这是正交位的含义),并且它们的长度都应该是 1(这是正常位的含义)。

您可以通过一些叉积技巧获得这些向量:两个向量的叉积与两者垂直(成 90 度)。

为了获得向右的向量,我们可以将相机方向向量与 (0, 1, 0) (一个指向正上方的向量)进行交叉乘积。您需要对从叉积中得到的向量进行归一化。

为了获得相机的向上矢量,我们可以将相机方向矢量与我们刚刚计算的向右矢量进行交叉乘积。假设两个输入向量都被归一化,这不应该需要归一化。

我们现在有了相机的正交基础。如果我们将这些向量粘贴到 3x3 矩阵的行中,我们会得到一个旋转矩阵,它将转换我们的坐标空间,因此相机直接指向其中一个轴(哪个轴取决于您粘贴向量的顺序)。

现在计算物体的方位角和仰角相当容易。

要获得方位角,只需atan2在对象的 x/z 坐标上执行。

要获得高程,请将对象坐标投影到 x/z 平面上(只需将 y 坐标设置为 0),然后执行以下操作:

acos(dot(normalise(object coordinates), normalise(projected coordinates)))

这将始终给出一个正角度——如果对象的 y 坐标小于 0,您可能想要否定它。

所有这些的代码将类似于:

fwd = vec3(camDirectionX, camDirectionY, camDirectionZ)
cam = vec3(camX, camY, camZ)
obj = vec3(objectX, objectY, objectZ)

# if fwd is already normalised you can skip this
fwd = normalise(fwd)

# translate so the camera is at (0, 0, 0)
obj -= cam

# calculate the orthonormal basis of the camera
right = normalise(cross(fwd, (0, 1, 0)))
up = cross(right, fwd)

# rotate so the camera is pointing straight down the z axis
# (this is essentially a matrix multiplication)
obj = vec3(dot(obj, right), dot(obj, up), dot(obj, fwd))

azimuth = atan2(obj.x, obj.z)

proj = vec3(obj.x, 0, obj.z)
elevation = acos(dot(normalise(obj), normalise(proj)))
if obj.y < 0:
    elevation = -elevation

需要注意的一件事是,当您的相机直上或直下时,原始相机矢量与 (0, 1, 0) 的叉积将返回零长度矢量。为了完全定义相机的方向,我假设它总是“直的”,但这并不意味着当它直上或直下时——你需要另一个规则。

于 2012-06-11T03:47:39.087 回答