将 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”

在 SpriteKit 项目中包含一个 UIKit 小游戏

ObservedObject 更改时的通知

带有 Skview 的 ViewController - SpriteKit SKScene

php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy

php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy