Reputation: 3221
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?
Upvotes: 2
Views: 398
Reputation: 637
In my experience, some older devices that don't have LiDAR perform far worse than the latest devices. I'm using an iPhone 11 vs an iPad Pro M1 to test the same raycast method. iPad Pro has 100% hit rate, while iPhone 11 only has about 15% due to my testing plane being too reflective (?).
If you are in doubt of the validity of your implementation, test with a LiDAR device first. (💸)
Upvotes: 0
Reputation: 58113
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.
Upvotes: 1