使用SceneKit&中的多个子对象,纹理,材质将.obj加载到.scn。模型I / O?

时间:2018-05-24 20:40:24

标签: swift xcode scenekit .obj modelio

我目前正在使用Apple的SceneKit / Model I / O中的大型.obj文件,其中包含多个对象,每个对象都有不同的纹理和材质。这意味着我不能像许多其他表单帖子所建议的那样将单个纹理应用于文件。有没有一种很好的方法来导入材料和纹理?

我将我的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也不起作用,因为我仍然丢失了材料。另外,我希望在代码中实现自动化,以便在运行时下载和转换模型。

似乎除了在代码中手工完成每个纹理和材质之外没有内置的方法,这只是一个完整的纹理,但这个模型可能有100种不同的材质。看起来它需要我手动解析obj / mtl然后手动创建和分配材料。这似乎完全不合理,我认为必须有一种我不了解的更好的方法。

1 个答案:

答案 0 :(得分:0)

当您通过模型I / O将OBJ文件作为MDLAsset导入时,它将作为一个或多个MDLM哈希的集合到达。网格将具有与之关联的MDLMaterials,而MDLMaterial将具有属性。这些属性将是数字,文件路径或图像。您需要迭代属性,并检查是否存在路径。

https://developer.apple.com/documentation/modelio/mdlmaterialproperty

如果存在,则可能是fileURL的内容与OBJ文件的相关MTL文件中的内容相同。

MDLScatteringFunction中描述的属性与典型MTL文件中的各种属性相对应。

https://developer.apple.com/documentation/modelio/mdlscatteringfunction

如果Model IO实际上可以找到MTL文件中引用的纹理,则MDLAsset.loadTextures将向该属性添加MDLTextureSampler值。