iOS - 如何将MTL纹理文件应用于OBJ模型

3
我正在使用ModelI/O展示3D模型。这是我的代码:

// Load the .OBJ file
    guard let url = Bundle.main.url(forResource: "agera r", withExtension: "obj") else {
        fatalError("Failed to find model file.")
    }

    let asset = MDLAsset(url:url)
    guard let object = asset.object(at: 0) as? MDLMesh else {
        fatalError("Failed to get mesh from asset.")
    }

    // Create a material from the various textures
    let scatteringFunction = MDLScatteringFunction()
    let material = MDLMaterial(name: "baseMaterial", scatteringFunction: scatteringFunction)
    let textureFileName = "agera_r.mtl"
    material.setTextureProperties([.baseColor: textureFileName])

    // Apply the texture to every submesh of the asset
    for submesh in object.submeshes!  {
        if let submesh = submesh as? MDLSubmesh {
            submesh.material = material
        }
    }

    // Wrap the ModelIO object in a SceneKit object
    let node = SCNNode(mdlObject: object)
    let scene = SCNScene()
    scene.rootNode.addChildNode(node)

    // Set up the SceneView
    sceneView.autoenablesDefaultLighting = true
    sceneView.allowsCameraControl = true
    sceneView.scene = scene
    sceneView.backgroundColor = UIColor.black
}
extension MDLMaterial {
func setTextureProperties(_ textures: [MDLMaterialSemantic:String]) -> Void {
    for (key,value) in textures {
        guard let url = Bundle.main.url(forResource: value, withExtension: "") else {
            fatalError("Failed to find URL for resource \(value).")
        }
        let property = MDLMaterialProperty(name:value, semantic: key, url: url)
        self.setProperty(property)
    }
}

问题是当应用程序运行时,3D模型可以显示,但.mtl纹理文件没有被应用。如何解决这个问题?感谢大家。

1个回答

0

这行代码的主要问题是:

let textureFileName = "agera_r.mtl"
material.setTextureProperties([.baseColor: textureFileName])

你应该传递纹理文件的URL而不是.mtl文件的URL。

这段代码对我来说运行良好:

Objective-C

MDLScatteringFunction *scatFunction = [MDLScatteringFunction new];
MDLMaterial *mdlMaterial = [[MDLMaterial alloc] initWithName:@"material" scatteringFunction:scatFunction];
MDLMaterialProperty *bcProperty = [[MDLMaterialProperty alloc] initWithName:@"BaseColor" semantic:MDLMaterialSemanticBaseColor URL:textureFileURL];
[mdlMaterial setProperty:bcProperty];
SCNMaterial *material = [SCNMaterial materialWithMDLMaterial:mdlMaterial];
node.geometry.firstMaterial = material;

SWIFT

let scatFunction = MDLScatteringFunction()
let material = MDLMaterial(name: "material", scatteringFunction: scatFunction)
material.setTextureProperties(textures: [.baseColor: "model/texture.png"])
mesh.submeshes?.forEach {
    if let submesh = $0 as? MDLSubmesh {
        submesh.material = material
    }
}

baseNode = SCNNode(mdlObject: mesh)

附注:这是两种稍微不同的方法来完成该任务。

更新:

let baseNode = SCNScene(named: "mesh.obj")!.rootNode

你也可以尝试使用这种方法。如果我记得正确的话,它将连接.mtl文件和其他纹理。(如果.obj文件中写入的.mtl文件路径有效,并且.mtl中纹理的路径也有效)


谢谢您的回复。那么除了使用png纹理文件,没有其他方法可以替代mtl文件吗? - Duc Phan
我不知道如何在运行时使用.mtl文件来完成它。如果您可以在设计时完成,您可以手动将此.obj添加到.scene文件中,它将使用.mtl文件和所有其他纹理。另外,我为您添加了另一个变体。 - Joker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接