Taras Tomchuk
Taras Tomchuk

Reputation: 331

ARKit removes a node when Reference Image disappeared

I'm building AR Scanner application where users are able to scan different images and receive rewards for this.

When they point camera at some specific image - I place SCNNode on top of that image and after they remove camera from that image - SCNNode get's dismissed.

But when image disappears and camera stays at the same position SCNNode didn't get dismissed.

How can I make it disappear together with Reference image disappearance?

I have studied lot's of other answers here, on SO, but they didn't help me

Here's my code for adding and removing SCNNode's:

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")
}

}

I also tried to make it work using ARSession, but I couldn't even get to prints:

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")
                }
            }
        }
    }
}

Upvotes: 1

Views: 1047

Answers (2)

Andy Jazz
Andy Jazz

Reputation: 58093

You have to use ARWorldTrackingConfiguration instead of ARImageTrackingConfiguration. It's quite bad idea to use both configurations in app because each time you switch between them – tracking state is reset and you have to track from scratch.

Let's see what Apple documentation says about 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.

The basic differences between these two configs are about how ARAnchors behave:

  • ARImageTrackingConfiguration allows you get ARImageAnchors only if your reference images is in a Camera View. So if you can't see a reference image – there's no ARImageAnchor, thus there's no a 3D model (it's resetting each time you cannot-see-it-and-then-see-it-again). You can simultaneously detect up to 100 images.

  • ARWorldTrackingConfiguration allows you track a surrounding environment in 6DoF and get ARImageAnchor, ARObjectAnchor, or AREnvironmentProbeAnchor. If you can't see a reference image – there's no ARImageAnchor, but when you see it again ARImageAnchor is still there. So there's no reset.

Conclusion:

ARWorldTrackingConfiguration's cost of computation is much higher. However this configuration allows you perform not only image tracking but also hit-testing and ray-casting for detected planes, object detection, and a restoration of world maps.

Upvotes: 3

Rom4in
Rom4in

Reputation: 562

Use nodeForAnchor to load your nodes, so when the anchors disappear, the nodes will go as well.

Upvotes: 0

Related Questions