在 ARKit 中获取相机的向上矢量

Get the up vector of the camera in ARKit

我试图在ARKit中获取构成平截头体边界的四个向量,我想出的解决方案如下:

这可能是一种草率的做法,但它是迄今为止我得到的最好的方法。

我能够从 ARCamera.intrinsicsARCamera.transform 属性中获取 FOV 角度和方向向量。但是,我现在不知道如何获取相机的向上矢量。

下面是我用来查找 FOV 角度和方向向量的代码片段:

func session(_ session: ARSession, didUpdate frame: ARFrame) {
  if xFovDegrees == nil || yFovDegrees == nil {
    let imageResolution = frame.camera.imageResolution
    let intrinsics = frame.camera.intrinsics
    xFovDegrees = 2 * atan(Float(imageResolution.width) / (2 * intrinsics[0,0])) * 180 / Float.pi
    yFovDegrees = 2 * atan(Float(imageResolution.height) / (2 * intrinsics[1,1])) * 180 / Float.pi
  }

  let cameraTransform = SCNMatrix4(frame.camera.transform)
  let cameraDirection = SCNVector3(-1 * cameraTransform.m31,
                                   -1 * cameraTransform.m32,
                                   -1 * cameraTransform.m33)
}

我也乐于接受关于如何找到我试图获得的四个向量的建议。

我不明白这条线是如何工作的:

let cameraDirection = SCNVector3(-1 * cameraTransform.m31,
                                 -1 * cameraTransform.m32,
                                 -1 * cameraTransform.m33)

这给出了摄像机的方向向量,因为变换矩阵的第 3 行给出了变换后摄像机的新 z 方向指向的位置。我们将它乘以 -1,因为相机的默认方向是负 z 轴。

考虑到此信息以及相机的默认向上矢量是正 y 轴这一事实,变换矩阵的第 2 行为我们提供了相机的向上矢量。下面的代码给了我我想要的:

let cameraUp = SCNVector3(cameraTransform.m21,
                          cameraTransform.m22,
                          cameraTransform.m23)

可能是我误解了你的意思,但我想提供一个替代方案(方法和结果与你的答案不同)。

出于我的目的,当 phone 笔直指向上方时,我将向上矢量定义为 (0, 1, 0) - 基本上我想要的单位矢量直接指向phone。当 phone 向左水平时,ARKit 将向上向量定义为 (0, 1, 0) - 因此 y 轴指向 phone 的右侧 - 据说是因为他们期望AR 应用更喜欢水平方向。

camera.transform returns AR 会话开始时相机的方向相对于其初始方向。它是一个 4x4 矩阵 - 第一个 3x3 是旋转矩阵 - 所以当你写 cameraTransform.m21 等时,你引用的是旋转矩阵的一部分,它与向上向量不同(但是你定义它).

因此,如果我将向上向量定义为单位 y 向量,其中 y 轴指向 phone 的顶部,我必须将其写为 (-1, 0, 0)在 ARKit space 中。然后简单地将这个矢量(稍微修改......见下文)乘以相机的变换就会给我正在寻找的 "up vector" 。下面是在 ARSessionDelegate 回调中使用此计算的示例。

func session(_ session: ARSession, didUpdate frame: ARFrame) {
    // the unit y vector is appended with an extra element
    // for multiplying with the 4x4 transform matrix
    let unitYVector = float4(-1, 0, 0, 1)
    let upVectorH = frame.camera.transform * unitYVector
    // drop the 4th element
    let upVector = SCNVector3(upVectorH.x, upVectorH.y, upVectorH.z)
}

如果您使用 ARKit 的水平方向,则可以使用 let unitYVector = float4(0, 1, 0, 1)

您也可以通过将单位向量 (0, 0, 1, 1) 乘以得到 "direction vector"(指向 phone 的前面)相机变换。