ARFaceTrackingConfiguration下前置True Depth相机是否支持射线检测?
前置True Depth相机在ARFaceTrackingConfiguration下的射线检测问题解答
核心结论:前置True Depth相机在ARFaceTrackingConfiguration模式下不支持你当前使用的ARRaycastQuery射线检测,原因和替代方案如下:
为什么现有代码无法工作
ARFaceTrackingConfiguration的核心是面部追踪,它的会话逻辑和后置相机的ARWorldTrackingConfiguration完全不同:
- 后置World模式会持续重建环境平面、追踪空间锚点,
raycast依赖这些环境数据(比如你指定的.estimatedPlane)返回结果; - 前置Face模式仅维护面部的3D Mesh数据和
ARFaceAnchor锚点,不会生成任何环境平面数据,所以基于.estimatedPlane的射线检测自然返回空数组。
True Depth相机的深度数据确实存在,但仅围绕追踪到的面部,不会扩展到环境空间。
实现3D两点距离的替代方案
你的目标是获取3D空间中两点距离,可基于ARFaceAnchor的面部Mesh数据实现自定义射线检测,或直接利用面部顶点坐标计算:
方案1:自定义射线与面部Mesh的相交检测
通过遍历ARFaceAnchor提供的面部三角形Mesh,实现射线与三角形的相交计算(比如经典的Möller–Trumbore算法),得到交点后即可计算距离。示例代码如下:
// 在ARSCNViewDelegate方法中获取面部追踪数据 func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let faceAnchor = anchor as? ARFaceAnchor else { return } // 将屏幕中心转换为3D射线 let screenCenter = sceneView.center let nearPoint = sceneView.unprojectPoint(SCNVector3(screenCenter.x, screenCenter.y, 0)) let farPoint = sceneView.unprojectPoint(SCNVector3(screenCenter.x, screenCenter.y, 1)) let rayDirection = (farPoint - nearPoint).normalized() // 遍历面部Mesh的三角形,检测射线交点 let geometry = faceAnchor.geometry let vertices = geometry.vertices let indices = geometry.triangleIndices for i in stride(from: 0, to: indices.count, by: 3) { let v1 = vertices[Int(indices[i])] let v2 = vertices[Int(indices[i+1])] let v3 = vertices[Int(indices[i+2])] if let intersectionPoint = rayIntersectsTriangle(origin: nearPoint, direction: rayDirection, v1: v1, v2: v2, v3: v3) { // 示例:计算交点到面部原点的距离 let distance = intersectionPoint.distance(to: SCNVector3Zero) print("3D距离:\(distance)米") break } } } // 辅助工具方法 extension SCNVector3 { func normalized() -> SCNVector3 { let length = sqrt(x*x + y*y + z*z) return SCNVector3(x/length, y/length, z/length) } func distance(to vector: SCNVector3) -> Float { let dx = x - vector.x let dy = y - vector.y let dz = z - vector.z return sqrt(dx*dx + dy*dy + dz*dz) } static func -(left: SCNVector3, right: SCNVector3) -> SCNVector3 { return SCNVector3(left.x - right.x, left.y - right.y, left.z - right.z) } static func +(left: SCNVector3, right: SCNVector3) -> SCNVector3 { return SCNVector3(left.x + right.x, left.y + right.y, left.z + right.z) } static func *(left: SCNVector3, right: Float) -> SCNVector3 { return SCNVector3(left.x * right, left.y * right, left.z * right) } func cross(_ vector: SCNVector3) -> SCNVector3 { return SCNVector3( y * vector.z - z * vector.y, z * vector.x - x * vector.z, x * vector.y - y * vector.x ) } func dot(_ vector: SCNVector3) -> Float { return x * vector.x + y * vector.y + z * vector.z } } // Möller–Trumbore射线三角形相交算法 func rayIntersectsTriangle(origin: SCNVector3, direction: SCNVector3, v1: SCNVector3, v2: SCNVector3, v3: SCNVector3) -> SCNVector3? { let edge1 = v2 - v1 let edge2 = v3 - v1 let h = direction.cross(edge2) let a = edge1.dot(h) if a > -0.00001 && a < 0.00001 { return nil // 射线与平面平行 } let f = 1/a let s = origin - v1 let u = f * s.dot(h) if u < 0 || u > 1 { return nil } let q = s.cross(edge1) let v = f * direction.dot(q) if v < 0 || u + v > 1 { return nil } let t = f * edge2.dot(q) if t > 0.00001 { return origin + direction * t } else { return nil } }
方案2:直接使用面部顶点坐标计算
如果你的两个目标点都是面部上的特征点(比如鼻尖、眼角),可以直接通过ARFaceAnchor的blendShapes或Mesh顶点索引获取对应3D坐标,再计算两点距离,无需射线检测。
内容的提问来源于stack exchange,提问作者K_C
相关产品推荐
相关产品推荐

