在 ARKit 中获取相机的向上矢量
Get the up vector of the camera in ARKit
我试图在ARKit中获取构成平截头体边界的四个向量,我想出的解决方案如下:
- 找到相机的视角
- 然后找到相机的方向和向上向量
- 使用这些信息,使用叉积和旋转找到四个向量
这可能是一种草率的做法,但它是迄今为止我得到的最好的方法。
我能够从 ARCamera.intrinsics
和 ARCamera.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 的前面)相机变换。
我试图在ARKit中获取构成平截头体边界的四个向量,我想出的解决方案如下:
- 找到相机的视角
- 然后找到相机的方向和向上向量
- 使用这些信息,使用叉积和旋转找到四个向量
这可能是一种草率的做法,但它是迄今为止我得到的最好的方法。
我能够从 ARCamera.intrinsics
和 ARCamera.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 的前面)相机变换。