【发布时间】:2018-01-12 13:54:30
【问题描述】:
我正在使用 ARKit 做一个小项目。我希望能够在点击时将对象添加到我的 AR SceneView,双击删除它们,然后通过平移或拖动来拖动主题。
最初点击放置对象工作正常,但我在删除节点和拖动时遇到了一些问题。
删除和拖动的主要问题是很难真正“按住”或单击 SCNNode。大多数结果最终不在我添加的 SCNNode 上。
第二个问题是拖动有点麻烦,SCNNode 并没有像我的手指在拖动时那样真正移动。
我决定在github上创建一个项目,链接在这里:https://github.com/theraad/ARAttempt
但我也会在此处发布用于删除对象和拖动对象的代码:
-(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;
}
}
任何帮助将不胜感激。
谢谢。
更新:
所以我发现抓取物体的困难是因为我使用的是:
self.sceneView.debugOptions = ARSCNDebugOptionShowFeaturePoints;
当我试图点击一个对象时,大多数时候它会抓住这些特征点之一。
-(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;
}
}
所以问题似乎是我之前没有抓住整个对象,而是抓住了这个对象的一个孩子,当你试图拖动一个孩子时,它会由于某种原因迫使运动变得迟缓。所以我不得不做一些试验和错误来意识到我必须提升父母级别来解决这个问题。
希望这会有所帮助。
【问题讨论】:
-
如果您还没有,您可能需要查看 Apple 的示例项目“在增强现实中放置虚拟对象”,请参阅 stackoverflow.com/questions/45488881/… 以获取项目的 url。这肯定涵盖了拖动屏幕部分。
-
什么是“movedObject”?我没有看到声明。我正在尝试快速执行此操作,这就是我目前所拥有的:@objc func panGesture(sender: UIPanGestureRecognizer){ let sceneView = sender.view as! ARSCNView let pannedLocation = sender.location(in: sceneView) let hitTest = sceneView.hitTest(pannedLocation) if(sender.state == UIGestureRecognizerState.began){ if(!hitTest.isEmpty){ let sceneHitTestResult = hitTest.first! sceneView.scene.rootNode.chil = sceneHitTestResult.node.parent } }
-
movedObject 只是对 SCNNode 的引用,如果有命中则设置为开始状态,然后在平移手势的状态更改中更新。基本上只用在这个函数中。
-
我正在使用 swift,但请查看我对 this thread 的回答,了解如何拖动具有任意数量子节点的 SCNNode。必须做的最基本的事情是为您要选择的对象分配一个
.categoryBitMask值,并且只对具有该位掩码的对象进行 hitTest,这样您就不会选择任何不需要的对象。 -
git 链接不起作用。您能否提供代码以了解对象放置的工作原理。
标签: ios objective-c arkit scnnode