How to export the contents of a SceneKit scene under MacOS

714 Views Asked by At

I'm getting unexpected results when exporting the contents of a SceneKit scene to a Collada (.dae) file. Here's what I have so far.

I created a simple scene with 5 spheres along the x-axis

var x:CGFloat = 0
for i in 0...4 {
    let sphere = SCNNode(geometry: SCNSphere(radius: 1))
    sphere.name = "sphere\(i+1)"
    sphere.position = SCNVector3(x: x, y: 0, z: 0)
    exportScene.rootNode.addChildNode(sphere)
    x += 2
}

and exported the contents with

let url = URL(fileURLWithPath: pathName)
exportScene.write(to: url, options: nil, delegate: nil) { totalProgress, error, stop in
    print("Export progress: \(totalProgress * 100.0)%")
}

When I load the .dae file into a 3D program (Cheetah 3D), I expect to have 5 identical spheres along the x-axis but instead the following appears. I had similar issues exporting to a .obj file.

enter image description here

The answer in the following says "Keep in mind that DAE doesn't handle all features of SceneKit, though" but the doesn't go into the limitations of the file format.

Easiest method to export a SceneKit scene as a Collada .dae file?

Q: Does anyone know how to export the contents of a SceneKit scene?

1

There are 1 best solutions below

6
Andy Jazz On

macOS app

Looks like the beginning of SceneKit's sunset.

Neither .dae nor .obj formats are properly generated in SceneKit macOS app. Moreover, an .usdz format is not exported at all.

iOS app

In iOS app, only the .usdz format is exported correctly (it kept all nodes' transforms and names of the SCN scene). This .usdz can be opened in Maya. But .dae and .obj files contain only one sphere instead of five.

If you have problems with USDZ's textures in Maya, read this post please.

enter image description here


Note that .usdz is not exported correctly when using for-in loop.

import SceneKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let sceneView = self.view as! SCNView
        sceneView.backgroundColor = .black
        sceneView.scene = SCNScene()
        let url = URL(string: "file:///Users/swift/Desktop/model.usdz")!

        let sphere1 = SCNNode(geometry: SCNSphere(radius: 0.5))
        sphere1.position = SCNVector3(x: -2, y: 0, z: 0)
        sceneView.scene!.rootNode.addChildNode(sphere1)
        
        // ...sphere2, sphere3, sphere4...
        
        let sphere5 = SCNNode(geometry: SCNSphere(radius: 0.5))
        sphere5.position = SCNVector3(x: 2, y: 0, z: 0)
        sceneView.scene!.rootNode.addChildNode(sphere5)
            
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            sceneView.scene?.write(to: url, delegate: nil) { (prgs, _, _) in
                print("Export progress: \(prgs * 100.0)%")
            }
        }
    }
}

P. S.

Tested it on macOS 13.0 Ventura, Xcode 14.1, iOS 16.1 Simulator.