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.

  • Convert a UIImage into NSData BUT stay as a GIF file
  • XcCode5: How do relationships work with interface builder?
  • Crashlog links to which .dSYM
  • Why is UIScrollView leaving space on top and does not scroll to the bottom
  • First frame of a video using AVFoundation
  • CAShapeLayer mask view
  • 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.