【问题标题】:ios - How to apply mtl texture file to OBJios - 如何将 mtl 纹理文件应用于 OBJ
【发布时间】:2018-10-18 20:46:59
【问题描述】:

我正在使用 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 纹理文件不适用于它。如何解决这个问题?谢谢大家。

【问题讨论】:

    标签: ios 3d scenekit


    【解决方案1】:

    这几行的主要问题:

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

    您应该将 URL 传递给纹理文件,而不是 .mtl 文件 URL。 这段代码对我来说很好用:

    目标-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文件,没有别的办法了吗?
    • 我不知道如何在运行时使用 .mtl 文件进行操作。如果你能在设计时做到这一点,你可以在 .scene 文件中手动添加这个 .obj ,它将使用 .mtl 文件和所有其他纹理。我还为您添加了另一个变体。
    猜你喜欢
    • 2021-07-20
    • 1970-01-01
    • 2013-07-16
    • 2017-01-24
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    相关资源
    最近更新 更多