admin管理员组文章数量:1134237
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:
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.
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.
2 Answers
Reset to default 1By 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)
Not sure why but this works. Likely related to SceneKit internal implementation, as Sweeper suggested.
func helper_cloneGeo(geo: SCNGeometry) -> SCNGeometry {
return SCNNode(geometry: geo).clone().geometry!
}
本文标签: iosCopied SCNGeometry does not work immediately in current runloopStack Overflow
版权声明:本文标题:ios - Copied SCNGeometry does not work immediately in current runloop - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736783935a1952752.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
geo.elements
andgeo.sources
are all empty, and this is why nothing got copied. I suspect thatflattenedClone
somehow made a node with a "lazy" geometry. If you don'tflattenedClone
and just clonenode.childNodes.first?.childNodes.first?.geometry
. It works as expected. – Sweeper Commented Jan 7 at 19:00flattenedClone
it in my real project, so that a node only has 1 geometry which is easier to deal with, regardless of usdz file setup (which i cant control since i buy them in batch from different studios) – OMGPOP Commented Jan 7 at 20:18DispatchQueue.main.async
already works. – Sweeper Commented Jan 7 at 20:43DispatchQueue.main.async
, since i have to add the models in the init of my container node. i could add the child node async'ly, but i have bunch of infras relying on the container being setup properly. I could load the assets on app launch, but that's also quite a huge change due to the scale of my infra – OMGPOP Commented Jan 7 at 23:37