iosswiftswiftuiscenekitusdz

SceneKit – Camera does not see a model when rendering in SwiftUI


I have a USDZ model that when imported in to SceneKit scene graph shows fine, if I set the preview to show from the cameras perspective it is in frame. However when I run it via SwiftUI preview, on simulator or on device it does not render. I've turned on camera controls on the simulator to look over the scene and it's simply not rendering rather than out of frame.

enter image description here

enter image description here

import SceneKit

struct HomeScreen: View {
    private var userDefaults: UserDefaults?
    var scene = SCNScene(named: "MyScene.scn")
    var cameraNode: SCNNode? {
        scene?.rootNode.childNode(withName: "camera", recursively: false)
    }
    var body: some View {
        VStack {
            
            SceneView(
                scene: scene,
                pointOfView: cameraNode,
                options: [.allowsCameraControl]
            )
        }
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        HomeScreen()
    }
}

Solution

  • SCN scene

    Loading a .scn model using SwiftUI's SceneView is as simple as that. Model is centered in frustum.

    If you don't use .autoenablesDefaultLighting option, the background will not be visible.

    import SwiftUI
    import SceneKit
    
    struct ContentView: View {
        
        var scene = SCNScene(named: "art.scnassets/ship.scn")
    
        var options: SceneView.Options = [.autoenablesDefaultLighting,
                                          .allowsCameraControl ]   
        var body: some View {
            ZStack {
                SceneView(scene: scene, options: options)
                    .ignoresSafeArea()
            }
        }
    }
    

    enter image description here


    USDZ model

    .usdz models are centered in SceneKit's camera frustum as well. However, in SceneKit + SwiftUI or in SceneKit + UIKit, you are obliged to turn a lighting on for .usdz models.

    var scene = SCNScene(named: "gramophone.usdz")
    
    var options: SceneView.Options = [.autoenablesDefaultLighting,
                                      .allowsCameraControl ]
    
    var body: some View {
        ZStack {
            SceneView(scene: scene, options: options).ignoresSafeArea()
            let _ = scene?.background.contents = UIColor.black
    
        }
    }
    

    If your model is rendered out of a center of a screen, there might be another invisible node in that framing. Or model's pivot point is offset.

    enter image description here