iosswiftxcodescenekitusdz

Load 3d usdz model from network in Scenekit view does not work?


I am trying to load a 3d used model from network in my Scene kit view. The model gets downloaded properly and is saved in file but is not displayed in scene kit view. Here is my code. I am not getting any error. Not sure what exactly is the issue

import UIKit
import SceneKit

class ViewController: UIViewController,URLSessionDownloadDelegate {
    
    @IBOutlet weak var scnView: SCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        downloadSceneTask()
    }
    
    
    func downloadSceneTask(){
        
        //1. Get The URL Of The SCN File
        guard let url = URL(string: "url_to_load_3d_model") else { return }
        
        //2. Create The Download Session
        let downloadSession = URLSession(configuration: URLSession.shared.configuration, delegate: self, delegateQueue: nil)
        
        //3. Create The Download Task & Run It
        let downloadTask = downloadSession.downloadTask(with: url)
        downloadTask.resume()
    }
    
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        
        //1. Create The Filename
        let fileURL = getDocumentsDirectory().appendingPathComponent("nike.usdz")
        
        //2. Copy It To The Documents Directory
        do {
            try FileManager.default.copyItem(at: location, to: fileURL)
            
            print("Successfuly Saved File \(fileURL)")
            
            //3. Load The Model
            loadModel()
            
        } catch {
            
            print("Error Saving: \(error)")
            loadModel()
        }
        
    }
    
    func getDocumentsDirectory() -> URL {
        
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentsDirectory = paths[0]
        return documentsDirectory
        
    }
    
    func loadModel(){
        
        //1. Get The Path Of The Downloaded File
        let downloadedScenePath = getDocumentsDirectory().appendingPathComponent("nike.usdz")
        
        do {
            
            //2. Load The Scene Remembering The Init Takes ONLY A Local URL
            let modelScene =  try SCNScene(url: downloadedScenePath, options: nil)
            
            //3. Create A Node To Hold All The Content
            let modelHolderNode = SCNNode()
            
            //4. Get All The Nodes From The SCNFile
            let nodeArray = modelScene.rootNode.childNodes
            
            //5. Add Them To The Holder Node
            for childNode in nodeArray {
                modelHolderNode.addChildNode(childNode as SCNNode)
            }
            
            //6. Set The Position
            modelHolderNode.position = SCNVector3(0, 0, 0)
            
            //7. Add It To The Scene
            self.scnView.scene?.rootNode.addChildNode(modelHolderNode)
            
            
        } catch  {
            print("Error Loading Scene")
        }
        
    }
    
    
    
}

Solution

  • I loaded the model this way and it worked for me:

    import SceneKit.ModelIO
    
    func loadModel(){
        
        //1. Get The Path Of The Downloaded File
        let downloadedScenePath = getDocumentsDirectory().appendingPathComponent("nike.usdz")
        
        self.scnView.autoenablesDefaultLighting=true
        self.scnView.showsStatistics=true
        self.scnView.backgroundColor = UIColor.blue
        let asset = MDLAsset(url: downloadedScenePath)
        asset.loadTextures()
        let scene = SCNScene(mdlAsset: asset)
        self.scnView.scene=scene
        self.scnView.allowsCameraControl=true
    }