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

时间:2017-12-08 17:34:47

标签: ios swift camera scenekit 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)
}

我也愿意找到方法找到我想要的四个载体。

2 个答案:

答案 0 :(得分:0)

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

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

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

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

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

答案 1 :(得分:0)

可能是我误解了您要做什么,但我想提供一个替代解决方案(方法和结果与您的答案不同)。

出于我的目的,当电话笔直指向上方时,我将向上矢量定义为(0,1,0)-基本上,我希望笔直指向手机顶部的单位矢量。当手机水平向左时,ARKit将向上向量定义为(0,1,0)-因此y轴指向手机的右侧-可能是因为他们希望AR应用程序更喜欢水平方向。 / p>

camera.transform返回AR会话开始时相机相对于其初始方向的方向。它是一个4x4矩阵-前3x3是旋转矩阵-因此,当您编写cameraTransform.m21等时,您引用的是旋转矩阵的一部分,这与up向量是不同的(但是您定义了它) )。

因此,如果我将向上向量定义为y轴指向手机顶部的单位y-向量,则必须在ARKit空间中将其写为(-1,0,0)。然后,简单地将此向量(稍作修改,请参见下文)乘以相机的变换即可得到我要寻找的“向上向量”。以下是在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)乘以摄像头变换,来进行相同的计算,以获得“方向矢量”(指向手机的正面)。