ARKit - 与现实世界的物体碰撞 [英] ARKit – Collision with Real world objects

查看:24
本文介绍了ARKit - 与现实世界的物体碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用 ARKit 检测虚拟对象何时与现实世界对象接触.

有什么办法可以查到吗?

解决方案

首先你需要创建一个符合OptionSet协议并具有bitset类型属性的碰撞类别结构体:

导入 ARKit结构类别:OptionSet {让 rawValue: Int静态 let sphereCategory = Category(rawValue: 1 << 0)静态 let targetCategory = Category(rawValue: 1 << 1)}

然后在生命周期方法中设置一个physics delegateSCNPhysicsContactDelegate协议:

class ViewController: UIViewController, SCNPhysicsContactDelegate {@IBOutlet var sceneView:ARSCNView!覆盖 func viewWillAppear(_ 动画:布尔){super.viewWillAppear(动画)sceneView.scene.physicsWorld.contactDelegate = self让配置 = ARWorldTrackingConfiguration()config.planeDetection = [.horizo​​ntal]场景视图.session.run(配置)}}

SCNPhysicsContactDelegate 包含 3 个可选的physicsWorld() 方法(稍后我们将使用第一个):

公共协议 SCNPhysicsContactDelegate: NSObjectProtocol {可选 func 物理世界(_ 世界:SCNPhysicsWorld,didBegin 联系方式:SCNPhysicsContact)可选 func 物理世界(_ 世界:SCNPhysicsWorld,didUpdate 联系方式:SCNPhysicsContact)可选 func 物理世界(_ 世界:SCNPhysicsWorld,didEnd 联系方式:SCNPhysicsContact)}

在此之后为球体碰撞器定义categoryBitMaskcollisionBitMask:

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
}

And only when you've added your SCNPlanes to real-world detected planes and append an SCNSphere to your SCNScene, you could use physicsWorld(_:didBegin:) instance method to detect collisions:

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 - 与现实世界的物体碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆