使用 C# 读取二进制 PLY 文件面索引
Reading binary PLY file face indices using C#
我正在使用这个项目读取 .ply 二进制文件:
https://github.com/Zarbuz/FileToVox/blob/2064dcf99532e9c22748afb8e1a3755c1e5dfb81/SchematicToVoxCore/Converter/PLYToSchematic.cs
它适用于读取点及其颜色。
但是我不明白如何检索网格面索引列表。
在 ReadDataHeaders 函数中我成功获取了面数:
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;
}
}
...
}
但我不明白的是如何在函数ReadDataBodyBoundary 中检索网格面索引。
我也不明白 BinaryReader 在这个函数中是如何工作的,它是如何读取网格面顶点索引的每一行二进制形式的。
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;
}
问题是您提供的示例只需要带颜色的点云(而不是面三角形)。
To key to read faces 似乎在您在代码中注释的那段代码中。
我假设你的 ply 文件的 header 是这样的:
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),以及一个带有顶点索引的有符号整数列表。
因此,您需要更改数据结构以使用 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;
我正在使用这个项目读取 .ply 二进制文件: https://github.com/Zarbuz/FileToVox/blob/2064dcf99532e9c22748afb8e1a3755c1e5dfb81/SchematicToVoxCore/Converter/PLYToSchematic.cs
它适用于读取点及其颜色。 但是我不明白如何检索网格面索引列表。
在 ReadDataHeaders 函数中我成功获取了面数:
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;
}
}
...
}
但我不明白的是如何在函数ReadDataBodyBoundary 中检索网格面索引。 我也不明白 BinaryReader 在这个函数中是如何工作的,它是如何读取网格面顶点索引的每一行二进制形式的。
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;
}
问题是您提供的示例只需要带颜色的点云(而不是面三角形)。
To key to read faces 似乎在您在代码中注释的那段代码中。
我假设你的 ply 文件的 header 是这样的:
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),以及一个带有顶点索引的有符号整数列表。
因此,您需要更改数据结构以使用 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;