6

I have a simple question. If I wanted to start a game and place the board right in front of me:

gameBoard!.position = SCNVector3(0, 0, -0.6)

This works until I leave the game and come back again. Can I show the game board in exact same position in front of camera or 0.6m in front of me? I might have physically moved to another position.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
Lim Thye Chean
  • 8,704
  • 9
  • 49
  • 88
  • You need to place the gameBoard 0.6m from where the camera is looking. Either reset the camera, or calculate the position of the board based on the camera's position. – allenh Jul 14 '17 at 14:41
  • @AllenHumphreys My app freezes when this happens. Have you seen any documentation for this? – Jches Jul 14 '17 at 19:05
  • My comment was based on working with SceneKit, but my assumption is that ARKit has a notion of a camera very similar to SceneKit. – allenh Jul 14 '17 at 19:06
  • @AllenHumphreys can you give me a sample code of how to reset camera or position? – Lim Thye Chean Jul 16 '17 at 09:28

4 Answers4

9

If you want to reset you ARSession, you have to pause, remove all nodes and rerun your session by resetting tracking and removing anchors.

I made a reset button that does it whenever i want to reset:

@IBAction func reset(_ sender: Any) {

    sceneView.session.pause()
    sceneView.scene.rootNode.enumerateChildNodes { (node, stop) in
        node.removeFromParentNode()
    }
    sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}

Or put it in your session was interrupted function!

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
slimboy
  • 1,633
  • 2
  • 22
  • 45
  • This seems to work fine. I put the reset in UIApplicationWillEnterForeground notification though, so every time the user comes back it will reset the game board position. – Lim Thye Chean Jul 20 '17 at 01:59
2

This should be possible using the option resetTracking when you call run on your ARSession again.

Example:

if let configuration = sceneView.session.configuration {
    sceneView.session.run(configuration,
                          options: .resetTracking)
}
Bersaelor
  • 2,517
  • 34
  • 58
1

"This works until I leave the game and come back again."

You can't track camera position in the background. Whenever your app goes to the background and camera turns off, you're losing your position, and sessionWasInterrupted(_:) will be called.

A session is interrupted when it fails to receive camera or motion sensing data. Session interruptions occur whenever camera capture is not available—for example, when your app is in the background or there are multiple foreground apps—or when the device is too busy to process motion sensor data.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Vasilii Muravev
  • 3,063
  • 17
  • 45
1

To reset ARSession in ARKit framework is quite easy:

class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

    @IBOutlet var arView: ARSCNView!
    @IBOutlet weak var sessionInfoLabel: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = [.horizontal, .vertical]
        arView.session.run(configuration)
        arView.session.delegate = self
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        arView.session.pause()
    }
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { 
            return 
        }
        let plane = Plane(anchor: planeAnchor, in: arView)
        node.addChildNode(plane)
    }
    func sessionInterruptionEnded(_ session: ARSession) {
        resetSessionTracking()
        sessionInfoLabel.text = "ARSession's interruption has ended" 
    }
    private func resetSessionTracking() {
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.vertical, .horizontal]
        arView.scene.rootNode.enumerateChildNodes { (childNode, _) in
            childNode.removeFromParentNode()
        }
        arView.session.run(config, options: [.removeExistingAnchors, 
                                             .resetTracking, ])
    }
}

Hope this helps.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220