我这里有点生疏了。
我有一个向量 (camDirectionX, camDirectionY, camDirectionZ) 代表我的相机视图方向。我有一个 (camX, camY, camZ) 这是我的相机位置。
然后,我在 (objectX, objectY, objectZ) 放置了一个对象
如何从相机的角度计算我的对象的方位角和仰角?
为了简化问题,我要做的第一件事是转换坐标空间,使相机位于 (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) 的叉积将返回零长度矢量。为了完全定义相机的方向,我假设它总是“直的”,但这并不意味着当它直上或直下时——你需要另一个规则。