Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I load a Data object into a SCNScene?

I want to load a 3d usdz blob into a view, but since I only have the data object, I'm trying to initialize the scene with that with no luck.

To that, I initialize the SCNSceneSource() and then open it using .scene().

Now what I don't understand: If I use a URL and load the scene directly - it works. If I use a Data object on the same URL it doesn't.

Apple docs says, the data should be of type NSData but that seems wrong.

import SceneKit

let url = URL(string: "file:///Users/thilo/Desktop/Input/UU2.usdz")!
// working
let src_ok = SCNSceneSource(url: url)
let scn_ok = src_ok?.scene(options: nil, statusHandler: {
    a,b,c,d in print("OK: \(a) \(b) \(String(describing: c)) \(d) ")
})
print("Ok: \(scn_ok)")

// Not working?
let data    = try! Data(contentsOf: url)
let src_bad = SCNSceneSource(data: data)
let scn_bad = src_bad?.scene(options: nil, status handler: {
    a,b,c,d in print("BAD: \(a) \(b) \(String(describing: c)) \(d) ")
})
print("Failed: \(scn_bad)")

running on Playground says:

Ok: Optional(<SCNScene: 0x6000038e1200>)
BAD: 0.0 SCNSceneSourceStatus(rawValue: 4) nil 0x000000016fa948bf 
BAD: 0.0 SCNSceneSourceStatus(rawValue: 4) nil 0x000000016fa942af 
BAD: 0.0 SCNSceneSourceStatus(rawValue: -1) Optional(Error Domain=NSCocoaErrorDomain Code=260 "Could not load the scene" UserInfo={NSLocalizedDescription=Could not load the scene, NSLocalizedRecoverySuggestion=An error occurred while parsing the COLLADA file. Please check that it has not been corrupted.}) 0x000000016fa942af 
Failed: nil

What am I missing?

like image 804
thilo Avatar asked Mar 02 '26 17:03

thilo


1 Answers

SCNSceneSource doesn't support .usdz in Data context

Official documentation says that SCNSceneSource object supports only .scn, .dae and .abc file formats. But it turns out that SceneKit doesn't support URL-loading of .usdz only in the context of working with Data. Thus, when working with Data, use files in the .scn format.

import SceneKit
import Cocoa

class GameViewController : NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let url = URL(string: "file:///Users/swift/Desktop/ship.scn") {
    
            let data = try! Data(contentsOf: url)
            let source = SCNSceneSource(data: data)
    
            let sceneView = self.view as! SCNView
            sceneView.scene = source?.scene()
        }
    }
}

To load .usdz using URL, try SCNSceneSource.init?(url: URL)

class GameViewController : NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let url = URL(string: "file:///Users/swift/Desktop/ship.usdz") {
    
            let source = SCNSceneSource(url: url)
    
            let sceneView = self.view as! SCNView
            sceneView.scene = source?.scene()
        }
    }
}

Or use SCNScene object to load .usdz model

class GameViewController : NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = URL(fileURLWithPath: "/Users/swift/Desktop/ship.usdz")

        do {
            let scene = try SCNScene(url: url)
            let sceneView = self.view as! SCNView
            sceneView.scene = scene
            sceneView.autoenablesDefaultLighting = true
        } catch {
            print(error.localizedDescription)
        }
    }
}
like image 123
Andy Jazz Avatar answered Mar 05 '26 09:03

Andy Jazz