1

I am trying to drag a node exactly where my finger is on the screen on the Y-axis. But I don't find any way to do it, here is my current code. Do you have any idea?

var movedObject:SCNNode?

@objc func handlePan(_ recognizer: UIPanGestureRecognizer) {

    if recognizer.state == .began {

        let tapPoint: CGPoint = recognizer.location(in: sceneView)
        let result = sceneView.hitTest(tapPoint, options: nil)
        if result.count == 0 {
            return
        }
        let hitResult: SCNHitTestResult? = result.first
        movedObject = hitResult?.node //.parent?.parent
        } else if recognizer.state == .changed {

        if (movedObject != nil) {
            let tapPoint: CGPoint = recognizer.location(in: sceneView)
            let hitResults = sceneView.hitTest(tapPoint, types: .featurePoint)
            let result: ARHitTestResult? = hitResults.last

            if result?.worldTransform != nil{                      
                let matrix: SCNMatrix4 = SCNMatrix4.init((result?.worldTransform)!)
                let vector: SCNVector3 = SCNVector3Make(matrix.m41, matrix.m42, matrix.m43)
                movedObject?.position = vector    
            }                   
        }
    } else if recognizer.state == .ended {
        movedObject = nil
    }  
}
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
Oscar Falmer
  • 1,771
  • 1
  • 24
  • 38

1 Answers1

4

Found the solution ! I added some explanations in comments.

if (movedObject != nil) {

    //Normalized-depth coordinate matching the plane I want
    let projectedOrigin = sceneView.projectPoint((movedObject?.position)!)

    //Location of the finger in the view on a 2D plane
    let location2D = recognizer.location(in: sceneView)

    //Location of the finger in a 3D vector
    let location3D = SCNVector3Make(Float(location2D.x), Float(location2D.y), projectedOrigin.z)

    //Unprojects a point from the 2D pixel coordinate system of the renderer to the 3D world coordinate system of the scene
    let realLocation3D = sceneView.unprojectPoint(location3D)

    if movedObject?.position != nil {

        //Only updating Y axis position
        movedObject?.position = SCNVector3Make((movedObject?.position.x)!, realLocation3D.y, (movedObject?.position.z)!)
    }

}

Posts that help understand:

unProjectPoint & projectedOrigin

translation & unProjectPoint

Oscar Falmer
  • 1,771
  • 1
  • 24
  • 38
  • How do we move it along any Axis? I don't want to restrict movement to particular axis. Also is it possible to rotate the selected child node with gesture? Can you please help me out? – Vidhya Sri May 22 '18 at 06:00