4
votes

Ok, like everyone else I am having trouble dragging/translating an SCNNode in ARKit/world space. Ive looked at Dragging SCNNode in ARKit Using SceneKit and all the popular questions, as well as the code from Apple https://github.com/gao0122/ARKit-Example-by-Apple/blob/master/ARKitExample/VirtualObject.swift

Ive tried to simplify as much as possible and just did what I would in a normal scene kit game - http://dayoftheindie.com/tutorials/3d-games-graphics/t-scenekit-3d-picking-dragging/

I can get the tapped object and store the current finger pos no problem with:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        guard let touch = touches.first else { return }

        let results = gameView.hitTest(touch.location(in: gameView), types: [ARHitTestResult.ResultType.featurePoint])

        //TAP Test
        let hits = gameView.hitTest(touch.location(in: gameView), options: nil)
        currentTapPos = getARPos(hitFeature: hitFeature) //TAP POSITION

        if let tappedNode = hits.first?.node {

My issue is, however, doing this in update - there is no animation. The object just appears wherever I tap, and overall not working -

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

        guard let touch = touches.first else { return }

        let results = gameView.hitTest(touch.location(in: gameView), types: [ARHitTestResult.ResultType.featurePoint])
        guard let hitFeature = results.last else { return }

        testNode.position = currentTapPos

I convert to SCNVector3 with this func:

func getARPos(hitFeature: ARHitTestResult)->SCNVector3
{

    let hitTransform = SCNMatrix4.init(hitFeature.worldTransform)
    let hitPosition = SCNVector3Make(hitTransform.m41,
                                     hitTransform.m42,
                                     hitTransform.m43)
    return hitPosition
}

I have tried:

-translate by vector -pan gesture (this screwed up other functions) -SCNAction.moveTo

What can I do here? Whats wrong?

1
Take a look at Apple’s newer version of that sample code. It seems to have much simpler, clearer dragging code (with gesture recognizers) now.rickster
Right - my issue is I cant use gesture recognizers since I have other UI on the screen and it messes with it. Do you see anything you can pull out/apply without a pan gesture?skyguy
What was problem with SCNAction? I used pan gesture but I did smooth transition using SCNAction.Alok Subedi

1 Answers

6
votes

I agree with @Rickster that the Apple Code provides a much more robust example, however, I have this and it seems to work smoothly (much more so when you are using PlaneDetection (since feature points are much more sporadic):

I don't make use of touchesBegan but simply do the work in touchesMoved instead:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Point
    guard let currentTouchPoint = touches.first?.location(in: self.augmentedRealityView),
        //2. Get The Next Feature Point Etc
        let hitTest = augmentedRealityView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }

    //3. Convert To World Coordinates
    let worldTransform = hitTest.worldTransform

    //4. Set The New Position
    let newPosition = SCNVector3(worldTransform.columns.3.x, worldTransform.columns.3.y, worldTransform.columns.3.z)

    //5. Apply To The Node
    nodeToDrag.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)

}

I might be going about this completely the wrong way (and if I am I would love to get feedback).

Anyway, I hope it might help... You can see a quick video of it in action here: Dragging SCNNode