我正在使用Arkit和scenekit Frameworks的应用程序。在我的应用程序中,我启用了表面检测(我遵循了Apple提供的对象样本的放置)。如何找到是否不再可用的表面?也就是说,最初,只有用户在文献中检测到表面,我才允许他放置3D对象。
但是,如果用户迅速移动或聚焦在某个地方,则检测到的表面积将丢失。在这种情况下,如果用户试图放置另一个对象,我不应该允许他放置它,直到他再次扫描地板并纠正表面为止。
是否有任何代表可以让我们知道检测到的表面不再可用?
您可以使用委托功能。代表是ARSCNViewDelegate
它具有renderer(_:didRemove:for:)
的函数,该函数在删除了杂物时会发射。当表面卸下时,您可以使用此功能执行一些操作。
arscnviewdelegate链接
有两种"丢失"表面的方法,因此有多种方法可以解决此类问题。
正如其他答案中指出的那样,当从AR会话中删除锚点时,有一种ARSCNViewDelegate
方法。但是,ARKIT在运行会话期间不会删除平面锚定 - 一旦检测到飞机,它就会假设飞机始终存在。因此,仅当以下情况下,该方法才会被调用:
- 您将飞机直接传递到
session.remove(anchor:)
或
直接卸下锚 - 您通过使用
.removeExistingAnchors
选项再次运行会话。
我不确定前者是个好主意,但是后者很重要,因此您可能希望您的代表能够很好地处理它。
您也可以通过使其流失视图来"丢失"表面 - 例如,ARKIT检测到表,然后用户转身,因此相机不再指向或附近桌子附近。
arkit本身并没有为解决此问题提供任何帮助。不过,它为您自己完成数学所需的所有信息。您可以获得飞机锚的位置,方向和大小,因此您可以计算其四个角点。而且您可以获得相机的投影矩阵,因此您可以检查是否有任何观点。
由于您已经在使用SceneKit,因此也有一些方法可以让Scenekit为您进行数学...向后工作:
- SceneKit为您提供了
isNode(_:insideFrustumOf:)
测试,因此,如果您有一个SCNNode
的边界框匹配飞机锚的范围,则可以与相机(view.pointOfView
)一起传递,以找出该节点是否可见。 - 要获取一个节点的边界框匹配平面锚,请实现
ARSCNViewDelegate
didAdd
和didUpdate
回调以创建/更新SCNPlane
,其位置和尺寸与ARPlaneAnchor
的中心及其范围匹配。(不要忘记将飞机侧面翻转,因为默认情况下SCNPlane
垂直面向。) - 如果您不希望AR视图中可见的飞机,请将其材料设置为透明。