I have a subclass of RealityKit's ARView
that has the following function for making a Raycast:
func makeRaycastQuery(alignmentType: ARRaycastQuery.TargetAlignment) -> simd_float4x4? {
let results = self.raycast(from: self.center,
// Better for pinning to planes
allowing: .estimatedPlane,
alignment: alignmentType)
// We don't care about changing scale on raycast so keep it the same
guard var result = results.first?.worldTransform else { return nil }
result.scale = SCNVector3(1, 1, 1)
return result
}
However, my results
array is always empty. Is there some sort of other configuration I need to do when setting up an ARView
to enable raycasting?
Try this code (I've written it for iPad's Playgrounds):
import RealityKit
import SwiftUI
import ARKit
import PlaygroundSupport
struct ContentView : View {
@State private var arView = ARView(frame: .zero)
var body: some View {
return ARContainer(arView: $arView)
.gesture(
TapGesture()
.onEnded { _ in
raycasting(arView: arView)
}
)
}
func raycasting(arView: ARView) {
guard let query = arView.makeRaycastQuery(from: arView.center,
allowing: .estimatedPlane,
alignment: .any)
else { fatalError() }
guard let result = arView.session.raycast(query).first
else { fatalError() }
let entity = ModelEntity(mesh: .generateSphere(radius: 0.1))
let anchor = AnchorEntity(raycastResult: result)
anchor.addChild(entity)
arView.scene.anchors.append(anchor)
}
}
struct ARContainer : UIViewRepresentable {
@Binding var arView: ARView
func makeUIView(context: Context) -> ARView {
arView.cameraMode = .ar
return arView
}
func updateUIView(_ view: ARView, context: Context) { }
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.setLiveView(ContentView())
P. S.
This version works in UIKit app.