ARKit:渲染器(didAdd:)和渲染器(nodeFor:)独占

ARKit: Are renderer(didAdd: ) and renderer(nodeFor: ) exclusive

完全依赖ARKit自动平面检测是我不想做的事情,因为检测表面需要时间,然后现实生活中的表面应该有足够的纹理,因此我需要想办法提供一个选项,如果我愿意,我应该能够通过点击一个按钮来随意添加锚点。

这就是 renderer(nodeFor: ) 派上用场的地方。只需点击按钮添加锚点,使用 hitTest 确定锚点的位置,然后使用 nodeFor: 方法添加节点。

然而,在其他情况下,当我不想手动点击按钮时,renderer(didAdd: ) 应该可以。我制作了一个共享对象,通过它我可以确定平面检测是否需要“自动”或“手动”。如果是自动的,planeDetection 将设置为 .horizontal,而如果是手动的,planeDetection 将设置为 []

问题在于测试委托下的两种方法中的任何一种似乎都有效。 有什么方法可以实现我想要的吗? 有一个开关,我可以使用它来切换是想要自动平面检测还是想要添加锚点,然后添加平面。我很想有这两种选择。

是否可以使用两个不同的代表来实现它,只是一个想法......在那种情况下它会如何工作。指针将不胜感激。

是的,renderer(didAdd: )renderer(nodeFor: )是互斥的。根据文档,如果我们想在场景中实现我们自己的添加节点的方法,我们可以继续使用 renderer(nodeFor: ),或者我们可以 而不是 选择 ARKit 来做我们使用 renderer(didAdd: ).

也是一样

管理这两种情况的方法,即。 planeDetection = [] 时手动添加节点;当 planeDetection = .horizontal 时自动添加节点可以通过使用 renderer(nodeFor: ) 方法本身来实现。不需要renderer(didAdd: )

renderer(nodeFor: ) 内,如果 planeDetection = .horizo​​ntal,anchor 可以投射为 ARPlaneAnchor,其 centerextent 可用于更新添加的节点。

如:

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    if let planeAnchor = anchor as? ARPlaneAnchor {
        let node = SCNNode()
        let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x),
                             height: CGFloat(planeAnchor.extent.z))

        let planeNode = SCNNode(geometry: plane)
        planeNode.name = "anchorPlane"
        planeNode.simdPosition = float3(planeAnchor.center.x, 0, planeAnchor.center.z)
        node.addChildNode(planeNode)
        return node

同时,可以为planeDetection = []附加一个条件,当anchor不能被投射为ARPlaneAnchor时,节点下的几何图形可以根据需要指定大小。

    } else {
        let node = SCNNode()
        let plane = SCNPlane(width: 0.5, height: 0.5)
        plane.firstMaterial?.diffuse.contents = UIColor.white
        let planeNode = SCNNode(geometry: plane)
        node.addChildNode(node)
        return node
    }
}