ios - 如何将mtl纹理文件应用于OBJ

时间:2018-05-08 19:59:37

标签: ios 3d scenekit

我正在使用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)
    }
}

问题是当app运行时,会显示3D模型,但.mtl纹理文件不适用于它。如何解决这个问题?谢谢大家。

1 个答案:

答案 0 :(得分:0)

这方面的主要问题是:

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)

P.S。这是完成该任务的两种略有不同的方法。

更新:

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

您也可以尝试使用此方法。如果我没记错的话,它会挂起.mtl文件和其他纹理。 (如果以.obj文件编写的.mtl文件的路径有效,并且.mtl中纹理的路径也有效)