swift - 使用ARAnchor插入节点和直接插入节点有什么区别?

标签 swift augmented-reality arkit

在 ARKit 中,我发现了 2 种在 hitTest 后插入节点的方法

  • 插入一个 ARAnchor 然后在 renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 中创建节点
     let anchor = ARAnchor(transform:hit.worldTransform)
     sceneView.session.add(anchor:anchor)
    
  • 直接插入节点
     node.position = SCNVector3(hit.worldTransform.columns.3.x, hit.worldTransform.columns.3.y, hit.worldTransform.columns.3.z)
     sceneView.scene.rootNode.addChildNode(node)
    

  • 两者都希望为我工作,但为什么会这样或那样呢?

    最佳答案

    更新:从 iOS 11.3(又名“ARKit 1.5”)开始,添加 ARAnchor 之间存在差异。到 session (然后通过 ARSCNViewDelegate 回调将 SceneKit 内容与其相关联)并将内容放置在 SceneKit 空间中。

    当您向 session 添加 anchor 时,您是在告诉 ARKit 世界空间中的某个点与您的应用程序相关。然后,ARKit 可以做一些额外的工作,以确保其世界坐标空间与现实世界准确对齐,至少在该点附近。

    因此,如果您试图使虚拟内容看起来“附加”到某些现实世界的兴趣点,例如将对象放在 table 或墙上,那么由于世界跟踪不准确,您应该看到更少的“漂移”,如果您给该对象是一个 anchor ,而不是将其放置在 SceneKit 空间中。如果该对象从一个静态位置移动到另一个位置,您将需要删除原始 anchor ,然后在新位置添加一个。

    此外,在 iOS 11.3 中,您可以 opt in到“重新定位”,这是一个帮助 ARKit 在 session 中断(通过电话、切换应用程序等)后恢复 session 的过程。该 session 在试图弄清楚如何将您之前所在的位置映射到您现在的位置时仍然有效,这可能会导致一旦重新定位成功, anchor 的世界空间位置就会发生变化。

    (另一方面,如果你只是制作漂浮在空中的太空入侵者,完美匹配世界空间并不重要,因此你不会真正看到基于 anchor 和非基于 anchor 的区别定位。)

    请参阅 Apple 的 Handling 3D Interaction and UI Controls in Augmented Reality 中有关“使用 anchor 提高虚拟对象跟踪质量”的相关内容。文章/示例代码。

    这个答案的其余部分在历史上仍然与 iOS 11.0-11.2.5 相关并解释了一些上下文,所以我将把它留在下面......

    首先考虑使用 ARAnchor没有 SceneKit。

  • 如果您使用的是 ARSKView ,您需要一种方法来引用 3D(真实世界)空间中的位置/方向,因为 SpriteKit 不是 3D。您需要 ARAnchor跟踪 3D 中的位置,以便将它们映射到 2D。
  • 如果您使用 Metal(或 GL,出于某种奇怪的原因)构建自己的引擎……那不是 3D 场景描述 API — 它是 GPU 编程 API — 所以它并没有真正的世界空间概念。您可以使用 ARAnchor作为 ARKit 的世界空间概念与您构建的任何内容之间的桥梁。

  • 所以在某些情况下你需要 ARAnchor因为这是引用 3D 位置的唯一合理方式。 (当然,如果你使用平面检测,你需要 ARPlaneAnchor 因为 ARKit 实际上会相对于场景空间移动它们,因为它改进了对平面位置的估计。)

    ARSCNView ,SceneKit 已经有一个 3D 世界坐标空间,而 ARKit 会完成所有工作,使该空间与 ARKit 映射出的真实世界空间相匹配。所以,给定一个 float4x4描述世界空间中位置(和方向等)的变换,您可以:
  • 创建 ARAnchor ,将其添加到 session 中,并回复 ARSCNViewDelegate为每个 anchor 提供 SceneKit 内容的回调,ARKit 将为您添加并在场景中定位。
  • 创建 SCNNode ,设置其simdTransform ,并将其添加为场景 rootNode 的子项.

  • 只要你有运行 ARSession ,这两种方法之间没有区别 - 它们是说同一件事的等效方式。所以如果你喜欢用 SceneKit 的方式做事,那没有什么错。 (如果需要,您甚至可以使用 SCNVector3SCNMatrix4 代替 SIMD 类型,但如果您还从 ARKit API 获取 SIMD 类型,则必须来回转换。)

    这些方法的唯一不同之处在于 session 重置时。如果世界跟踪失败,您将恢复中断的 session ,和/或
    当您重新开始一个 session 时,“世界空间”可能不再像在场景中放置内容时那样与现实世界对齐。

    在这种情况下,您可以让 ARKit 从 session 中删除 anchor — 参见 run(_:options:) 方法和 ARSession.RunOptions . (是的,所有这些,因为在这一点上你不能再相信它们中的任何一个是有效的。)如果你使用 anchor 和委托(delegate)回调将内容放置在场景中,ARKit 将核对所有内容。 (您会收到被删除的委托(delegate)回调。)如果您使用 SceneKit API 放置内容,它会留在场景中(但很可能是在错误的位置)。

    因此,使用哪种取决于您希望如何处理 session 失败和中断(除此之外没有真正的区别)。

    关于swift - 使用ARAnchor插入节点和直接插入节点有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45155379/

    相关文章:

    iphone - 在游戏中调用 addObject 时出现 IOS 8 XCode 6 beta 4 异常

    ios - 如何在 Xcode 的 UI 测试中检查是否存在从网络显示的静态文本?

    swift - Reality Composer 默认 anchor

    swift - 如何将Blender制作的动画加载到ARKit?

    c# - CGRectMake。在 Swift 中不可用

    ios - 我怎样才能在 Swift 中展开这个可选的,更优雅一点?

    ios - SWIFT:尝试使用 objective c 类的委托(delegate)方法

    ios - SceneKit 和 ARKit – 柔和阴影或模糊阴影

    ios - GKAgent 不会更新 ARKit/SCNScene/GamplayKit 游戏中团队中注册为实体的 SCNNode 的位置

    ios - 使arkit相机垂直而不是水平