【问题标题】:hitTest(_:options:) don't recognize nodes behind ARKit planeshitTest(_:options:) 无法识别 ARKit 平面后面的节点
【发布时间】:2023-04-04 00:20:01
【问题描述】:

我将一个对象放在墙上,然后尝试识别点击它,但点击测试返回 0 个对象。当我改变对象的 Z 位置并将其放置在更靠近凸轮的位置时,可以很好地识别它,但这不是解决方案,因为平面总是在变化,它可以随时覆盖对象。如何使 hitTest 正常工作并识别平面后面的节点?或者,也许,我使用了错误的方法?

fileprivate func addNode(atPoint point: CGPoint) {
    let hits = sceneView.hitTest(point, types: .existingPlaneUsingExtent)
    if hits.count > 0, let firstHit = hits.first, let originNode = originNode {
        let node = originNode.clone()
        sceneView.scene.rootNode.addChildNode(node)
        node.position = SCNVector3Make(firstHit.worldTransform.columns.3.x, firstHit.worldTransform.columns.3.y, firstHit.worldTransform.columns.3.z)
        let resize = simd_float4x4(SCNMatrix4MakeScale(0.2, 0.2, 0.2))
        let rotation = simd_float4x4(SCNMatrix4MakeRotation(.pi / 2, -1, 0, 0))
        let transform = simd_mul(firstHit.worldTransform, resize)
        let finalTransform = simd_mul(transform, rotation)
        node.simdTransform = finalTransform
        addedNodes.insert(node)
    }
}

func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {
        print("Unable to identify touches on any plane. Ignoring interaction...")
        return
    }

    let touchPoint = touch.location(in: sceneView)

    let hits = sceneView.hitTest(touchPoint, options: [SCNHitTestOption.boundingBoxOnly: true])
    let filtered = hits.filter({ addedNodes.contains($0.node) })
    print("\(hits.count) vs \(filtered.count), \(hits.first?.node.name ?? "no name")")
    if let node = filtered.first?.node {
        node.removeFromParentNode()
        addedNodes.remove(node)
        return
    }

    addPictureToPlane(atPoint: touchPoint)
}

addedNodes - 设置有添加的对象。当我添加平移变换并改变 Z 坐标至少在 0.05(靠近相机)检测工作良好。至少在平面改变和前进节点之前。

【问题讨论】:

  • 请分享您的代码 - 不知道您在做什么就无法回答。
  • 添加了一段代码

标签: swift scenekit arkit


【解决方案1】:

我相信你需要做的是改变你的SCNHitTestSearchMode参数,它允许你设置:

用于命中测试的 searchMode 选项的可能值 方法。

static let searchMode: SCNHitTestOption

在哪里:

这个键的值是一个 NSNumber 对象,包含原始的 SCNHitTestSearchMode 常量的整数值。

Apple Docs 中,您可以在这里使用三个可能的选项:

case all

命中测试应该返回所有可能的结果,从最近的排序 到最远。

case any

命中测试应该只返回找到的第一个对象,而不管 距离。

case closest

命中测试应该只返回找到的关闭对象。

因此,根据您的问题,您可能需要使用all case

因此,您的hitTest function 可能需要看起来像这样(记住self.augmentedRealityView 指的是ARSCNView):

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView) else { return }

    //2. Perform An SCNHitTest Setting The SearchMode To 1 (All) Which Returns A List Of Results Sorted From Nearest To Farthest
    if #available(iOS 11.0, *) {

        let hitTestResults = self.augmentedRealityView.hitTest(currentTouchLocation, options: [SCNHitTestOption.searchMode: 1])

        //3. Loop Through The Results & Get The Nodes
        for index in 0..<hitTestResults.count{

            let node = hitTestResults[index]
            print(node)

        }
    }
}

【讨论】:

  • 我不知道,我怎么错过了这个参数。非常感谢!
  • 很高兴它有帮助:)
  • 考虑用 SCNHitTestSearchMode.all.rawValue 更改“1”以获得更清晰的代码
猜你喜欢
  • 2018-12-01
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多