Rahul Dasgupta
Rahul Dasgupta

Reputation: 924

Export Texture with .obj file

I am currently working on a project on face tracking and exporting the face in obj file. I am successful in exporting it but not able to export the texture files. I am sharing the code for exporting the file , may be I am missing something please help me. When ever I am calling the function newMesh!.generateLightMapTexture it is crashing the code and giving following log:

Removed 41721 bad triangles
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation
Can't choose for edge creation ...
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: unordered_map::at: key not found

Below I am sharing the code for exporting:

func exportFile() {
    let geometry = currentFaceAnchor.geometry
    let allocator = MDLMeshBufferDataAllocator()

    let vertices = allocator.newBuffer(with: Data(fromArray: geometry.vertices), type: .vertex)
    let textureCoordinates = allocator.newBuffer(with: Data(fromArray: geometry.textureCoordinates), type: .vertex)
    let triangleIndices = allocator.newBuffer(with: Data(fromArray: geometry.triangleIndices), type: .index)

    let material = MDLMaterial(name: "mat1", scatteringFunction: MDLPhysicallyPlausibleScatteringFunction())
    material.setProperty(MDLMaterialProperty.init(name: "matName", semantic: MDLMaterialSemantic.ambientOcclusion))

    let submesh = MDLSubmesh(indexBuffer: triangleIndices, indexCount: geometry.triangleIndices.count, indexType: .uInt16, geometryType: .triangles, material: material)

    let vertexDescriptor = MDLVertexDescriptor()
    // Attributes
    vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition,
                                                        format: .float3,
                                                        offset: 0,
                                                        bufferIndex: 0)
    vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate,
                                                        format: .float2,
                                                        offset: 0,
                                                        bufferIndex: 1)
    // Layouts
    vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<SIMD3<Float>>.stride)
    vertexDescriptor.layouts[1] = MDLVertexBufferLayout(stride: MemoryLayout<SIMD2<Float>>.stride)

    let mdlMesh = MDLMesh(vertexBuffers: [vertices, textureCoordinates], vertexCount: geometry.vertices.count, descriptor: vertexDescriptor, submeshes: [submesh])
    let newMesh = MDLMesh.newSubdividedMesh(mdlMesh, submeshIndex: 0, subdivisionLevels: 2)

    let light = MDLLight.init(scnNode: node)
    light.lightType = .ambient
    newMesh!.generateLightMapVertexColorsWithLights(toConsider: [light], objectsToConsider: [newMesh!], vertexAttributeNamed: MDLVertexAttributeNormal)

   **//Crashing Next Line**

    newMesh!.generateLightMapTexture(withQuality: 1.0, lightsToConsider: [light], objectsToConsider: [newMesh!], vertexAttributeNamed: MDLVertexAttributeNormal, materialPropertyNamed: "matName")

    let asset = MDLAsset(bufferAllocator: allocator)
    asset.add(newMesh!)
    let fileManager = FileManager.default

    let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
    let exportUrl = documentsPath.appendingPathComponent("face.obj")
    do {
        try asset.export(to: exportUrl)
        let fileURLs = try fileManager.contentsOfDirectory(at: documentsPath, includingPropertiesForKeys: nil)

        DispatchQueue.main.async {
            let activityVC = UIActivityViewController(activityItems: fileURLs, applicationActivities: nil)
            self.present(activityVC, animated: true, completion: nil)
        }
    }
    catch {

    }
}

Upvotes: 5

Views: 918

Answers (1)

Zeyu Wang
Zeyu Wang

Reputation: 21

Maybe this is what you needed. Try adding this line before where it crashed.

newMesh!.addUnwrappedTextureCoordinates(forAttributeNamed: MDLVertexAttributeTextureCoordinate)

Upvotes: 1

Related Questions