ARKit – 使用 raycastQuery 而不是 hitTest 的 Tap 节点,后者已被弃用
ARKit – Tap node with raycastQuery instead of hitTest, which is deprecated
在iOS14,hitTest(_:types:)
was deprecated. It seems that you are supposed to use raycastQuery(from:allowing:alignment:)
now. From the documentation:
Raycasting is the preferred method for finding positions on surfaces in the real-world environment, but the hit-testing functions remain present for compatibility. With tracked raycasting, ARKit continues to refine the results to increase the position accuracy of virtual content you place with a raycast.
但是,如何使用光线投射命中测试 SCNNode
s?我只看到命中测试飞机的选项。
raycastQuery
method documentation
Only choices for allowing:
are planes
这是我当前的代码,它使用 hit-testing 检测立方体节点上的点击并将其变为蓝色。
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( { [=10=].node.name == "ColorCube" }) { /// See if the beam hit the cube
let cubeNode = result.node
cubeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue /// change to blue
}
}
}
如何用等效的 raycastQuery
代码替换 let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1])
?
关于命中测试
官方文档说在iOS14中只有ARKit的hitTest(_:types:)实例方法被弃用了。但是在iOS15中你仍然可以使用它。 ARKit 的命中测试方法应该替换为光线投射方法。
已弃用的命中测试:
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!)
如果您更喜欢光线投射方法来击中节点(实体),请使用 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)
P.S.
无需寻找 SceneKit 的 hitTest(_:options:) 实例方法返回 [SCNHitTestResult] 的替代方法,因为它运行良好,现在不是弃用它的时候。
在iOS14,hitTest(_:types:)
was deprecated. It seems that you are supposed to use raycastQuery(from:allowing:alignment:)
now. From the documentation:
Raycasting is the preferred method for finding positions on surfaces in the real-world environment, but the hit-testing functions remain present for compatibility. With tracked raycasting, ARKit continues to refine the results to increase the position accuracy of virtual content you place with a raycast.
但是,如何使用光线投射命中测试 SCNNode
s?我只看到命中测试飞机的选项。
raycastQuery method documentation |
Only choices for allowing: are planes |
---|---|
这是我当前的代码,它使用 hit-testing 检测立方体节点上的点击并将其变为蓝色。
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( { [=10=].node.name == "ColorCube" }) { /// See if the beam hit the cube
let cubeNode = result.node
cubeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue /// change to blue
}
}
}
如何用等效的 raycastQuery
代码替换 let results = sceneView.hitTest(location, options: [SCNHitTestOption.searchMode : 1])
?
关于命中测试
官方文档说在iOS14中只有ARKit的hitTest(_:types:)实例方法被弃用了。但是在iOS15中你仍然可以使用它。 ARKit 的命中测试方法应该替换为光线投射方法。
已弃用的命中测试:
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!)
如果您更喜欢光线投射方法来击中节点(实体),请使用 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)
P.S.
无需寻找 SceneKit 的 hitTest(_:options:) 实例方法返回 [SCNHitTestResult] 的替代方法,因为它运行良好,现在不是弃用它的时候。