ios 14 中的 .ply(多边形)格式文件问题

.ply (polygon) format file issue in ios 14

我的应用程序在扫描对象后生成 ply 文件。 ios 14 更新后,我的 3d 模型的颜色无法正确加载。此外,我无法在 xcode 中查看 ply 文件(在预览中工作正常)。

有人知道这个问题的解决方法吗?

我厌倦了阅读 ply 文件内容并在场景几何体中显示顶点和面,但加载文件花费的时间太长。

显然创建 mdlAsset() 会引发一些金属警告,并且网格颜色无法正确显示。

以下是 ios 13 和 14 在 sceneKit 中预览的示例图像。

同样的问题,我发现这是一个SceneKit的错误,我有一个解决方案,用C读取.ply文件,并用数据创建一个SCNGeometry实例,主要代码:

  1. 首先我们需要读取 .ply 文件中的 vertexCount 和 faceCount(我的文件是 ASCII 格式,所以,)
    bool readFaceAndVertexCount(char* filePath, int *vertexCount, int *faceCount);

示例:

    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] = '[=11=]';
        
        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、读取数据到数组: 在.c

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

在.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 创建自定义 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

有效!更快!