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

标签 ios swift scenekit metal ply-file-format

我的应用程序在扫描对象后生成 ply 文件。 ios 14 更新后,我的 3d 模型的颜色无法正确加载。另外我无法在 xcode 中查看 ply 文件(在预览中工作正常)。
有人知道这个问题的解决方法吗?
我厌倦了阅读层文件内容并在场景几何图形中显示顶点和面,但加载文件需要很长时间。
显然,创建 mdlAsset() 会引发一些 Metal 警告,并且网格颜色无法正确显示。
以下是sceneKit 中ios 13 和14 预览的示例图像。
comparison of ios 13 and ios 14 ply file preview in scenekit

最佳答案

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

  • 首先我们需要读取 .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] = '\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、读取数据到数组:
    在.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
    
    这行得通!而且更快!

    关于ios - ios 14 中的 .ply(多边形)格式文件问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64100276/

    相关文章:

    swift - CAGradientLayer 设置为 scenekit 背景 block 场景

    ios - 在快速过滤来自服务器的字典数组时遇到问题

    swift - 如何添加 30 秒计时器来结束游戏回合?

    ios - 对 SceneKit 中相机的正交投影感到困惑

    ios - 如何从 cellForItemAtIndexPath 设置 UICollectionViewCell 高度?

    objective-c - 无法在 Swift 中正确地将参数传递给 CFSwapInt16LittleToHost

    swift - 复制 NSTableView 行变灰

    ios - UIDocumentInteractionController PresentOptionsMenuFromBarButtonItem 不打开应用程序

    ios - 以前的核心数据迁移失败

    ios - 从 WKWebView 打印 2 页时出现问题