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

ahe*_*eze 4 augmented-reality scenekit swift arkit realitykit

在 iOS 14 中,hitTest(_:types:)已弃用。看来你现在应该使用raycastQuery(from:allowing:alignment:)了。从文档

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

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

raycastQuery 方法文档 唯一的选择allowing:是飞机
“raycastQuery(from:allowing:alignment:)”方法的文档截图 “allowing:”参数标签的可能选项文档的屏幕截图,显示了 3 种不同类型的平面

这是我当前的代码,它使用命中测试来检测多维数据集节点上的点击并将其变为蓝色。

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

代码结果的 Gif。 点击红色立方体将其变为蓝色。

ARG*_*Geo 7

关于命中测试

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

弃用的命中测试:

let results: [ARHitTestResult] = sceneView.hitTest(sceneView.center, 
                                           types: .existingPlaneUsingGeometry)
Run Code Online (Sandbox Code Playgroud)


光线投射等效:

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

let results: [ARRaycastResult] = sceneView.session.raycast(raycastQuery!)
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢使用光线投射方法来击中节点(实体),请使用 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)
Run Code Online (Sandbox Code Playgroud)

聚苯乙烯

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

  • sceneView 对象(ARSCNView 类型)有 3 个 `hitTest()` 方法。其中一个已被弃用,返回“[ARHitTestResult]”——它用于对检测到的飞机进行命中测试。第二个“hitTest()”返回“UIView?”,第三个返回“[SCNHitTestResult]”,这对于针对节点的纯 SceneKit 命中测试非常有用。第三种方法并未被弃用 - 您可以将其用于 AR 应用程序和 VR 应用程序。因此,iOS 14 的 ARSCNView 中的武器库是 2 个“hitTest”方法和 1 个“raycastQuery()”方法。此外,ARSCNView 的会话对象允许您对检测到的平面应用光线投射方法。 (2认同)