【问题标题】:ARKit – Tap node with raycastQuery instead of hitTest, which is deprecatedARKit – 使用 raycastQuery 而非 hitTest 来点击节点,这已被弃用
【发布时间】:2021-05-16 13:49:28
【问题描述】:

在 iOS 14 中,hitTest(_:types:) 已被弃用。看来您现在应该使用raycastQuery(from:allowing:alignment:)。来自documentation

光线投射是在现实环境中寻找表面位置的首选方法,但为了兼容性,命中测试功能仍然存在。通过跟踪光线投射,ARKit 会继续优化结果,以提高您通过光线投射放置的虚拟内容的位置准确性。

但是,我如何通过光线投射来测试SCNNodes?我只看到了测试飞机的选项。

raycastQuery method documentation Only choices for allowing: are planes

这是我当前的代码,它使用命中测试来检测立方体节点上的点击并将其变为蓝色。

class ViewController: UIViewController {

    @IBOutlet weak var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /// Run the configuration
        let worldTrackingConfiguration = ARWorldTrackingConfiguration()
        sceneView.session.run(worldTrackingConfiguration)
        
        /// Make the red cube
        let cube = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
        cube.materials.first?.diffuse.contents = UIColor.red
        
        let cubeNode = SCNNode(geometry: cube)
        cubeNode.position = SCNVector3(0, 0, -0.2) /// 20 cm in front of the camera
        cubeNode.name = "ColorCube"
        
        /// Add the node to the ARKit scene
        sceneView.scene.rootNode.addChildNode(cubeNode)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        guard let location = touches.first?.location(in: sceneView) else { return }
        
        let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1])
        for result in results.filter( { $0.node.name == "ColorCube" }) {  /// See if the beam hit the cube
            let cubeNode = result.node
            cubeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue /// change to blue
        }
    }
}

如何将let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1]) 替换为等效的raycastQuery 代码?

【问题讨论】:

    标签: swift augmented-reality scenekit arkit realitykit


    【解决方案1】:

    关于命中测试

    官方文档说,iOS 14 中仅弃用了 ARKit 的 hitTest(_:types:) 实例方法。但是,在 iOS 15 中,您仍然可以使用它。 ARKit 的命中测试方法应该被替换为光线投射方法。

    已弃用的命中测试:

    let results: [ARHitTestResult] = sceneView.hitTest(sceneView.center, 
                                               types: .existingPlaneUsingGeometry)
    


    Raycasting 等效项:

    let raycastQuery: ARRaycastQuery? = sceneView.raycastQuery(
                                                          from: sceneView.center, 
                                                      allowing: .estimatedPlane, 
                                                     alignment: .any)
    
    let results: [ARRaycastResult] = sceneView.session.raycast(raycastQuery!)
    

    如果您更喜欢光线投射方法来击中节点(实体),请使用 RealityKit 模块而不是 SceneKit:

    let arView = ARView(frame: .zero)
    
    let query: CollisionCastQueryType = .nearest
    let mask: CollisionGroup = .default
        
    let raycasts: [CollisionCastHit] = arView.scene.raycast(from: [0, 0, 0], 
                                                              to: [5, 6, 7],  
                                                           query: query, 
                                                            mask: mask, 
                                                      relativeTo: nil)
        
    guard let raycast: CollisionCastHit = raycasts.first else { return }
        
    print(raycast.entity.name)
    

    附言

    无需寻找替代 SceneKit 的 hitTest(_:options:) 实例方法返回 [SCNHitTestResult],因为它工作正常,现在不是制作的时候它已弃用。

    【讨论】:

    • 感谢您的快速答复!但是有没有办法从let results: [ARRaycastResult]获取立方体节点?
    • 知道了。所以基本上,如果我仍在使用 ARKit + SceneKit,即使它已被弃用,也只需进行命中测试?
    • sceneView 对象(ARSCNView 类型)有 3 个hitTest() 方法。其中一个已被弃用,返回[ARHitTestResult]——它用于命中测试检测到的飞机。第二个hitTest() 返回UIView?, and the third one returns [SCNHitTestResult]`,这对于针对节点的纯 SceneKit 命中测试很有用。第三种方法没有被弃用——你可以将它用于 AR 应用程序和 VR 应用程序。因此,您在 ARSCNView for iOS 14 中的武器库是 2 个 hitTest 方法和 1 个 raycastQuery() 方法。此外,ARSCNView 的会话对象允许您对检测到的平面应用光线投射方法。
    • 但是,如果您使用的是 ARView(ARKit 也可以使用 RealityKit 的视图),则只能使用光线投射方法 - arView.raycast(...)(返回 [ARRaycastResult]),arView.session.raycast(...)(返回 [ARRaycastResult] ])、arView.session.trackedRaycast(...) 和 2 个方法 arView.scene.raycast(...)
    • hitTestraycast 方法不是来自协议。您可以对 SceneKit 节点使用命中测试,也可以对 RealityKit 实体使用光线投射。对于 ARKit 检测到的飞机,您必须使用 raycasting
    猜你喜欢
    • 2020-03-06
    • 2023-04-04
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 2018-09-14
    • 2018-02-22
    相关资源
    最近更新 更多