Load .obj to .scn with multiple sub-objects, textures, materials?

I'm currently working with large .obj files that contain multiple objects within, each with seperate 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?


I have my obj mtl and jpg's all in one directory where I'm also putting the scn scene.


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.

//...

// 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
}

// ...


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.


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 completly unresonable and I figure there must be a better way that I don't know about.

Replies

Hello,


The simplest course of action here would be to convert your .obj to a .usd using the usd converter (included with Xcode 10 command line tools). There are ways to import a .obj using Model/IO but as you know, it is pretty difficult/tedious when you have so many materials.