Hit testing in SceneKit

To find a 3D node pointed to by the user in SceneKit, add a tap gesture recogniser in ViewDidLoad()


  let fingerTap = UITapGestureRecognizer(target: self, action: "handleTap:")
  self.view.addGestureRecognizer(fingerTap)

 

And here’s a simple handler:


func handleTap(sender: UIGestureRecognizer)
{
    let p = sender.locationInView(self.sceneView)

    let hitResults = self.sceneView.hitTest(p, options: nil)

    if let results = hitResults {
        if (results.count > 0) {
            let result: SCNHitTestResult = results[0] as! SCNHitTestResult
             println("Hit \(result)")
        }

     }
}

 

Using SceneKit with animated Collada file

I recently needed to load a Collada file into SceneKit and have a short animation play once as soon as the file was loaded.

The Collada file with animation had to be exported from Maya and the initial loading and playing was very straightforward.


func sceneSetup() {
    let scene = SCNScene(named: "Scenes.scnassets/test.dae")
    sceneView.scene = scene
    sceneView.autoenablesDefaultLighting = true
}

However, the animation looped continually.

I not sure this is the best fix but iterating through all possible node animations and setting the repeatCount to 1 fixed the problem.


func sceneSetup() {
    let scene = SCNScene(named: "Scenes.scnassets/test.dae")

    //Get all the child nodes
    let children = scene?.rootNode.childNodes
    
    //Initialise the count of child nodes to zero
    var childCount = 0

    //Iterate through the child nodes
    if let theChildren = children {
        for child in theChildren {
            let keys = child.animationKeys() //get all the animation keys

            //Iterate through the keys and get each animation
            if let theKeys = keys {
                for key in theKeys {
                    let animation = child.animationForKey(key as! String)
                    //Set the repeatCount to 1
                    animation.repeatCount = 1

                    //Write the new animation back
                    scene?.rootNode.childNodes[childCount].removeAnimationForKey(key as! String)
                    scene?.rootNode.childNodes[childCount].addAnimation(animation, forKey: key as! String)
                }
            }
            //Increment the childCount
            childCount++
         }
     }
     sceneView.scene = scene
     sceneView.autoenablesDefaultLighting = true
}