在ARKit中,我找到了两种在hitTest之后插入节点的方法
插入ARAnchor然后在渲染器中创建节点(_ renderer:SCNSceneRenderer,nodeFor anchor:ARAnchor) - > SCNNode? P>
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)
两者都看起来适合我,但为什么这样或那样?
答案 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方式做事,那就没什么不对。 (如果需要,您甚至可以使用SCNVector3
和SCNMatrix4
代替SIMD类型,但如果您还从ARKit API获取SIMD类型,则必须来回转换。)
这些方法的不同之处在于会话重置时。如果世界跟踪失败,则恢复中断的会话,和/或 你重新开始一个会话,“世界空间”可能不再与现实世界对齐,就像你在场景中放置内容时一样。
在这种情况下,您可以让ARKit从会话中删除锚点 - 请参阅run(_:options:)
方法和ARSession.RunOptions
。 (是的,所有这些,因为在这一点上你不能相信它们中的任何一个都是有效的。)如果你使用锚点和委托回调在场景中放置内容,ARKit将核对所有内容。 (你得到它被删除的委托回调。)如果你用SceneKit API放置内容,它会留在场景中(但很可能在错误的地方)。
那么,使用哪种方式取决于你想如何处理会话失败和中断(除此之外没有真正的区别)。
答案 1 :(得分:0)
SCNVector3只是“三分量矢量的表示”。 SCNVector3 docs
使用ARAnchor时,您可以访问三分量矢量,但您也可以“跟踪相对于相机的真实或虚拟物体的位置和方向”ARAnchor docs。这就是你使用会话来添加锚而不是使用场景的原因。
查看文档,您可以看到API的差异:)
希望它有所帮助。