Placing, Dragging and Removing SCNNodes in ARKit

I’m working on a small project using ARKit. I want to be able to add objects to my AR SceneView on tap, remove them with a double tap, and drag theme around with a pan or drag.

The initial tap to place objects is working fine, but I have some issues with the Node removal and the dragging.

  • adding a lot of custom nodes to scene takes a long time to load
  • Stroke Width with a SceneKit line primitive type
  • Why SCNPhysicsBody resets position when set eulerAngles?
  • Using SceneKit for hitTesting not returning a hit with SCNNode
  • cameranode rotate as iOS device moving
  • Node group's position is reset at the start of SCNNode.runAction
  • The main issue with the removal and the dragging is that it is very difficult to actually ‘hold’ or click on the SCNNode. Most of the results end up not being on the SCNNode I’ve added.

    The second issue is that the dragging is a bit buggy, the SCNNode doesn’t really move as much as my finger does on the drag.

    I’ve decided to create a project on github, which is linked here: https://github.com/theraad/ARAttempt

    But I’ll also post my code for removing objects and dragging objects here:

    -(void)handleRemoveObject:(UITapGestureRecognizer *)recognizer {
        NSLog(@"Long Press Fired");
        CGPoint tapPoint = [recognizer locationInView:_sceneView];
    
        NSArray <SCNHitTestResult *> *result = [self.sceneView hitTest:tapPoint options:nil];
    
        if ([result count] == 0) {
            return;
        }
        SCNHitTestResult *hitResult = [result firstObject];
        if (hitResult.node) {
            [[hitResult.node parentNode] removeFromParentNode];
        }
    }
    
    -(void)moveObject:(UIPanGestureRecognizer *)recognizer {
        NSLog(@"Move object");
        if (recognizer.state == UIGestureRecognizerStateBegan) {
            NSLog(@"Pan state began");
            CGPoint tapPoint = [recognizer locationInView:_sceneView];
            NSArray <SCNHitTestResult *> *result = [self.sceneView hitTest:tapPoint options:nil];
    
            if ([result count] == 0) {
                return;
            }
            SCNHitTestResult *hitResult = [result firstObject];
            if ([hitResult.node.name isEqualToString:@"candle"]) {
                movedObject = [hitResult node];
            } else if ([[hitResult.node parentNode].name isEqualToString:@"candle"]) {
                movedObject = [[[hitResult node] parentNode] parentNode] parentNode];
            }
            if (movedObject){
                NSLog(@"Holding an Object");
            }
        }
        if (recognizer.state == UIGestureRecognizerStateChanged) {
            NSLog(@"Pan State Changed");
            if (movedObject) {
    
                CGPoint tapPoint = [recognizer locationInView:_sceneView];
                NSArray <ARHitTestResult *> *hitResults = [_sceneView hitTest:tapPoint types:ARHitTestResultTypeFeaturePoint];
                ARHitTestResult *result = [hitResults lastObject];
    
                SCNMatrix4 matrix = SCNMatrix4FromMat4(result.worldTransform);
                SCNVector3 vector = SCNVector3Make(matrix.m41, matrix.m42, matrix.m43);
    
                [movedObject setPosition:vector];
                NSLog(@"Moving object position");
            }
        }
        if (recognizer.state == UIGestureRecognizerStateEnded) {
            NSLog(@"Done moving object homeie");
            movedObject = nil;
        }
    }
    

    Any help would be highly appreciated.

    Thank you.

    UPDATE:

    So I found out that the difficulty with grabbing objects was because I was using:
    self.sceneView.debugOptions = ARSCNDebugOptionShowFeaturePoints;

    And when i would try to click on an object, it would most of the times be grabbing one of these feature points.

    -(void)moveObject:(UIPanGestureRecognizer *)recognizer {
        NSLog(@"Move object");
        if (recognizer.state == UIGestureRecognizerStateBegan) {
            NSLog(@"Pan state began");
            CGPoint tapPoint = [recognizer locationInView:_sceneView];
            NSArray <SCNHitTestResult *> *result = [self.sceneView hitTest:tapPoint options:nil];
    
            if ([result count] == 0) {
                return;
            }
            SCNHitTestResult *hitResult = [result firstObject];
            movedObject = [[[hitResult node] parentNode] parentNode] parentNode]; //This aspect varies based on the type of .SCN file that you have
            }
            if (movedObject){
                NSLog(@"Holding an Object");
            }
        }
        if (recognizer.state == UIGestureRecognizerStateChanged) {
            NSLog(@"Pan State Changed");
            if (movedObject) {
    
                CGPoint tapPoint = [recognizer locationInView:_sceneView];
                NSArray <ARHitTestResult *> *hitResults = [_sceneView hitTest:tapPoint types:ARHitTestResultTypeFeaturePoint];
                ARHitTestResult *result = [hitResults lastObject];
    
                SCNMatrix4 matrix = SCNMatrix4FromMat4(result.worldTransform);
                SCNVector3 vector = SCNVector3Make(matrix.m41, matrix.m42, matrix.m43);
    
                [movedObject setPosition:vector];
                NSLog(@"Moving object position");
            }
        }
        if (recognizer.state == UIGestureRecognizerStateEnded) {
            NSLog(@"Done moving object homeie");
            movedObject = nil;
        }
    }
    

    So the issue seems that instead of grabbing the whole object previously, I was still grabbing a child of this object, and when you attempt to drag a child it forces the movement to be laggy for some reason. So I had to do a bit of trial and error to realize that I had to move up parent levels to fix the issue.

    Hope this helps.

    Solutions Collect From Internet About “Placing, Dragging and Removing SCNNodes in ARKit”

    The solution for dragging the object was to set the movedObject to the [[[hitResult node] parentNode] parentNode] parentNode] and the drag became smoother.