I'm creating AR app (Xcode 10.1, Swift 4.2.1).
I'd like to load USDZ
3D object into an empty SceneKit's scene and then process it as MDL
mesh.
Here's my code:
import ARKit
import SceneKit.ModelIO
let scene = SCNScene(named: "art.scnassets/emptyScene.scn")!
if let filePath = Bundle.main.path(forResource: "Helicopter",
ofType: "usdz",
inDirectory: "art.scnassets") {
let refURL = URL(fileURLWithPath: filePath)
let refNode = SCNReferenceNode(url: refURL)
refNode?.load()
scene.rootNode.addChildNode(refNode!)
}
let helicopterGeo = refNode!.geometry
let mdlMesh = MDLMesh(scnGeometry: helicopterGeo!) // ERROR APPEARS HERE
try! mdlMesh.makeVerticesUniqueAndReturnError()
let flattenedGeometry = SCNGeometry(mdlMesh: mdlMesh)
let flattenedNode = SCNNode(geometry: flattenedGeometry)
scene.rootNode.addChildNode(flattenedNode)
But compiler gives me an error:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
The question is: what approach should I use to assign a "Helicopter.usdz"
geometry to a helicopterGeo
constant?
Help me find a workaround, please!
You can download USDZ
file for testing HERE.
This should work:
var scene: SCNScene!
if let filePath = Bundle.main.path(forResource: "Helicopter",
ofType: "usdz",
inDirectory: "art.scnassets") {
let refURL = URL(fileURLWithPath: filePath)
let mdlAsset = MDLAsset(url: refURL)
scene = SCNScene(mdlAsset: mdlAsset)
}
SCNReferenceNode
only works for .scn files. You can then get the geometry from a child node of the rootNode
of the scene
.
let helicopterNode = scene.rootNode.childNode(withName: "helicopter", recursively: true)
let geometry = helicopterNode.geometry!
Using one of the files from the AR Quick Look Gallery I managed to get this code to work. The main problem that I had was with the name of the specific child node, there was one called "RetroTV" but it did not have any geometry attached to it, it was just the parent for both "RetroTVBody" and "RetroTVScreen." The only problem is that it isn't loading the textures for the geometry.
var scene: SCNScene!
if let filePath = Bundle.main.path(forResource: "retrotv",
ofType: "usdz",
inDirectory: "art.scnassets") {
let refURL = URL(fileURLWithPath: filePath)
let mdlAsset = MDLAsset(url: refURL)
scene = SCNScene(mdlAsset: mdlAsset)
let tvNode = scene.rootNode.childNode(withName: "RetroTVBody", recursively: true)
let geometry = tvNode!.geometry!
} else {
print("invalid path!")
}
The above code also works with the tvNode
and geometry
declarations outside of the if let
statement.
I don't have an exact answer, but what I would do in your situation would be to examine the hierarchy of refNode
.
Place a breakpoint after it's loaded and use the debugger to see if it's got any children. Do those children have any geometries? Do they have any children with geometry?
When creating 3D assets, sometimes multiple sections will be grouped on a parent node, and in many cases that parent node is empty.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With