SceneKit – Dynamically Loading Models from a Web Service

When I had originally set out to create Nabaal Shipyards – I was under the incorrect assumption that just being able to unpack and load the .zip file I downloaded into a .scnassets folder in the Document folder of an iOS application would be enough. I was wrong! Turns out, iOS does a bunch of optimizations to a .scnassets folder through the process of building in XCode.

So, a quick google revealed that there was a command line that you needed to execute against your .scnassets folder before you could just dynamically load a node from file into your scene.

Very simply…

cd /Applications/Xcode/Contents/Developer/usr/bin

copySceneKitAssets product-1.scnassets/ -o product-1-optimized.scnassets

And you’re done! No fuss, your Collada scene is ready to load. There is however, a slight gotcha that I had to experience firsthand when working with the .zip after you’ve downloaded the asset to your device….

 

Not so simply…

You need to load the scene from file as below. Make sure that you’re passing in a NSURL or you’ll be in a world of hurt (especially if you’re passing a NSString path) :

NSURL * documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];

documentsDirectoryURL = [documentsDirectoryURL URLByAppendingPathComponent:@”product-1-optimized.scnassets/cube.dae”];

SCNSceneSource *sceneSource = [SCNSceneSource sceneSourceWithURL:documentsDirectoryURL options:nil];

But now you need to actually get at the node in the scene. You’d want to run something like:

var sceneNode : SCNNode = sceneSource.entryWithIdentifier(props.1, withClass: SCNNode.self) as! SCNNode

But if you’re unsure of what the name of your node might be:

sceneSource.identifiersOfEntriesWithClass(SCNNode.self)

This will return a list of names of nodes for you that you can look at.