Loading an .Obj model file

I created a simple model in an obj and attempted to load it as an Asset


let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("Torus", ofType: "obj")
var torusModel = MDLAsset(URL: NSURL(string: path!)!)


Error message: Could not load data from /Users/jason/Library/Developer/Xcode/DerivedData/MetalDemo-auxpwrdxoklbrpbtkxmrhkecewhb/Build/Products/Debug/Met ... orus.obj

Answered by MoreLightning in 8483022

Here's the working code:


        let bundle = NSBundle.mainBundle()
        let path = bundle.pathForResource("Model", ofType: "obj")
        let url = NSURL(fileURLWithPath: path!)
        let asset = MDLAsset(URL: url)
   
        let scene = SCNScene(MDLAsset: asset)


Step 1) Get the path of the model file

Step 2) Load the file into a MDLAsset

Step 3) Create a SCNScene with the asset (alternatively you can find the model inside the asset and add it to an existing scene)

Maybe a problem with the file? I created a Torus in Blender and exported it as a triangulated obj file. Seemed to load fine.

Code:

let urlForAsset = NSBundle.mainBundle().URLForResource("Torus", withExtension: "obj")!
let boxAsset = MDLAsset(URL: urlForAsset)


Console:

2015-06-09 17:53:06.669 MetalX[1406:75348] Creating vertex buffer for 3456 vertices
2015-06-09 17:53:06.669 MetalX[1406:75348] Adding 2 submeshes


I'm tried this on OSX

when I ran your code I saw the actual problem 🙂


when creating the URL I needed to specifically create a file URL.


//var torusModel = MDLAsset(URL: NSURL(string: path!)!) 
let torusModel = MDLAsset(URL: NSURL.fileURLWithPath(path!))


Loaded just fine after that

Accepted Answer

Here's the working code:


        let bundle = NSBundle.mainBundle()
        let path = bundle.pathForResource("Model", ofType: "obj")
        let url = NSURL(fileURLWithPath: path!)
        let asset = MDLAsset(URL: url)
   
        let scene = SCNScene(MDLAsset: asset)


Step 1) Get the path of the model file

Step 2) Load the file into a MDLAsset

Step 3) Create a SCNScene with the asset (alternatively you can find the model inside the asset and add it to an existing scene)

Hi,


when I try to create a SCNScene with:

let scene = SCNScene(MDLAsset: asset)

I get the error: Incorrect argument label in call (have 'MDLAsset:', expected 'named:') Xcode also doesn't give me an autosuggestion for MDLAsset.

I use XCODE Version 7.0 (7A220) deployment ios 9.0

Have anyone an idea why this code doesn't work on my machine ?

I came into this problem when I wanted to make my own obj loader in opengl ES or GLKIT or NinvehGL, ....

Though I succeeded in loading and rendering a small object with limitted vertices, I had difficulty with big Obj files.

So I Came to this problem, and found out about model IO, and then scenekit 😝

Anyhow, after a minute of trial and error, I converted the obj file to scn file, and loaded with SCNscene,

The code above

let scene = SCNScene(MDLAsset: asset)

as you mentioned didn't work for me with Obj file.

And then I tried with SCN file directly using the scenkit, and it worked

Then surprisingly scenekit worked with obj file directly. (and it automatically loaded texture / mtl)

My guess is maybe ModelIO is more for exporting (and importing) For file conversion. I hope at one point they support VRML files as well.


So the code that helped me : (Be sure you Obj file is in the bundle in build phase of the target settings)

let scene = SCNScene(named: "youfile.obj")!
let sceneView = self.view as! SCNView
sceneView.scene = scene



PS. I have no idea how swift works, but it is a very easy language, and I could get the project I wanted in a few minutes!

Hi nabi,


Thanks for posting and suggesting future features. Please feel free to file radars if there is something you find isn't working or something you'd like to see in the future.


Any asset you load via Model I/O should be loadable via SceneKit as well. Just as UIKit can load images that you could have loaded yourself via Image I/O. They are related and work together seamlessly.


Quoting the programming guide at https://developer.apple.com/library/ios/documentation/ModelIO/Reference/ModelIO_Framework/index.html:


'The Model I/O framework provides a system-level understanding of 3D model assets and related resources. You can use this framework to import and export assets from and to a variety of industry standard file formats supported by popular authoring tools and game engines. You can also use Model I/O to generate or process model and texture data—for example, to create subdivision surfaces, bake ambient occlusion textures, or generate light probes. Model I/O can share data buffers with the MetalKit, GLKit, and SceneKit frameworks to help you load, process, and render 3D assets efficiently.'


If SceneKit does everything you want then by all means stay there and you'll implicitly be taking advantage of Model I/O's features.


Cheers

With the import statement:

import SceneKit.ModelIO

you can load a .obj file with

let asset = MDLAsset(URL: fileURL!)
let scene = SCNScene(MDLAsset: asset)


I'm also trying to write a .obj loader and map the file to SceneKit. My goal is to create from each MDLSubmesh a Node with geometry.

The code below works for small files, but the memory consumption increasing enormous with every MDLSubmesh until the app crashes.

let mesh = asset.objectAtIndex(0) as! MDLMesh
let vertexBuffer = mesh.vertexBuffers[0]
let descripter = mesh.vertexDescriptor
let submeshes = mesh.submeshes

for var a = 0; a < submeshes.count; a++ {
   let submesh = submeshes[a] as! MDLSubmesh
   let singleMesh = MDLMesh(vertexBuffer: vertexBuffer, vertexCount: mesh.vertexCount, descriptor: descripter, submeshes:  [submesh])
   let geometry = SCNGeometry(MDLMesh: singleMesh)
   
   let Node = SCNNode(geometry: geometry)
   self.scene.rootNode.addChildNode(Node)
}


So I'm searching for a better solution.

Loading an .Obj model file
 
 
Q