我正在使用 ARKit 和 SceneKit 框架开发应用程序。在我的应用程序中,我启用了表面检测(我遵循了 Apple 提供的放置对象示例)。如何确定检测到的表面是否不再可用?也就是说,最初只有当用户在 ARSession 中检测到表面时,我才允许他放置 3D 对象。
但是,如果用户快速移动或专注于某处,检测到的表面积就会丢失。在这种情况下,如果用户试图放置另一个对象,我不应该让他放置它,直到他再次扫描地板并纠正表面。
是否有任何代表可以让我们知道检测到的表面不再可用?
我正在使用 ARKit 和 SceneKit 框架开发应用程序。在我的应用程序中,我启用了表面检测(我遵循了 Apple 提供的放置对象示例)。如何确定检测到的表面是否不再可用?也就是说,最初只有当用户在 ARSession 中检测到表面时,我才允许他放置 3D 对象。
但是,如果用户快速移动或专注于某处,检测到的表面积就会丢失。在这种情况下,如果用户试图放置另一个对象,我不应该让他放置它,直到他再次扫描地板并纠正表面。
是否有任何代表可以让我们知道检测到的表面不再可用?
您可以使用一些委托函数。代表是ARSCNViewDelegate
它有一个功能是renderer(_:didRemove:for:)
在 ARAnchor 被移除时触发。当表面被移除时,您可以使用此功能执行一些操作。
有两种方法可以“丢失”一个表面,因此处理此类问题的方法不止一种。
如另一个答案中所述,ARSCNViewDelegate
当从 AR 会话中删除锚点时,ARKit 会调用一个方法。然而,ARKit 不会在运行会话期间移除平面锚点——一旦检测到平面,它就会假定平面始终存在。因此,只有在以下情况下才会调用该方法:
session.remove(anchor:)
, 或.removeExistingAnchors
选项再次运行会话来重置会话。我不确定前者是否是一个好主意,但后者很重要,因此您可能希望您的代表能够很好地处理它。
您还可以通过让表面离开视野来“丢失”表面——例如,ARKit 检测到一张桌子,然后用户转身,这样相机就不再指向或靠近桌子。
ARKit 本身并没有为您提供处理此问题的任何帮助。不过,它为您提供了自己进行数学计算所需的所有信息。你得到了平面锚的位置、方向和大小,所以你可以计算它的四个角点。你得到相机的投影矩阵,所以你可以检查是否有任何点在视锥体中。
但是,由于您已经在使用 SceneKit,因此还有一些方法可以让 SceneKit 为您做数学计算......向后工作:
isNode(_:insideFrustumOf:)
测试,因此如果您SCNNode
的边界框与平面锚点的范围相匹配,您可以将其与相机 ( view.pointOfView
) 一起传递,以确定节点是否可见。ARSCNViewDelegate
didAdd
和didUpdate
回调以创建/更新SCNPlane
其位置和尺寸与ARPlaneAnchor
的中心和范围匹配的节点。(不要忘记将平面翻转到侧面,因为SCNPlane
默认情况下是垂直方向的。)