使用ARAnchor插入节点并直接插入节点有什么区别?

时间:2017-07-18 00:01:05

标签: swift augmented-reality arkit

在ARKit中,我找到了两种在hitTest之后插入节点的方法

  1. 插入ARAnchor然后在渲染器中创建节点(_ renderer:SCNSceneRenderer,nodeFor anchor:ARAnchor) - > SCNNode?

    let anchor = ARAnchor(transform:hit.worldTransform)
    sceneView.session.add(anchor:anchor)
    
  2. 直接插入节点

    node.position = SCNVector3(hit.worldTransform.columns.3.x, hit.worldTransform.columns.3.y, hit.worldTransform.columns.3.z)
    sceneView.scene.rootNode.addChildNode(node)
    
  3. 两者都看起来适合我,但为什么这样或那样?

2 个答案:

答案 0 :(得分:43)

更新:从iOS 11.3(又名“ARKit 1.5”)开始, 在向会话中添加ARAnchor之间存在差异(然后关联) SceneKit内容通过ARSCNViewDelegate回调),只是将内容放在SceneKit空间中。

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

所以,如果你试图让虚拟内容“附加”到一些真实世界的兴趣点,比如把一个物体放在桌子或墙上,你应该看到由于世界跟踪不准确而导致的“漂移”减少如果你给该对象一个锚点,而不是只将它放在SceneKit空间中。如果该对象从一个静态位置移动到另一个静态位置,您将需要删除原始锚点并在之后的新位置添加一个。

此外,在iOS 11.3中,您可以opt in进行“重新本地化”,这个过程可以帮助ARKit在中断(通过电话,切换应用等)后恢复会话。会议仍然有效,同时它正试图弄清楚如何将你以前的位置映射到现在的位置,这可能会导致锚点的世界空间位置在重新定位成功后发生变化。

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

请参阅Apple的Handling 3D Interaction and UI Controls in Augmented Reality文章/示例代码中的“使用锚点来提高虚拟对象周围的跟踪质量”。

这个答案的其余部分在历史上仍与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,将其添加到会话中,并回复ARSCNViewDelegate回调,为每个锚提供SceneKit内容,ARKit将为您添加并在场景中定位。
  • 创建SCNNode,设置其simdTransform,并将其添加为场景rootNode的子项。

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

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

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

那么,使用哪种方式取决于你想如何处理会话失败和中断(除此之外没有真正的区别)。

答案 1 :(得分:0)

SCNVector3只是“三分量矢量的表示”。 SCNVector3 docs

使用ARAnchor时,您可以访问三分量矢量,但您也可以“跟踪相对于相机的真实或虚拟物体的位置和方向”ARAnchor docs。这就是你使用会话来添加锚而不是使用场景的原因。

查看文档,您可以看到API的差异:)

希望它有所帮助。