ios 如何使用SCNView作为ARView的子视图?

pkln4tw6  于 2022-11-26  发布在  iOS
关注(0)|答案(1)|浏览(134)

我使用ARKit-CoreLocation库在AR World中,在iOS 14中呈现POI。但问题是,我 * 不能 * 使用ARCLSceneLocationView,因为它是SCNView。所以当我将它作为子视图添加时,它覆盖了我的ARView内容,并创建了一个新的ARSession,将我的ARView留在后台。
编码:

extension RealityKitViewController {
    typealias Context = UIViewControllerRepresentableContext<RealityKitViewControllerRepresentable>
}

class RealityKitViewController: UIViewController {
    let sceneLocationView = SceneLocationView()
    let arView = ARView(frame: .zero)
    let context : Context
    let pins: [Pin]
    
    var currentLocation : CLLocation? {
        return sceneLocationView.sceneLocationManager.currentLocation
    }
    
    init (_ context : Context, pins: [Pin]) {
        self.context = context
        self.pins = pins
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func makeArView()
    {
        // Start AR session
        let session = arView.session
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.horizontal, .vertical]
        session.run(config)
        
        // Add coaching overlay
        let coachingOverlay = ARCoachingOverlayView()
        coachingOverlay.session = session
        coachingOverlay.goal = .horizontalPlane
        coachingOverlay.delegate = context.coordinator
        
        
        arView.addSubview(coachingOverlay)
        
        arView.debugOptions = [.showFeaturePoints, .showAnchorOrigins, .showAnchorGeometry]
        
        // Handle ARSession events via delegate
        context.coordinator.view = arView
        session.delegate = context.coordinator
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // probably problem here
        sceneLocationView.frame = view.bounds
        arView.frame = sceneLocationView.bounds
        
        sceneLocationView.addSubview(arView)
        view.addSubview(sceneLocationView)
        addPins()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        sceneLocationView.frame = view.bounds
    }
    
    override func viewWillAppear(_ animated: Bool) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            super.viewWillAppear(animated)
            self.sceneLocationView.run()
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        sceneLocationView.pause()
    }
    
    func addPins() {
        guard let currentLocation = currentLocation, currentLocation.horizontalAccuracy < 16 else {
            return DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
                self?.addPins()
            }
        }
        
        self.pins.forEach { pin in
            guard pin.isLocation else { return }
            guard let location = pin.location else { return assertionFailure() }
            guard let image = UIImage(named: pin.image) else { return assertionFailure() }
            
            let node = LocationAnnotationNode(location : location, image: image)
            
            node.scaleRelativeToDistance = true
            sceneLocationView.addLocationNodeWithConfirmedLocation(locationNode: node)
        }
    }
}

// if you want to test it, you can try to place these pins to a location where you can easily get coordinates from Google Earth.
struct RealityKitViewControllerRepresentable : UIViewControllerRepresentable {
    let pins = [Pin(image: "test", location: CLLocation(coordinate: CLLocationCoordinate2D(latitude: 0.03275742958, longitude: 0.32827424), altitude: 772.1489524841309), isLocation: true)]
    @Binding var arActivate : Bool
    
    func makeUIViewController(context: Context) -> RealityKitViewController {
        let viewController = RealityKitViewController(context, pins: pins)
        
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: RealityKitViewController, context: Context) {
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
}

class Coordinator: NSObject, ARSessionDelegate {
    weak var view: ARView?
 }
kx1ctssn

kx1ctssn1#

我解决了这个问题:没有解决办法。
使用SCNView作为一个子视图是一个非常可怕的想法,但我发现的每个答案都说“不”,似乎这个特性将一直悬而未决,直到Apple发布一个集成或其他东西。

相关问题