0

I am reading .ply binary file using this project: https://github.com/Zarbuz/FileToVox/blob/2064dcf99532e9c22748afb8e1a3755c1e5dfb81/SchematicToVoxCore/Converter/PLYToSchematic.cs

It works for reading points and their colors. But I do not understand how to retrieve the list of mesh faces indices.

In the function ReadDataHeaders I successuflly retrieve the number of faces:

 private static DataHeader ReadDataHeader(StreamReader reader) {
 ...
                if (col[0] == "element") {
                    if (col[1] == "vertex") {
                        data.vertexCount = Convert.ToInt32(col[2]);
                        skip = false;
                    } else if (col[1] == "face") {
                        data.faceCount = Convert.ToInt32(col[2]);
                        skip = false;
                    } else {
                        // Don't read elements other than vertices.
                        skip = true;
                    }
                }

...
}

But what I do not understand is how retrieve the mesh face indices in the function ReadDataBodyBoundary. I do not also understand how the BinaryReader works in this function, how does it reads the each line of binary form for mesh faces vertex indices.

 private static DataBody ReadDataBodyBinary(DataHeader header, BinaryReader reader) {
            DataBody data = new DataBody(header.vertexCount,header.faceCount);

            float x = 0, y = 0, z = 0;
            byte r = 255, g = 255, b = 255, a = 255;
            int f0 = 0, f1 = 0, f2 = 0;

            //for(int i = 0; i < header.faceCount; i++) {
            //    //foreach(var face in )
            //    int faceVertex = reader.ReadInt32();
            //    Console.WriteLine();
            //}
            //reader.BaseStream.Position = readCount;
            Console.WriteLine("Number of properties:   " + header.properties.Count().ToString());
            for (int i = 0; i < header.vertexCount; i++) {
                foreach (DataProperty prop in header.properties) {//iterate six properties
                    //Console.WriteLine(prop.ToString());
                    switch (prop) {
                        case DataProperty.R8:
                        r = reader.ReadByte();
                        break;
                        case DataProperty.G8:
                        g = reader.ReadByte();
                        break;
                        case DataProperty.B8:
                        b = reader.ReadByte();
                        break;
                        case DataProperty.A8:
                        a = reader.ReadByte();
                        break;

                        case DataProperty.R16:
                        r = (byte)(reader.ReadUInt16() >> 8);
                        break;
                        case DataProperty.G16:
                        g = (byte)(reader.ReadUInt16() >> 8);
                        break;
                        case DataProperty.B16:
                        b = (byte)(reader.ReadUInt16() >> 8);
                        break;
                        case DataProperty.A16:
                        a = (byte)(reader.ReadUInt16() >> 8);
                        break;

                        case DataProperty.SingleX:
                        x = reader.ReadSingle();
                        break;
                        case DataProperty.SingleY:
                        y = reader.ReadSingle();
                        break;
                        case DataProperty.SingleZ:
                        z = reader.ReadSingle();
                        break;

                        case DataProperty.DoubleX:
                        x = (float)reader.ReadDouble();
                        break;
                        case DataProperty.DoubleY:
                        y = (float)reader.ReadDouble();
                        break;
                        case DataProperty.DoubleZ:
                        z = (float)reader.ReadDouble();
                        break;

                        case DataProperty.Data8:
                        reader.ReadByte();
                        break;
                        case DataProperty.Data16:
                        reader.BaseStream.Position += 2;
                        break;
                        case DataProperty.Data32:
                        reader.BaseStream.Position += 4;
                        break;
                        case DataProperty.Data64:
                        reader.BaseStream.Position += 8;
                        break;
                    }
                }

                data.AddPoint(x, y, z, r, g, b);
            }

            return data;
        }
4

1 回答 1

0

问题是您提供的示例仅期望具有颜色的点云(并且没有面的三角形)。

读取面孔的关键似乎在您在代码中注释的那段代码中。

我假设您的 ply 文件的标题是这样的:

ply
format binary_little_endian 1.0
element vertex 326
property float x
property float y
property float z
property uchar r
property uchar g
property uchar b
property uchar a
element face 595
property list uchar int vertex_indices
end_header

重要的一行是这property list uchar int vertex_indices意味着您有一个 uchar ,其中包含面中的顶点数(通常为 3),以及一个带有顶点索引的有符号 int 列表。

因此,您需要更改数据结构以存储具有类似内容的人脸,public List<List<Int> > faces;并在您的return data;行中添加与此类似的内容。

for(int i = 0; i < header.faceCount; i++) {
    byte numVertex = reader.ReadByte(); //Read one uchar. Usually 3.
    List<int> indices = new List<int>();
    for(byte j = 0; j < numVertex; j++) {
       indices.Add(reader.ReadInt());   //Read one int and store in the list
    }
    data.faces.Add(indices);                 //Store the face
}

return data;
于 2019-11-28T09:44:07.673 回答