我目前在 Apple 的 SceneKit/Model I/O 中处理大型 .obj 文件,其中包含多个对象,每个对象都有单独的纹理和 Material 。这意味着我不能像许多其他表单帖子所建议的那样将一个单一的纹理应用于文件。有什么好的方法可以导入 Material 和贴图吗?
我将我的 obj mtl 和 jpg 都放在一个目录中,我也将 scn 场景放在该目录中。
代码目前遵循这种设计,我从它各自的位置访问它,将它加载到 MDLAsset 中,然后将它放入 SCNScene 中,它被保存回一个文件,以便稍后在代码中加载。
//...
// Get the mesh from the obj object
let asset = MDLAsset(url:url)
//asset.loadTextures()
guard let object = asset.object(at: 0) as? MDLMesh else {
fatalError("Failed to get mesh from obj asset.")
}
// Wrap the ModelIO object in a SceneKit object
let scene = SCNScene()
let node = SCNNode(mdlObject: object)
scene.rootNode.addChildNode(node)
// Get the document directory name the write a url for the object replacing its extention with scn
let dirPaths = FileManager().urls(for: .documentDirectory, in: .userDomainMask)
let fileUrl = dirPaths[0].appendingPathComponent(url.lastPathComponent.replacingOccurrences(of: ".obj", with: ".scn"))
// Write the scene to the new url
if !scene.write(to: fileUrl, delegate: nil) {
print("Failed to write scn scene to file!")
return nil
}
// ...
MDLAsset.loadTextures 函数没有文档,只会导致内存泄漏,因此在撰写本文时,它不是一个选项。手动打开模型并点击转换为 SCNScene 也不起作用,因为我仍然丢失了 Material 。此外,我希望它在代码中实现自动化,以允许在运行时下载和转换模型。
似乎没有内置的方法可以做到这一点,除了在代码中手动处理每个纹理和 Material ,当它只有一个完整的纹理时很容易,但这个模型可能有 100 种不同的 Material 。看起来需要我手动解析 obj/mtl,然后手动创建和分配 Material 。这似乎完全不合理,我认为一定有更好的方法,但我不知道。
最佳答案
当您通过模型 I/O 将 OBJ 文件作为 MDLAsset 导入时,它将作为一个或多个 MDLMeshes 的集合到达。网格将具有与其关联的 MDLMaterials,并且 MDLMaterial 将具有属性。这些属性将是数字、文件路径或图像。您需要迭代属性,并检查是否有路径。
https://developer.apple.com/documentation/modelio/mdlmaterialproperty
如果有,它可能是一个 fileURL,其内容与 OBJ 文件的关联 MTL 文件中的内容相同。
MDLScatteringFunction 中描述的属性对应于典型 MTL 文件中的各种属性。
https://developer.apple.com/documentation/modelio/mdlscatteringfunction
如果模型 IO 实际上可以找到 MTL 文件中引用的纹理,MDLAsset.loadTextures 将向该属性添加一个 MDLTextureSampler 值。
关于swift - 使用 SceneKit 和模型 I/O 中的多个子对象、纹理、 Material 将 .obj 加载到 .scn?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50517852/