1

我正在使用 ARKit 和 SceneKit 框架开发应用程序。在我的应用程序中,我启用了表面检测(我遵循了 Apple 提供的放置对象示例)。如何确定检测到的表面是否不再可用?也就是说,最初只有当用户在 ARSession 中检测到表面时,我才允许他放置 3D 对象。

但是,如果用户快速移动或专注于某处,检测到的表面积就会丢失。在这种情况下,如果用户试图放置另一个对象,我不应该让他放置它,直到他再次扫描地板并纠正表面。

是否有任何代表可以让我们知道检测到的表面不再可用?

4

2 回答 2

3

您可以使用一些委托函数。代表是ARSCNViewDelegate

它有一个功能是renderer(_:didRemove:for:)在 ARAnchor 被移除时触发。当表面被移除时,您可以使用此功能执行一些操作。

ARSCNViewDelegate 链接

于 2017-09-05T09:39:12.877 回答
2

有两种方法可以“丢失”一个表面,因此处理此类问题的方法不止一种。


如另一个答案中所述,ARSCNViewDelegate当从 AR 会话中删除锚点时,ARKit 会调用一个方法。然而,ARKit 不会在运行会话期间移除平面锚点——一旦检测到平面,它就会假定平面始终存在。因此,只有在以下情况下才会调用该方法:

  1. 您可以通过将平面锚直接传递给session.remove(anchor:), 或
  2. 您可以通过使用该.removeExistingAnchors选项再次运行会话来重置会话。

我不确定前者是否是一个好主意,但后者很重要,因此您可能希望您的代表能够很好地处理它。


您还可以通过让表面离开视野来“丢失”表面——例如,ARKit 检测到一张桌子,然后用户转身,这样相机就不再指向或靠近桌子。

ARKit 本身并没有为您提供处理此问题的任何帮助。不过,它为您提供了自己进行数学计算所需的所有信息。你得到了平面锚的位置、方向和大小,所以你可以计算它的四个角点。你得到相机的投影矩阵,所以你可以检查是否有任何点在视锥体中。

但是,由于您已经在使用 SceneKit,因此还有一些方法可以让 SceneKit 为您做数学计算......向后工作:

  1. SceneKit 为您提供了一个isNode(_:insideFrustumOf:)测试,因此如果您SCNNode的边界框与平面锚点的范围相匹配,您可以将其与相机 ( view.pointOfView) 一起传递,以确定节点是否可见。
  2. 要获取其边界框与平面锚点匹配的节点,请实现ARSCNViewDelegate didAdddidUpdate回调以创建/更新SCNPlane其位置和尺寸与ARPlaneAnchor的中心和范围匹配的节点。(不要忘记将平面翻转到侧面,因为SCNPlane默认情况下是垂直方向的。)
  3. 如果您不希望该平面在 AR 视图中可见,请将其材质设置为透明。
于 2017-09-08T16:00:07.750 回答