How to detect penetration without physical interaction in ARKit?

不想你离开。 提交于 2021-02-20 00:59:06

问题


I have a fixed laser beam SCNNode and a detecting sphere SCNNode attached in front of a camera.

How to detect penetration without physical interaction? I have not found any clue..

EDIT: - as suggested below by maxxFrazer I implemented physical interaction and I'm able to register collision IF my laser beam is .static and detector moved by camera set .kinematic.


回答1:


If you need to detect a penetration without physical interaction use trackedRaycast instance method working in iOS 13+:

func trackedRaycast(_ query: ARRaycastQuery, 
              updateHandler: @escaping ([ARRaycastResult]) -> Void) -> ARTrackedRaycast?

trackedRaycast(_:updateHandler:) repeats a ray-cast query over time to notify you of updated surfaces in the physical environment.

Here's how it looks like:

import ARKit

let query = arView.raycastQuery(from: screenCenter,
                            allowing: .estimatedPlane, // also specifies nonplanar geo
                           alignment: .any)

let raycast = session.trackedRaycast(query) { results in

    if let result = results.first {
        object.transform = result.transform
    } 
}

raycast.stop()

Rememmber that trackedRaycast instance method repeatedly hits surfaces, so you have to stop it if you don't need it anymore.


However, if you need a convex raycast, use a RealityKit's instance method that also works in iOS 13+ and i's called raycast(origin:direction:query:mask:relativeTo:).

func raycast(origin: SIMD3<Float>, 
          direction: SIMD3<Float>,
              query: CollisionCastQueryType, 
               mask: CollisionGroup, 
         relativeTo: Entity) -> [CollisionCastHit]

This instance method performs a convex ray cast against all the geometry in the scene for a ray of a given origin, direction, and length.

import RealityKit

let startPosition: SIMD3<Float> = [7,7,7]
let endPosition: SIMD3<Float> = [-10,18,5]
let query: CollisionCastQueryType = .all
let mask: CollisionGroup = .all

let raycasts: [CollisionCastHit] = arView.scene.raycast(from: startPosition, 
                                                          to: endPosition, 
                                                       query: query,  
                                                        mask: mask, 
                                                  relativeTo: nil)

guard let rayCast: CollisionCastHit = raycasts.first
else { 
    return 
}



回答2:


It looks like you want to use a SceneKit solution, not RealityKit. And also want to find when two actual nodes intersect rather than a hitTest or raycast? If so, I've attempted to explain how to set that up below…

First add a physicsBody to the SCNNode, along with a categoryBitMask + contactTestBitMask. These two are basically saying what category your SCNNode body is, and what categories it can collide with.

You then also need to set up your SCNScene.physicsWorld.contactDelegate to an object which conforms to SCNPhysicsContactDelegate, this is so you can use the physicsWorld callbacks found here.

There's another question on stack overflow which may help in making this work for you:

Detecting collisions in SceneKit issue



来源:https://stackoverflow.com/questions/62393887/how-to-detect-penetration-without-physical-interaction-in-arkit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!