I observed a very strange behavior where a copied SCNGeometry doesn't work immediately. I had to wait one run-loop (DispatchQueue.main.async
) in order to make it work. Is it a bug or am I doing something wrong?
Here's my code:
func helper_cloneGeo(geo: SCNGeometry) -> SCNGeometry {
let copiedGeo = geo.copy() as! SCNGeometry
copiedGeo.materials = geo.materials.map { $0.copy() as! SCNMaterial }
return copiedGeo
}
override init() {
super.init()
let geo = readGeo(fn: "alcohol.usdz", texture: "texture.png").geometry!
// HERE!!!
// SCNGeometry is only clone-able after async!!
// DispatchQueue.main.async {
let copiedGeo = self.helper_cloneGeo(geo: geo)
let newNode = SCNNode(geometry: copiedGeo)
self.rootNode.addChildNode(newNode)
// }
}
The readGeo
is just a helper function that reads a 3d model file, which should be correct, because the original (not cloned) node works.
You can download my sample project here: https://drive.google.com/file/d/1kYyqCAJXnXqpZc6vaaXORe_UVmLH6wHL/view?usp=sharing
In this project, when you run it, it shows the model. Then if you comment out the DispatchQueue.main.async
(like in the code above), the model won't be shown.
By doing some basic debugging, you can see that geo.elements
and geo.sources
are all empty, and this is why nothing got copied. I suspect that SCNNode.flattenedClone
(which you used in readGeo
) somehow made a node with a "lazy" geometry that doesn't get immediately created.
If you don't want to do this asynchronously, you can always just run the run loop yourself.
let geo = readGeo(fn: "alcohol.usdz", texture: "texture.png").geometry!
RunLoop.main.run(until: .now) // run the run loop for just one iteration
let copiedGeo = self.helper_cloneGeo(geo: geo)
let newNode = SCNNode(geometry: copiedGeo)