swiftaugmented-realityarkitraycastingrealitykit

How to use Raycast methods in RealityKit?


There are three ways about Detecting Intersections in RealityKit framework, but I don't know how to use it in my project.

1.

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

2.

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

3.

func convexCast(convexShape: ShapeResource, 
               fromPosition: SIMD3<Float>, 
            fromOrientation: simd_quatf, 
                 toPosition: SIMD3<Float>, 
              toOrientation: simd_quatf, 
                      query: CollisionCastQueryType, 
                       mask: CollisionGroup, 
                 relativeTo: Entity?) -> [CollisionCastHit]

Solution

  • Simple Ray-Casting

    If you want to find out how to position a model made in Reality Composer into a RealityKit scene (that has a detected horizontal plane) using Ray-Casting method, use the following code:

    import RealityKit
    import ARKit
    
    class ViewController: UIViewController {
        
        @IBOutlet var arView: ARView!
        let scene = try! Experience.loadScene()
        
        @IBAction func onTap(_ sender: UITapGestureRecognizer) {
            
            scene.steelBox!.name = "Parcel"
            
            let tapLocation: CGPoint = sender.location(in: arView)
            let estimatedPlane: ARRaycastQuery.Target = .estimatedPlane
            let alignment: ARRaycastQuery.TargetAlignment = .horizontal
                    
            let result: [ARRaycastResult] = arView.raycast(from: tapLocation,
                                                       allowing: estimatedPlane,
                                                      alignment: alignment)
            
            guard let rayCast: ARRaycastResult = result.first
            else { return }
            
            let anchor = AnchorEntity(world: rayCast.worldTransform)
            anchor.addChild(scene)
            arView.scene.anchors.append(anchor)
            
            print(rayCast)
        }
    }
    

    Pay attention to a class ARRaycastQuery. This class comes from ARKit, not from RealityKit.

    Convex-Ray-Casting

    A Convex-Ray-Casting methods like raycast(from:to:query:mask:relativeTo:) is the op of swiping a convex shapes along a straight line and stopping at the very first intersection with any of the collision shape in the scene. Scene raycast() method performs a hit-tests against all entities with collision shapes in the scene. Entities without a collision shape are ignored.

    You can use the following code to perform a convex-ray-cast from start position to end:

    import RealityKit
    
    let startPosition: SIMD3<Float> = [0, 0, 0]
    let endPosition: SIMD3<Float> = [5, 5, 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 }
        
    print(rayCast.distance)      /* The distance from the ray origin to the hit */
    print(rayCast.entity.name)   /* The entity's name that was hit              */
    

    A CollisionCastHit structure is a hit result of a collision cast and it lives in RealityKit's scene.

    P.S.

    When you use raycast(from:to:query:mask:relativeTo:) method for measuring a distance from camera to entity it doesn't matter what an orientation of ARCamera is, it only matters what its position is in world coordinates.