Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
498 views
in Technique[技术] by (71.8m points)

ios - 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.

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...