7
votes

I have downloaded the .usdz models provided by Apple: https://developer.apple.com/arkit/gallery/

But now, I want to create a SCNNode with one of these models, so I am doing this to obtain the node:

guard let urlPath = Bundle.main.url(forResource: "retrotv", withExtension: "usdz") else {
    return
}
let mdlAsset = MDLAsset(url: urlPath)
let modelRootNode = SCNScene(mdlAsset: mdlAsset).rootNode

Then I add it to the scene and the result is this:

enter image description here

Why does it have no textures?

I have the downloaded .usdz files into a folder in my project directory as you can see:

enter image description here

3

3 Answers

13
votes

The correct way to add the .USDZ object is actually creating the scene with the file's URL:

 let scene = try! SCNScene(url: usdzURL, options: [.checkConsistency: true])

Or even creating via Reference Node:

 let referenceNode = SCNReferenceNode(url: usdzURL)
 referenceNode.load()
1
votes

It is possible to load a usdz into an ARKit scene.

It's important to have the these imports

import ARKit
import SceneKit
import SceneKit.ModelIO

Load the usdz via a URL.

guard let urlPath = Bundle.main.url(forResource: "retrotv", withExtension: "usdz") else {
    return
}
let mdlAsset = MDLAsset(url: urlPath)
// you can load the textures on an MDAsset so it's not white
mdlAsset.loadTextures()

Wrap it in a node.

let asset = mdlAsset.object(at: 0) // extract first object
let assetNode = SCNNode(mdlObject: asset)

You can now attach this node in ARKit. You would need to scale and orientate the object to where you want it in the real world, but that code depends on what you are trying to do, so I've left that out.

0
votes

The correct way to access the Internal USDZ Node

func usdzNodeFrom(file: String, exten: String, internal_node: String) -> SCNNode? {
    let rootNode = SCNNode()
    let scale = 1

    guard let fileUrl = Bundle.main.url(forResource: file, withExtension: exten) else {
        fatalError()
    }
    
    let scene = try! SCNScene(url: fileUrl, options: [.checkConsistency: true])
    let node = scene.rootNode.childNode(withName: internal_node, recursively: true)!
    node.name = internal_node
    let height = node.boundingBox.max.y - node.boundingBox.min.y
    node.position = SCNVector3(0, 0, 0)
    tNode.scale = SCNVector3(scale, scale, scale)
    rootNode.addChildNode(tNode)
    return rootNode
}

Further texture not displaying is different Issue, could be addressed by adding lightning to environment.