ARKit – 使用 raycastQuery 而非 hitTest 来点击节点,这已被弃用
Posted
技术标签:
【中文标题】ARKit – 使用 raycastQuery 而非 hitTest 来点击节点,这已被弃用【英文标题】:ARKit – Tap node with raycastQuery instead of hitTest, which is deprecated 【发布时间】:2021-05-16 13:49:28 【问题描述】:在 ios 14 中,hitTest(_:types:)
已被弃用。看来您现在应该使用raycastQuery(from:allowing:alignment:)
。来自documentation:
光线投射是在现实环境中寻找表面位置的首选方法,但为了兼容性,命中测试功能仍然存在。通过跟踪光线投射,ARKit 会继续优化结果,以提高您通过光线投射放置的虚拟内容的位置准确性。
但是,我如何通过光线投射来测试SCNNode
s?我只看到了测试飞机的选项。
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
代码?
【问题讨论】:
【参考方案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(...)
。
hitTest
和 raycast
方法不是来自协议。您可以对 SceneKit 节点使用命中测试,也可以对 RealityKit 实体使用光线投射。对于 ARKit 检测到的飞机,您必须使用 raycasting
。以上是关于ARKit – 使用 raycastQuery 而非 hitTest 来点击节点,这已被弃用的主要内容,如果未能解决你的问题,请参考以下文章