title: Load .obj to .scn with multiple sub-objects, textures, materials in SceneKit & Model I/O?
body: <p>I'm currently working with large .obj files in Apple's SceneKit/Model I/O that contain multiple objects within, each with separate textures and materials. This means I cannot apply one single texture to the file like many other form posts suggest. Is there a good way to import in the the materials and textures?</p>
  
  <p>I have my obj mtl and jpg's all in one directory where I'm also putting the scn scene.</p>
  
  <p>The code currently follows this design, where I access it from its respective location, load it into a MDLAsset then place it into a SCNScene where it is saved back to a file to be loaded in later in the code.</p>
  
  <pre><code>//...  
  
  // Get the mesh from the obj object  
  let asset = MDLAsset(url:url)  
  //asset.loadTextures()  
  guard let object = asset.object(at: 0) as? MDLMesh else {  
      fatalError("Failed to get mesh from obj asset.")  
  }  
  
  // Wrap the ModelIO object in a SceneKit object  
  let scene = SCNScene()  
  let node = SCNNode(mdlObject: object)  
  scene.rootNode.addChildNode(node)  
  
  // Get the document directory name the write a url for the object replacing its extention with scn  
  let dirPaths = FileManager().urls(for: .documentDirectory, in: .userDomainMask)  
  let fileUrl = dirPaths[0].appendingPathComponent(url.lastPathComponent.replacingOccurrences(of: ".obj", with: ".scn"))  
  
  // Write the scene to the new url  
  if !scene.write(to: fileUrl, delegate: nil) {  
      print("Failed to write scn scene to file!")  
      return nil  
  }  
  
  // ... 
  </code></pre>
  
  <p>The MDLAsset.loadTextures function has no documentation and only causes a memory leak so at the time of this post, it's not an option. Opening the model by hand and hitting the convert to SCNScene dosn't work either as I still lose the materials. Additionally I want this to be automated in code to allow for downloading and conversion of models at runtime.</p>
  
  <p>It seems like there is not built in way to do this except to do each texture and material by hand in the code, which is easy when it's only one complete texture but this model might have 100 different materials. It looks like it requires me to parse the obj/mtl manually and then create and assign the materials by hand. This seems completely unreasonable and I figure there must be a better way that I don't know about.</p>