将 ARFaceAnchor 与 SpriteKit 叠加层对齐
Posted
技术标签:
【中文标题】将 ARFaceAnchor 与 SpriteKit 叠加层对齐【英文标题】:Aligning ARFaceAnchor with SpriteKit overlay 【发布时间】:2019-04-10 01:50:49 【问题描述】:我正在尝试在特定几何点ARFaceGeometry
/ARFaceAnchor
上计算 SpriteKit 覆盖内容位置(不仅仅是覆盖视觉内容)。
我正在使用计算出的世界坐标中的SCNSceneRenderer.projectPoint
,但结果是 y 反转并且未与相机图像对齐:
let vertex4 = vector_float4(0, 0, 0, 1)
let modelMatrix = faceAnchor.transform
let world_vertex4 = simd_mul(modelMatrix, vertex4)
let pt3 = SCNVector3(x: Float(world_vertex4.x),
y: Float(world_vertex4.y),
z: Float(world_vertex4.z))
let sprite_pt = renderer.projectPoint(pt3)
// To visualize sprite_pt
let dot = SKSpriteNode(imageNamed: "dot")
dot.size = CGSize(width: 7, height: 7)
dot.position = CGPoint(x: CGFloat(sprite_pt.x),
y: CGFloat(sprite_pt.y))
overlayScene.addChild(dot)
【问题讨论】:
【参考方案1】:根据我的经验,ARKit 的projectPoint
函数给出的屏幕坐标在绘制到例如CALayer
时可以直接使用。这意味着它们遵循here 中描述的 ios 坐标,其中原点在左上角,y 是倒置的。
SpriteKit 有its own coordinate system:
单位坐标系将原点放置在框架的左下角,将(1,1)放置在框架的右上角。 sprite 的锚点默认为 (0.5,0.5),对应于帧的中心。
最后,SKNodes 被放置在一个 SKScene 中,它的原点位于左下角。您应该确保您的 SKScene 与您的实际视图大小相同,否则原点可能不在视图的左下角,因此您从视图坐标中定位节点的位置可能不正确。 this question 的答案可能会有所帮助,特别是检查视图的 AspectFit 或 AspectFill 以确保您的场景被缩小。
场景的原点位于左下角,根据您的场景大小和缩放比例,它可能会在屏幕外。这是 0,0 所在的位置。因此,您添加的每个孩子都将从那里开始,并根据位置向上和向上工作。 SKSpriteNode 的原点位于中心。
因此,从视图坐标和 SpriteKit 坐标转换的两个基本步骤是 1) 反转 y 轴,使原点位于左下方,以及 2) 确保 SKScene 框架与视图框架匹配。
我可以稍后更全面地测试一下,如果有任何问题,我会进行编辑
【讨论】:
我发布了一个简单的测试用例来演示这个问题:github.com/AnsonT/ARFaceSpriteKitMapping。使用 ProjectPoint 映射到 spritekit 坐标的顶点只是不与图像或场景套件几何图形对齐。非常感谢您查看我的问题。 注意,目标是做正确的变换计算以映射到相机图像,我只是使用 spritekit 进行可视化。 您想要映射到的“相机图像”是什么意思?喜欢实际的ARFrame
?如果您只是使用 SpriteKit 来可视化 projectPoint
的输出,那么您的可视化器的坐标系将与您最终尝试映射到的坐标系不同。
是的,ARFrame,capturedImage。
那么最终你会想要从屏幕坐标转换为 ARFrame 坐标。尝试使用ARFrame's displayTransform function 给出的变换矩阵的逆矩阵。您可能必须首先对 projectPoint
调用返回的坐标进行归一化。【参考方案2】:
找到了使用 camera.projectPoint 而不是 renderer.projectPoint 的转换。
要在 spritekit 上正确缩放点:设置 scaleMode=.aspectFill
我更新了https://github.com/AnsonT/ARFaceSpriteKitMapping 来演示这个。
guard let faceAnchor = anchor as? ARFaceAnchor,
let camera = sceneView.session.currentFrame?.camera,
let sie = overlayScene?.size
else return
let modelMatrix = faceAnchor.transform
let vertices = faceAnchor.geometry.vertices
for vertex in vertices
let vertex4 = vector_float4(vertex.x, vertex.y, vertex.z, 1)
let world_vertex4 = simd_mul(modelMatrix, vertex4)
let world_vector3 = simd_float3(x: world_vertex4.x, y: world_vertex4.y, z: world_vertex4.z)
let pt = camera.projectPoint(world_vector3, orientation: .portrait, viewportSize: size)
let dot = SKSpriteNode(imageNamed: "dot")
dot.size = CGSize(width: 7, height: 7)
dot.position = CGPoint(x: CGFloat(pt.x), y: size.height - CGFloat(pt.y))
overlayScene?.addChild(dot)
【讨论】:
以上是关于将 ARFaceAnchor 与 SpriteKit 叠加层对齐的主要内容,如果未能解决你的问题,请参考以下文章
ARKit 中的 FaceTracking – 如何在屏幕上显示“lookAtPoint”
带有 Skview 的 ViewController - SpriteKit SKScene