为什么 ARFaceAnchor 有负 Z 位置?
Why does ARFaceAnchor have negative Z position?
我正在使用 ARKit 的 ARFaceTrackingConfiguration
与 ARConfiguration.WorldAlignment.camera
对齐,但我发现文档(貌似)没有反映现实;
根据下面的文档摘录,我希望面部锚点的 transform
是用右手坐标系表示的。但是,当我尝试移动头部时,我注意到面部锚点的 Z 坐标始终为负(即 faceAnchor.transform.columns.3.z < 0
)。请注意,在 X 和 Y 方向上移动头部对应于预期结果(与 Z 坐标不同)。
Camera alignment defines a coordinate system based on the native sensor orientation of the device camera. Relative to a AVCaptureVideoOrientation.landscapeRight
-oriented camera image, the x-axis points to the right, the y-axis points up, and the z-axis points out the front of the device (toward the user).
我希望 transform
按照文档的方式运行,即面锚的 Z 坐标应该是正的,因为文档说“z 轴指向设备(朝向用户)”。到目前为止,Z 轴似乎指向设备的 back…
我是不是遗漏了什么明显的东西?
我尝试通过以下代码修复旋转,但我不确定修复此问题的方法是否正确:
// Repair rotation
let oldFaceRotation = simd_quatf(face.transform) // get quaternion from
let repairedFaceRotation = simd_quatf(ix: oldFaceRotation.axis.y, iy: oldFaceRotation.axis.x, iz: -oldFaceRotation.axis.z, r: oldFaceRotation.real)
// Repair translation
var repairedPosition = face.transform.columns.3
repairedPosition.z *= -1
// Combine
var correctedFaceTransform = float4x4(repairedFaceRotation)
correctedFaceTransform.columns.3 = repairedPosition
好像很明显:
当 ARSession 为 运行 且 ARCamera 开始跟踪环境时,它会将 WorldOriginAxis
放在你的脸前 在 (x: 0, y: 0, z: 0)
。只需使用以下方法检查它:
sceneView.debugOptions = [.showWorldOrigin]
所以你的脸的位置必须在世界坐标positive part of Z axis
处。
Thus, ARFaceAnchor
will be placed at positive Z-axis direction, as well.
当您使用 ARFaceTrackingConfiguration
与 ARWorldTrackingConfiguration
时,有两件事需要考虑:
Rear Camera沿负Z轴向物体移动(正X轴在右边) .
前置摄像头沿正Z轴朝向面部移动(正X轴在左侧) .
Hence, when you are "looking" through TrueDepth Camera, a 4x4 Matrix
is mirrored.
虽然我仍然不知道为什么面部锚点的行为与文档中描述的不一样,但我至少可以回答如何将其左手系统修正为Metal 和 SceneKit 友好的右手系统(X 轴向右,Y 轴向上,Z 轴从屏幕朝向用户):
func faceAnchorPoseToRHS(_ mat: float4x4) -> float4x4 {
let correctedPos = float4(x: mat.columns.3.x, y: mat.columns.3.y, z: -mat.columns.3.z, w: 1)
let quat = simd_quatf(mat)
let newQuat = simd_quatf(angle: -quat.angle, axis: float3(quat.axis.x, quat.axis.y, -quat.axis.z))
var newPose = float4x4(newQuat)
newPose.columns.3 = correctedPos
return newPose
}
我正在使用 ARKit 的 ARFaceTrackingConfiguration
与 ARConfiguration.WorldAlignment.camera
对齐,但我发现文档(貌似)没有反映现实;
根据下面的文档摘录,我希望面部锚点的 transform
是用右手坐标系表示的。但是,当我尝试移动头部时,我注意到面部锚点的 Z 坐标始终为负(即 faceAnchor.transform.columns.3.z < 0
)。请注意,在 X 和 Y 方向上移动头部对应于预期结果(与 Z 坐标不同)。
Camera alignment defines a coordinate system based on the native sensor orientation of the device camera. Relative to a
AVCaptureVideoOrientation.landscapeRight
-oriented camera image, the x-axis points to the right, the y-axis points up, and the z-axis points out the front of the device (toward the user).
我希望 transform
按照文档的方式运行,即面锚的 Z 坐标应该是正的,因为文档说“z 轴指向设备(朝向用户)”。到目前为止,Z 轴似乎指向设备的 back…
我是不是遗漏了什么明显的东西?
我尝试通过以下代码修复旋转,但我不确定修复此问题的方法是否正确:
// Repair rotation
let oldFaceRotation = simd_quatf(face.transform) // get quaternion from
let repairedFaceRotation = simd_quatf(ix: oldFaceRotation.axis.y, iy: oldFaceRotation.axis.x, iz: -oldFaceRotation.axis.z, r: oldFaceRotation.real)
// Repair translation
var repairedPosition = face.transform.columns.3
repairedPosition.z *= -1
// Combine
var correctedFaceTransform = float4x4(repairedFaceRotation)
correctedFaceTransform.columns.3 = repairedPosition
好像很明显:
当 ARSession 为 运行 且 ARCamera 开始跟踪环境时,它会将 WorldOriginAxis
放在你的脸前 在 (x: 0, y: 0, z: 0)
。只需使用以下方法检查它:
sceneView.debugOptions = [.showWorldOrigin]
所以你的脸的位置必须在世界坐标positive part of Z axis
处。
Thus,
ARFaceAnchor
will be placed at positive Z-axis direction, as well.
当您使用 ARFaceTrackingConfiguration
与 ARWorldTrackingConfiguration
时,有两件事需要考虑:
Rear Camera沿负Z轴向物体移动(正X轴在右边) .
前置摄像头沿正Z轴朝向面部移动(正X轴在左侧) .
Hence, when you are "looking" through TrueDepth Camera, a
4x4 Matrix
is mirrored.
虽然我仍然不知道为什么面部锚点的行为与文档中描述的不一样,但我至少可以回答如何将其左手系统修正为Metal 和 SceneKit 友好的右手系统(X 轴向右,Y 轴向上,Z 轴从屏幕朝向用户):
func faceAnchorPoseToRHS(_ mat: float4x4) -> float4x4 {
let correctedPos = float4(x: mat.columns.3.x, y: mat.columns.3.y, z: -mat.columns.3.z, w: 1)
let quat = simd_quatf(mat)
let newQuat = simd_quatf(angle: -quat.angle, axis: float3(quat.axis.x, quat.axis.y, -quat.axis.z))
var newPose = float4x4(newQuat)
newPose.columns.3 = correctedPos
return newPose
}