1 Reply
      Latest reply on Jan 2, 2020 7:12 AM by Bobjt
      bolt45 Level 1 Level 1 (0 points)

        In an iOS ARKit app, I've been trying to save the ARFaceGeometry data to an OBJ file. I followed the explanation here: How to make a 3D model from AVDepthData?. However, the OBJ isn't created correctly. Here's what I have:


        func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
                guard let faceAnchor = anchor as? ARFaceAnchor else { return }
                currentFaceAnchor = faceAnchor
                // If this is the first time with this anchor, get the controller to create content.
                // Otherwise (switching content), will change content when setting `selectedVirtualContent`.
                if node.childNodes.isEmpty, let contentNode = selectedContentController.renderer(renderer, nodeFor: faceAnchor) {
                // https://stackoverflow.com/questions/52953590/how-to-make-a-3d-model-from-avdepthdata
                let geometry = faceAnchor.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 submesh = MDLSubmesh(indexBuffer: triangleIndices, indexCount: geometry.triangleIndices.count, indexType: .uInt16, geometryType: .triangles, material: MDLMaterial(name: "mat1", scatteringFunction: MDLPhysicallyPlausibleScatteringFunction()))
                let vertexDescriptor = MDLVertexDescriptor()
                // Attributes
                vertexDescriptor.addOrReplaceAttribute(MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0))
                vertexDescriptor.addOrReplaceAttribute(MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout.stride, bufferIndex: 0))
                vertexDescriptor.addOrReplaceAttribute(MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout.stride + MemoryLayout.stride, bufferIndex: 0))
                // Layouts
                vertexDescriptor.layouts.add(MDLVertexBufferLayout(stride: MemoryLayout.stride + MemoryLayout.stride + MemoryLayout.stride))
                let mdlMesh = MDLMesh(vertexBuffers: [vertices, textureCoordinates], vertexCount: geometry.vertices.count, de}scriptor: vertexDescriptor, submeshes: [submesh])
                mdlMesh.addNormals(withAttributeNamed: MDLVertexAttributeNormal, creaseThreshold: 0.5)
                let asset = MDLAsset(bufferAllocator: allocator)
                let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                let exportUrl = documentsPath.appendingPathComponent("face.obj")
                try! asset.export(to: exportUrl)


        The resulting OBJ file looks like this. I would expect many more vertices, and the index values look wrong.


        # Apple ModelIO OBJ File: face
        mtllib face.mtl
        v -0.000128156 -0.0277879 0.0575149
        vn 0 0 0
        vt -9.36008e-05 -0.0242016
        usemtl material_1
        f 1/1/1 1/1/1 1/1/1
        f 1/1/1 1/1/1 1/1/1
        f 1/1/1 1/1/1 1/1/1
        ... and many more lines