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.
.categoryBitMask
-value to the object you want to select and only hitTest for objects with that bitmask so you don't select any unwanted objects. – A. Claesson