SceneKit加载.obj模型时如何获取所有子网格名称?
如何用SceneKit+ModelIO获取.obj模型的子网格名称
当然可以通过SceneKit结合ModelIO获取.obj文件里的所有子网格/部件名称!从你贴的代码和控制台输出来看,你其实已经离目标很近了,咱们来理清楚怎么操作:
确认可行性
.obj格式的子网格名称会被ModelIO完整解析并保留,你可以直接从MDLSubmesh对象,或者对应的SCNGeometry、SCNNode上获取这些名称。
从你的代码和输出分析
看你控制台打印的object.childNodes结果,里面的节点已经带有对应的子网格名称了:
object.childNodes==>[<SCNNode: 0x1c41e9300 'default' | geometry=<SCNGeometry: 0x1c5339280 'default' | 6 elements> | no child>, <SCNNode: 0x1c41f5a00 | geometry=<SCNGeometry: 0x1c5339320 'Obj1'> | no child>, ...]
这里的'default'、'Obj1'到'Obj6'就是.obj文件里各个子网格的名称,说明ModelIO已经成功读取到了这些信息。
优化代码直接获取子网格名称
你可以在循环处理子网格的时候,直接从MDLSubmesh的name属性拿到子网格名称,还能把这个名称赋值给对应的SCNGeometry和SCNNode,方便后续操作。修改后的代码如下:
// Here Obj url let url = URL(string: "https://s3.ap-south-1.amazonaws.com/p9-platform/DAE/barware_s11624.obj")! let asset = MDLAsset(url: url) let scene = SCNScene(mdlAsset: asset) guard let mesh = asset.object(at:0) as? MDLMesh else { print("无法获取MDLMesh对象") return } let vertexBuffer = mesh.vertexBuffers[0] let descriptor = mesh.vertexDescriptor let submeshes = mesh.submeshes for index in 0..<(submeshes?.count ?? 0) { guard let submesh0 = submeshes![index] as? MDLSubmesh else { continue } // 获取子网格的原始名称,没有的话设置默认名称 let submeshName = submesh0.name ?? "Unnamed_Submesh_\(index)" let singleMesh = MDLMesh(vertexBuffer: vertexBuffer, vertexCount: mesh.vertexCount, descriptor: descriptor, submeshes: [submesh0]) let geometry = SCNGeometry(mdlMesh: singleMesh) // 给几何对象设置子网格名称 geometry.name = submeshName let node = SCNNode(geometry: geometry) // 给节点设置子网格名称,方便后续查找或操作 node.name = submeshName scene.rootNode.addChildNode(node) // 打印子网格名称,直观查看结果 print("子网格 \(index) 名称:\(submeshName)") } print("scene ===>\(scene.rootNode)")
补充说明
- 如果你的.obj文件里的子网格本身有自定义命名,ModelIO会直接把这个名称赋值给
MDLSubmesh.name; - 如果子网格没有命名,
submesh0.name会返回nil,这时候可以像代码里那样设置一个默认名称,避免空值问题; - 给
SCNNode和SCNGeometry设置名称后,后续你可以通过scene.rootNode.childNode(withName: "Obj1", recursively: true)快速找到对应的部件,进行隐藏、修改材质等操作。
内容的提问来源于stack exchange,提问作者Lanover Solutions
相关产品推荐
相关产品推荐

