Swift: can’t detect hit test on SCNNode? See if vector3 is contained in a node?
我试图检测在我的 AR 场景中实例化的 SCNNode 上的点击。它似乎不像 SceneKit 在这里命中测试结果那样工作,而且我对场景套件没有太多经验。
我只想检测点击点是否包含在场景中的任何节点中,从而检测对象上的点击。我从其他答案中尝试过的内容:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return } let results = sceneView.hitTest(touch.location(in: sceneView), types: [ARHitTestResult.ResultType.featurePoint]) let hitTransform = SCNMatrix4.init(hitFeature.worldTransform) let hitPosition = SCNVector3Make(hitTransform.m41, if(theDude.node.boundingBoxContains(point: hitPosition)) } } |
我得到的最后一个 if 语句没有打印任何内容:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
extension SCNNode {
func boundingBoxContains(point: SCNVector3, in node: SCNNode) -> Bool { let localPoint = self.convertPosition(point, from: node) return boundingBoxContains(point: localPoint) } func boundingBoxContains(point: SCNVector3) -> Bool { struct BoundingBox { init(_ boundTuple: (min: SCNVector3, max: SCNVector3)) { func contains(_ point: SCNVector3) -> Bool { max.x > point.x && return contains |
并且 ARHitTestResult 不包含节点。如何检测 ARScene 中节点上的点击?
当您使用 ARSCNView 时,您可以进行两种命中测试,它们使用完全独立的代码路径。
- 如果您想针对真实世界(或至少针对 ARKit 对真实世界特征所在位置的估计)进行测试,请使用 ARKit 方法 hitTest(_:types:)。这会返回 ARHitTestResult 对象,这些对象会告诉您真实世界的特征,例如检测到的平面。换句话说,如果您想找到一个任何人都可以在没有设备的情况下看到和触摸的真实对象,例如您将设备指向的桌子,请使用此方法。
- 如果要对 SceneKit 内容进行测试,请使用 SceneKit 方法 hitTest(_:options:);也就是说,搜索您放置在 AR 场景中的虚拟 3D 对象。这会返回 SCNHitTestResult 对象,这些对象会告诉您诸如节点和几何图形之类的信息。如果要查找 SceneKit 节点、节点中的模型(几何体)或几何体上点击位置的特定点,请使用此方法。
在这两种情况下,命中测试找到的 3D 位置是相同的,因为 ARSCNView 确保虚拟”世界坐标”空间与真实世界空间匹配。
看起来您正在使用前者,但期待后者。当您进行 SceneKit 命中测试时,当且仅当命中测试点下方有一个节点时,您才会得到结果,因为您不需要任何类型的边界框测试,因为它已经为您完成了。
- 好的,谢谢,不过这里还是有点不清楚。节点本来是放在hitPosition位置的”现实世界”中,所以我想我想要ARKit的命中测试。你能提供一个使用 ARHitTestResult 来判断那里是否有节点的例子吗?
- ARHitTestResult 只返回一个向量,这就是我尝试使用节点边界框??的原因
- 您不会将 SceneKit 节点放置在”现实世界”中。至少,不是没有一些额外的软件和 3D 打印机。但是,使用 ARSCNView,SceneKit 节点的位置和大小在”实际世界”测量中,因此您仍然可以使用 SceneKit 方法来查找它们。相反,试图从一个向量(通过 ARHitTestResult 获得)返回到一个节点只是编写(以及调试和维护)比您需要的更多的代码。编辑答案以澄清。
- 好的,谢谢你的澄清。所以我需要使用 SceneKit NOT Ar 命中测试功能吗?那会返回节点吗?你能写出你会怎么做吗 – 当我尝试 SceneKit 命中测试时,我不断收到关于需要指定结果类型的错误
- 已经有很多关于 SceneKit 命中测试的问题和答案,这对于 SceneKit-with-ARKit 同样有效。
- @rickster 如何忽略 ARSCNDebugOptions.showFeaturePoints 中的 hittest ?
- 诶?显示特征点与命中测试没有任何关系。澄清您的问题并将其作为问题(而不是评论)发布,也许?
添加一个 UITapGestureRecognizer
1
|
let tapRec = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(rec:)))
|
在 state .ended 上的 handleTap 方法中:
1
2 3 4 5 6 7 8 9 |
@objc func handleTap(rec: UITapGestureRecognizer){
if rec.state == .ended { let location: CGPoint = rec.location(in: sceneView) let hits = self.sceneView.hitTest(location, options: nil) if let tappednode = hits.first?.node { //do something with tapped object } } } |
来源:https://www.codenong.com/46185723/