Dragging SCNNode in ARKit Using SceneKit

六月ゝ 毕业季﹏ 提交于 2019-12-17 17:58:15

问题


I have a simple SCNNode in ARKit and I am trying to drag it wherever I moved my finger on the phone. Here is my code.

 @objc func pan(recognizer :UIGestureRecognizer) {

        guard let currentFrame = self.sceneView.session.currentFrame else {
            return
        }

        var translation = matrix_identity_float4x4
        translation.columns.3.z = -1.5

        let sceneView = recognizer.view as! ARSCNView
        let touchLocation = recognizer.location(in: sceneView)

        let hitTestResult = sceneView.hitTest(touchLocation, options: [:])

        if !hitTestResult.isEmpty {

            print("hit result")

            guard let hitResult = hitTestResult.first else {
                return
            }

            let node = hitResult.node

            node.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
        }
    }

The problem is that the drag is very slow and not smooth.


回答1:


I handle translation with PanGesture like this. The division by 700 is to smooth and adjust speed of movement, I reached to that value by trial or error, you may want to experiment with it

@objc func onTranslate(_ sender: UIPanGestureRecognizer) {
    let position = sender.location(in: scnView)
    let state = sender.state

    if (state == .failed || state == .cancelled) {
        return
    }

    if (state == .began) {
        // Check it's on a virtual object
        if let objectNode = virtualObject(at: position) {
            // virtualObject(at searches for root node if it's a subnode
            targetNode = objectNode
            latestTranslatePos = position
        }

    }
    else if let _ = targetNode {

        // Translate virtual object
        let deltaX = Float(position.x - latestTranslatePos!.x)/700
        let deltaY = Float(position.y - latestTranslatePos!.y)/700

        targetNode!.localTranslate(by: SCNVector3Make(deltaX, 0.0, deltaY))

        latestTranslatePos = position

        if (state == .ended) {
            targetNode = nil
        }
    }
}



回答2:


I had a similar problem. Whilst you should use John's advice in the comments and use the pan gesture states correct (Began, Changed, Ended), I think the issue might be that you are grabbing the hitResult.node when you should be grabbing the parent of the node, or even the parent's parent, etc... I've had this issue and ended up fixing it by going up parent levels until the entire object was being selected instead of a part of it.




回答3:


Had the same issue. Using a SCNTransaction did the trick for me.

@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
    [...]

    SCNTransaction.begin()
    SCNTransaction.animationDuration = 0
    imagePlane.position.x = hitTestResult.localCoordinates.x
    imagePlane.position.y = hitTestResult.localCoordinates.y
    SCNTransaction.commit()
}


来源:https://stackoverflow.com/questions/44729610/dragging-scnnode-in-arkit-using-scenekit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!