微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ARKit – 使用 raycastQuery 而不是 hitTest 来点击节点,后者已被弃用

如何解决ARKit – 使用 raycastQuery 而不是 hitTest 来点击节点,后者已被弃用

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

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

但是,我如何使用光线投射命中测试 SCNNode?我只看到测试飞机的选项。

raycastQuery 方法文档 只有 allowing: 的选择是飞机

Screenshot of documentation for the "raycastQuery(from:allowing:alignment:)" method

Screenshot of documentation of the possible options for the "allowing:" argument label,showing 3 different types of 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.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 代码

Gif of the code's result. Tapping the red cube turns it blue.

解决方法

官方文档说只弃用了 ARKit 的 hitTest(_:types:) 实例方法。但是在 iOS 14 中你仍然可以使用它。 ARKit的hit-testing方法应该换成raycasting方法。

已弃用的命中测试:

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

等效光线投射:

let raycastQuery: ARRaycastQuery? = sceneView.raycastQuery(
                                                      from: sceneView.center,allowing: .estimatedPlane,alignment: .any)

let results: [ARRaycastResult] = sceneView.session.raycast(raycastQuery!)

而且没有必要寻找 SceneKit 的 hitTest(_:options:) 实例方法的替代品,因为它运行良好,现在不是弃用它的时候。


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

let arView = ARView(frame: .zero)

let query: CollisionCastQueryType = .nearest
let mask: CollisionGroup = .default
    
let raycasts: [CollisionCastHit] = arView.scene.raycast(from: [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 的命中测试。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。