PruitIgoe
PruitIgoe

Reputation: 6384

ARKit – Add a "SCNNode" to an "ARAnchor"

I'm not sure I am approaching this correctly. I have a long rectangular box that I want to add -1.5 from the camera when the app starts up. But I want it to be stationary, like the ship that comes default in an ARKit project. But whenever I add it, the object stays relative (distance wise) to the camera. i.e - move towards it, it moves back, move back, it moves forward.

I though dropping an anchor on the scene would resolve this but I am still getting the same affect. Here is my code. Any help would be appreciated:

override func viewDidLoad() {
    super.viewDidLoad()

    // Set the view's delegate
    sceneView.delegate = self

    // Show statistics such as fps and timing information
    //sceneView.showsStatistics = true

    // Create a new scene
    let scene = SCNScene()//

    // Set the scene to the view
    sceneView.scene = scene 
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARWorldTrackingConfiguration()

    //configuration.planeDetection = .horizontal

    // Run the view's session
    sceneView.session.run(configuration)

    print(#function, sceneView.session.currentFrame)
}

// MARK: - SCNSceneRendererDelegate
    func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
        print(#function, sceneView.session.currentFrame)

        if !hasPortalAnchor {

            //add anchor - this may take a second as the current frames are initially nil
            if let currentFrame = sceneView.session.currentFrame {
                var translation = matrix_identity_float4x4
                translation.columns.3.z = -1.3
                let transform = simd_mul(currentFrame.camera.transform, translation)

                if (arrAnchors.count < 1) {
                let portalAnchor = ARAnchor(transform: transform)
                sceneView.session.add(anchor: portalAnchor)
                arrAnchors.append(portalAnchor)
                print(arrAnchors)
                }
            }

        } else {
            hasPortalAnchor = true
        }          
    }

//this function gets called whenever we add an anchor to our scene
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {

    let portalScene = SCNScene(named: "art.scnassets/portal.scn")! 
    return portalScene.rootNode.childNode(withName: "portal", recursively: true)   
}

Upvotes: 2

Views: 1196

Answers (1)

Jordan
Jordan

Reputation: 491

Are you deliberately using the renderer(_:) function? If not then you can just use the following viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()

    sceneView.delegate = self

    let scene = SCNScene(named: "art.scnassets/portal.scn")!

    sceneView.scene = scene

}

This will replace the default rocket that appears on startup, with your portal scene. (Note that the scene may move around if tracking hasn't been established. For instance if the light is low, or if you are in an environment without many features (a blank or repetitive wall for instance)).

Also it looks like you're not actually setting hasPortalAnchor to true? Is it being set somewhere else?

Upvotes: 0

Related Questions