问题描述
我需要使用 ARKit 检测虚拟对象何时与现实世界对象接触.
有什么办法可以查到吗?
首先你需要创建一个符合OptionSet
协议并具有bitset类型属性的碰撞类别结构体:
导入 ARKit结构类别:OptionSet {让 rawValue: Int静态 let sphereCategory = Category(rawValue: 1 << 0)静态 let targetCategory = Category(rawValue: 1 << 1)}
然后在生命周期方法中设置一个physics delegate
到SCNPhysicsContactDelegate
协议:
class ViewController: UIViewController, SCNPhysicsContactDelegate {@IBOutlet var sceneView:ARSCNView!覆盖 func viewWillAppear(_ 动画:布尔){super.viewWillAppear(动画)sceneView.scene.physicsWorld.contactDelegate = self让配置 = ARWorldTrackingConfiguration()config.planeDetection = [.horizontal]场景视图.session.run(配置)}}
SCNPhysicsContactDelegate
包含 3 个可选的physicsWorld() 方法(稍后我们将使用第一个):
公共协议 SCNPhysicsContactDelegate: NSObjectProtocol {可选 func 物理世界(_ 世界:SCNPhysicsWorld,didBegin 联系方式:SCNPhysicsContact)可选 func 物理世界(_ 世界:SCNPhysicsWorld,didUpdate 联系方式:SCNPhysicsContact)可选 func 物理世界(_ 世界:SCNPhysicsWorld,didEnd 联系方式:SCNPhysicsContact)}
在此之后为球体碰撞器定义categoryBitMask
和collisionBitMask
:
fileprivate func createSphere() ->SCN节点{var sphere = SCNNode()sphere.geometry = SCNSphere(半径:0.1)sphere.physicsBody = SCNPhysicsBody(类型:.dynamic,形状:nil)sphere.physicsBody?.isAffectedByGravity = truesphere.physicsBody?.categoryBitMask = Category.sphereCategory.rawValuesphere.physicsBody?.collisionBitMask = Category.targetCategory.rawValue返回球体}
...并为现实世界检测到的平面以相反的顺序定义位掩码:
fileprivate func visualDetectedPlane() ->SCN节点{var 平面 = SCNNode()平面.几何= SCNPlane(宽度:0.7,高度:0.7)plane.physicsBody = SCNPhysicsBody(类型:.dynamic,形状:nil)plane.physicsBody?.isAffectedByGravity = falseplane.physicsBody?.categoryBitMask = Category.targetCategory.rawValueplane.physicsBody?.collisionBitMask = Category.sphereCategory.rawValue回程飞机}
并且只有当您将 SCNPlanes 添加到现实世界检测到的平面并将 SCNSphere 添加到您的 SCNScene 时,您才能使用 physicsWorld(_:didBegin:)
实例方法来检测碰撞:
func PhysicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {如果 contact.nodeA.physicsBody?.categoryBitMask ==Category.targetCategory.rawValue ||contact.nodeB.physicsBody?.categoryBitMask ==Category.targetCategory.rawValue {打印(砰!")}}
I need to detect when the virtual objects gets in contact with the real world object using ARKit.
Is there any way to find it out?
At first you need to create a collision category struct that conforms to OptionSet
protocol and has properties with bitset types:
import ARKit
struct Category: OptionSet {
let rawValue: Int
static let sphereCategory = Category(rawValue: 1 << 0)
static let targetCategory = Category(rawValue: 1 << 1)
}
Then set a physics delegate
to SCNPhysicsContactDelegate
protocol inside lifecycle method:
class ViewController: UIViewController, SCNPhysicsContactDelegate {
@IBOutlet var sceneView: ARSCNView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
sceneView.scene.physicsWorld.contactDelegate = self
let config = ARWorldTrackingConfiguration()
config.planeDetection = [.horizontal]
sceneView.session.run(config)
}
}
SCNPhysicsContactDelegate
contains 3 optional physicsWorld() methods (we'll use 1st later):
public protocol SCNPhysicsContactDelegate: NSObjectProtocol {
optional func physicsWorld(_ world: SCNPhysicsWorld,
didBegin contact: SCNPhysicsContact)
optional func physicsWorld(_ world: SCNPhysicsWorld,
didUpdate contact: SCNPhysicsContact)
optional func physicsWorld(_ world: SCNPhysicsWorld,
didEnd contact: SCNPhysicsContact)
}
After this define categoryBitMask
and collisionBitMask
for sphere collider:
fileprivate func createSphere() -> SCNNode {
var sphere = SCNNode()
sphere.geometry = SCNSphere(radius: 0.1)
sphere.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
sphere.physicsBody?.isAffectedByGravity = true
sphere.physicsBody?.categoryBitMask = Category.sphereCategory.rawValue
sphere.physicsBody?.collisionBitMask = Category.targetCategory.rawValue
return sphere
}
...and define bit-masks in reversed order for real world detected plane:
fileprivate func visualizeDetectedPlane() -> SCNNode {
var plane = SCNNode()
plane.geometry = SCNPlane(width: 0.7, height: 0.7)
plane.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
plane.physicsBody?.isAffectedByGravity = false
plane.physicsBody?.categoryBitMask = Category.targetCategory.rawValue
plane.physicsBody?.collisionBitMask = Category.sphereCategory.rawValue
return plane
}
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
if contact.nodeA.physicsBody?.categoryBitMask ==
Category.targetCategory.rawValue ||
contact.nodeB.physicsBody?.categoryBitMask ==
Category.targetCategory.rawValue {
print("BOOM!")
}
}
这篇关于ARKit - 与现实世界的物体碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!