.ply (polygon) format file issue in ios 14

1.5k views Asked by At

My app generates ply files after scanning objects. After ios 14 update the color of my 3d models does not load correctly. Also I am unable to view ply files in xcode (works fine in preview).

Anyone know the workaround to this problem?

I tired reading ply file content and display vertices and faces in scene geometry but it takes too long to load a file.

Apparently creating mdlAsset() throws some Metal warning and the mesh color does not show up properly.

Here are the sample images from ios 13 and 14 preview in sceneKit.

comparison of ios 13 and ios 14 ply file preview in scenekit

1

There are 1 answers

0
henrs On BEST ANSWER

same problem,i found it is a SceneKit's bug, i had a solution that read .ply file with C, and creat a SCNGeometry instance with data, main code:

  1. first we need read vertexCount and faceCount in .ply file (my file is ASCII format,so, )
    bool readFaceAndVertexCount(char* filePath, int *vertexCount, int *faceCount);

example:

    bool readFaceAndVertexCount(char* filePath, int *vertexCount, int *faceCount) {
    
    char data[100];
    FILE *fp;
    if((fp = fopen(filePath,"r")) == NULL)
    {
        printf("error!");
        return false;
    }
    
    while (!feof(fp))
        
    {
        fgets(data,1024,fp);  
        unsigned long i = strlen(data);
        data[i - 1] = '\0';
        
        if (strstr(data, "element vertex") != NULL) {
            char *res = strtok(data," ");
            while (res != NULL) {
                res = strtok(NULL, " ");
                if (res != NULL) {
                    *vertexCount = atoi(res);
                }
            }
        }
        
        if (strstr(data, "element face") != NULL) {
            char *res = strtok(data," ");
            while (res != NULL) {
                res = strtok(NULL, " ");
                if (res != NULL) {
                    *faceCount = atoi(res);
                }
            }
        }
        
        
        if (*faceCount > 0 && *vertexCount > 0) {
            break;
        }
    }
    
    fclose(fp);
    return  true;
}

2, read data to array: in .c

// you need to implement with your files
bool readPlyFile(char* filePath, const int vertexCount, int faceCount, float *vertex, float *color, int *elment)

in .swift:

 var vertex: [Float] = Array.init(repeating: 0, count: Int(vertexCount) * 3)
        
 var color: [Float] = Array.init(repeating: 0, count: Int(vertexCount) * 3)
        
 var face: [Int32] = Array.init(repeating: 0, count: Int(faceCount) * 3)
        
 readPlyFile(UnsafeMutablePointer<Int8>(mutating: url.path),vertexCount,faceCount,&vertex,&color,&face)

3 creat a custom SCNGeometry:

       let positionData = NSData.init(bytes: vertex, length: MemoryLayout<Float>.size * vertex.count)
        
        let vertexSource = SCNGeometrySource.init(data: positionData as Data, semantic: .vertex, vectorCount: Int(vertexCount), usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size * 3)
        
        let colorData = NSData.init(bytes: color, length: MemoryLayout<Float>.size * color.count)
        
        let colorSource = SCNGeometrySource.init(data: colorData as Data, semantic: .color, vectorCount: Int(vertexCount), usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<Float>.size * 3)
        
        
        let indexData = NSData(bytes: face, length: MemoryLayout<Int32>.size * face.count)
        
        let element = SCNGeometryElement(data: indexData as Data, primitiveType: SCNGeometryPrimitiveType.triangles, primitiveCount: Int(faceCount), bytesPerIndex: MemoryLayout<Int32>.size)
        
        let gemetry = SCNGeometry.init(sources: [vertexSource,colorSource], elements: [element])
        
        let node = SCNNode.init(geometry: gemetry)
        
        let scene = SCNScene.init()
       
        node.geometry?.firstMaterial?.cullMode = .back
        node.geometry?.firstMaterial?.isDoubleSided = true
        
        scene.rootNode.addChildNode(node)
        scnView.scene = scene

it work! and faster!