我有一个包含 3 个几何形状的 3D 模型,如下所示
这是我从 USDZ 文件创建此类 SCNNode 的代码:
private func readGeo(fn: String) -> SCNNode {
let bundle = Bundle.main
let url = bundle.url(forResource: fn, withExtension: nil)!
let asset = MDLAsset(url: url)
asset.loadTextures()
let object = asset.object(at: 0)
let node = SCNNode(mdlObject: object)
return node
}
然后我需要展平节点,因为我想让它只是一个几何体,这样更容易附加物理体。所以我将返回更改为:
return node.flattenedClone()
几何形状的位置似乎不正确,如下所示:(看到盖子伸出来)
您可以在此处下载示例项目:https://drive.google.com/file/d/1ewudz3A2NKeW-72bXRPJJtphyRMae-1e/view?usp=sharing
编辑:
我意识到展平后子节点的位置发生了变化。它们最初位于非零坐标,但在展平后,它们被定位为好像位于零坐标。我不知道为什么
我相信这是 SceneKit 中的一个错误,如果节点没有几何图形,则变换将被忽略。我能够通过使用 DFS 将变换传递到子节点来修复它:
fileprivate extension SCNNode {
// pre-process it before taking the flattenedClone()
var preProcessed: SCNNode {
let clone = self.clone()
Self.dfs_passDownTransform(node: clone)
return clone
}
static func dfs_passDownTransform(node: SCNNode) {
// If it's an empty node with just transform, we want to pass the transform to its immediate children
if node.geometry == nil && !SCNMatrix4IsIdentity(node.transform) {
for child in node.childNodes {
child.transform = SCNMatrix4Mult(child.transform, node.transform)
}
node.transform = SCNMatrix4Identity
}
for child in node.childNodes {
dfs_passDownTransform(node: child)
}
}
}