ARKit 在参考图像消失时删除一个节点

ARKit removes a node when Reference Image disappeared

我正在构建 AR 扫描仪应用程序,用户可以在其中扫描不同的图像并为此获得奖励。

当他们将相机对准某个特定图像时 - 我将 SCNNode 放在该图像的顶部,在他们从该图像中移除相机后 - SCNNode 被解雇。

但是当图像消失并且相机停留在同一位置时 SCNNode 没有被关闭。

如何让它与参考图像一起消失?

我在这里研究了很多关于 SO 的其他答案,但它们对我没有帮助

这是我添加和删除 SCNNode 的代码:

extension ARScannerScreenViewController: ARSCNViewDelegate {

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    DispatchQueue.main.async { self.instructionLabel.isHidden = true }
    if let imageAnchor = anchor as? ARImageAnchor {
        handleFoundImage(imageAnchor, node)
        imageAncors.append(imageAnchor)
        trackedImages.append(node)
    } else if let objectAnchor = anchor as? ARObjectAnchor {
        handleFoundObject(objectAnchor, node)
    }
}

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let pointOfView = sceneView.pointOfView else { return }
    for (index, item) in trackedImages.enumerated() {
        if !(sceneView.isNode(item, insideFrustumOf: pointOfView)) {
            self.sceneView.session.remove(anchor: imageAncors[index])
        }
    }
}

private func handleFoundImage(_ imageAnchor: ARImageAnchor, _ node: SCNNode) {
    let name = imageAnchor.referenceImage.name!
    print("you found a \(name) image")

    let size = imageAnchor.referenceImage.physicalSize
    if let imageNode = showImage(size: size) {
        node.addChildNode(imageNode)
        node.opacity = 1
    }
}

private func showImage(size: CGSize) -> SCNNode? {
    let image = UIImage(named: "InfoImage")
    let imageMaterial = SCNMaterial()
    imageMaterial.diffuse.contents = image

    let imagePlane = SCNPlane(width: size.width, height: size.height)
    imagePlane.materials = [imageMaterial]

    let imageNode = SCNNode(geometry: imagePlane)
    imageNode.eulerAngles.x = -.pi / 2
    return imageNode
}

private func handleFoundObject(_ objectAnchor: ARObjectAnchor, _ node: SCNNode) {
    let name = objectAnchor.referenceObject.name!
    print("You found a \(name) object")
}

}

我也尝试使用 ARSession 使其工作,但我什至无法打印:

func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
    for anchor in anchors {
        for myAnchor in imageAncors {
            if let imageAnchor = anchor as? ARImageAnchor, imageAnchor == myAnchor {
                if !imageAnchor.isTracked {
                    print("Not tracked")
                } else {
                    print("tracked")
                }
            }
        }
    }
}

使用nodeForAnchor加载你的节点,所以当锚点消失时,节点也会消失。

您必须使用 ARWorldTrackingConfiguration instead of ARImageTrackingConfiguration。在应用程序中使用这两种配置是非常糟糕的主意,因为每次在它们之间切换时 – 跟踪状态都会重置,您必须从头开始跟踪。

让我们看看 Apple 文档对 ARImageTrackingConfiguration 的描述:

With ARImageTrackingConfiguration, ARKit establishes a 3D space not by tracking the motion of the device relative to the world, but solely by detecting and tracking the motion of known 2D images in view of the camera.

这两个配置之间的基本区别在于 ARAnchors 的行为方式:

  • ARImageTrackingConfiguration 仅当您的参考图像在相机视图中时才允许您获得 ARImageAnchors。因此,如果您看不到参考图像——就没有 ARImageAnchor,因此也就没有 3D 模型(每次您看不到然后再次看到它时,它都会重新设置)。可以同时检测.

  • ARWorldTrackingConfiguration 允许您在 6DoF 中跟踪周围环境并获得 ARImageAnchor, ARObjectAnchor,或 AREnvironmentProbeAnchor。如果你看不到参考图像——没有 ARImageAnchor,但当你再次看到它时,ARImageAnchor 仍然存在。所以没有重置。

结论

ARWorldTrackingConfiguration的计算成本要高得多。但是,此配置不仅允许您执行图像跟踪,还可以执行检测平面的命中测试和光线投射、对象检测以及世界地图的恢复。