public static PlyResult GetResult(byte[] content) { PlyResult plyResult = null; var header = GetHeader(content); var headerParsed = new PlyHeader(header); if (!headerParsed.VertexElement.IsValid || (!headerParsed.FaceElement.IsValid && !headerParsed.LineElement.IsValid)) { return(null); } if (headerParsed.Format == PlyFormat.Ascii) { plyResult = ParseAscii(GetLines(content), headerParsed); } else if (headerParsed.Format == PlyFormat.BinaryLittleEndian) { plyResult = ParseBinaryLittleEndian(content, headerParsed); } else // todo: support BinaryBigEndian { return(null); } return(plyResult); // new PlyResult(mesh, headerParsed.GloablMaterialElement.GetColor()); }
private static Color ParseColor(string[] xyzrgb, PlyHeader header) { int r = 255; int g = 255; int b = 255; int a = 255; if (header.RedIndex.HasValue) { int.TryParse(xyzrgb[header.RedIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out r); } if (header.GreenIndex.HasValue) { int.TryParse(xyzrgb[header.GreenIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out g); } if (header.BlueIndex.HasValue) { int.TryParse(xyzrgb[header.BlueIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out b); } if (header.AlphaIndex.HasValue) { int.TryParse(xyzrgb[header.AlphaIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out a); } return(new Color(r / 255f, g / 255f, b / 255f, a / 255f)); }
private static PlyResult ParseBinaryLittleEndian(byte[] content, PlyHeader header) { PlyResult plyResult = new PlyResult(); plyResult.meshName = header.GlobalMeshInfoElement.GetName(); plyResult.meshColor = header.GloablMaterialElement.GetColor(); var headerAsText = header.RawHeader.Aggregate((a, b) => $"{a}\n{b}") + "\n"; var headerAsBytes = Encoding.ASCII.GetBytes(headerAsText); var withoutHeader = content.Skip(headerAsBytes.Length).ToArray(); int bytesUsed; header.VertexElement.ParseElementBinaryLittleEndian(withoutHeader, out bytesUsed, out plyResult.vertices, out plyResult.normals, out plyResult.colors); int bytesOffset = bytesUsed; header.FaceElement.ParseElementBinaryLittleEndian(withoutHeader, bytesOffset, out bytesUsed, out plyResult.triangles); bytesOffset = bytesOffset + bytesUsed; header.LineElement.ParseElementBinaryLittleEndian(withoutHeader, bytesOffset, out bytesUsed, out plyResult.lines); bytesOffset = bytesOffset + bytesUsed; header.LineColorElement.ParseElementBinaryLittleEndian(withoutHeader, bytesOffset, out bytesUsed, out plyResult.lineColors); return(plyResult); }
private static List <int> GetTriangles(string faceVertexList, PlyHeader header) { switch (header.FaceParseMode) { case PlyFaceParseMode.VertexCountVertexIndex: var split = faceVertexList.Split(' '); var count = Convert.ToInt32(split.First()); switch (count) { case 3: // triangle return(split.ToList().GetRange(1, 3).Select(x => Convert.ToInt32(x)).ToList()); case 4: // face var triangles = new List <int>(); var indices = split.ToList().GetRange(1, 4).Select(x => Convert.ToInt32(x)).ToList(); triangles.AddRange(QuadToTriangles(indices)); return(triangles); default: Debug.LogWarning("Warning: Found a face with more than 4 vertices, skipping..."); return(new List <int>()); } default: Debug.LogWarning("Ply GetTriangles: Unknown parse mode"); return(new List <int>()); } }
private static Vector4b ParseColor(string[] xyzrgb, PlyHeader header) { byte r = 255; byte g = 255; byte b = 255; byte a = 255; if (header.RedIndex.HasValue) { byte.TryParse(xyzrgb[header.RedIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out r); } if (header.GreenIndex.HasValue) { byte.TryParse(xyzrgb[header.GreenIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out g); } if (header.BlueIndex.HasValue) { byte.TryParse(xyzrgb[header.BlueIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out b); } if (header.AlphaIndex.HasValue) { byte.TryParse(xyzrgb[header.AlphaIndex.Value], NumberStyles.Integer, CultureInfo.InvariantCulture, out a); } return(new Vector4b(r, g, b, a)); }
private static List <Vector3> GetVertices(byte[] bytes, PlyHeader header, out List <Color> colors) { var vertices = new List <Vector3>(); colors = new List <Color>(); int bpvc = 4; // bytes per vertex component int bpcc = 1; // bytes per color component bool hasColor = header.RedIndex.HasValue && header.GreenIndex.HasValue && header.BlueIndex.HasValue; // todo: support other types than just float for vertex components and byte for color components int bytesPerVertex = GetByteCountPerVertex(header); for (int i = 0; i < header.VertexCount; i++) { int byteIndex = i * bytesPerVertex; var x = System.BitConverter.ToSingle(bytes.SubArray(byteIndex + 0 * bpvc, bpvc), 0); var y = System.BitConverter.ToSingle(bytes.SubArray(byteIndex + 1 * bpvc, bpvc), 0); var z = System.BitConverter.ToSingle(bytes.SubArray(byteIndex + 2 * bpvc, bpvc), 0); if (hasColor) { byte r, g, b, a = 255; r = bytes[byteIndex + 3 * bpvc + 0 * bpcc]; g = bytes[byteIndex + 3 * bpvc + 1 * bpcc]; b = bytes[byteIndex + 3 * bpvc + 2 * bpcc]; if (header.AlphaIndex.HasValue) { a = bytes[byteIndex + 3 * bpvc + 3 * bpcc]; } colors.Add(new Color(r / 255f, g / 255f, b / 255f, a / 255f)); } vertices.Add(new Vector3(x, y, z)); } return(vertices); }
private static PlyResult ParseAscii(List <string> plyFile, PlyHeader header) { var vertices = new List <Vector3f>(); var triangles = new List <int>(); var colors = new List <Vector4b>(); var headerEndIndex = plyFile.IndexOf("end_header"); var vertexStartIndex = headerEndIndex + 1; var faceStartIndex = vertexStartIndex + header.VertexCount + 1; plyFile.GetRange(vertexStartIndex, header.VertexCount).ForEach(vertex => { var xyzrgb = vertex.Split(' '); vertices.Add(ParseVertex(xyzrgb, header)); colors.Add(ParseColor(xyzrgb, header)); }); List <string> lines = plyFile.GetRange(faceStartIndex - 1, header.FaceCount); //??? lines.ForEach(face => { triangles.AddRange(GetTriangles(face, header)); }); return(new PlyResult(vertices, triangles, colors)); }
private static Vector3 ParseVertex(string[] xyzrgb, PlyHeader header) { decimal dx, dy, dz; decimal.TryParse(xyzrgb[header.XIndex], NumberStyles.Float, CultureInfo.InvariantCulture, out dx); decimal.TryParse(xyzrgb[header.YIndex], NumberStyles.Float, CultureInfo.InvariantCulture, out dy); decimal.TryParse(xyzrgb[header.ZIndex], NumberStyles.Float, CultureInfo.InvariantCulture, out dz); return(new Vector3((float)dx, (float)dy, (float)dz)); }
private static PlyResult ParseBinaryLittleEndian(string path, PlyHeader header) { var headerAsText = header.RawHeader.Aggregate((a, b) => $"{a}\n{b}") + "\n"; var headerAsBytes = Encoding.ASCII.GetBytes(headerAsText); var withoutHeader = File.ReadAllBytes(path).Skip(headerAsBytes.Length).ToArray(); var colors = new List <Color>(); var vertices = GetVertices(withoutHeader, header, out colors); var triangles = GetTriangles(withoutHeader, header); return(new PlyResult(vertices, triangles, colors)); }
public PlyFaceElement(IList <string> headerUnparsed, PlyHeader header) : base("face") { _plyHeader = header; if (!ParseElementInfo(headerUnparsed)) { IsValid = false; return; } IsValid = IsValid && IsElementValid(); }
private static int GetByteCountPerVertex(PlyHeader header) { int bpvc = 4; // bytes per vertex component int bpcc = 1; // bytes per color component // todo: support other types than just float for vertex components and byte for color components int r = header.RedIndex.HasValue ? bpcc : 0; int g = header.GreenIndex.HasValue ? bpcc : 0; int b = header.BlueIndex.HasValue ? bpcc : 0; int a = header.AlphaIndex.HasValue ? bpcc : 0; return(3 * bpvc + r + g + b + a); }
public PlyVertexElement(IList <string> headerUnparsed, PlyHeader header) : base("vertex") { _header = header; if (!ParseElementInfo(headerUnparsed)) { IsValid = false; return; } HasPosition = DictProperties.ContainsKey("x") && DictProperties.ContainsKey("y") && DictProperties.ContainsKey("z"); HasNormal = DictProperties.ContainsKey("nx") && DictProperties.ContainsKey("ny") && DictProperties.ContainsKey("nz"); HasColor = DictProperties.ContainsKey("red") && DictProperties.ContainsKey("green") && DictProperties.ContainsKey("blue") && DictProperties.ContainsKey("alpha"); IsValid = IsValid && IsElementValid(); }
public static PlyResult GetVerticesAndTriangles(string path) { List <string> header = File.ReadLines(path).TakeUntilIncluding(x => x == "end_header").ToList(); var headerParsed = new PlyHeader(header); if (headerParsed.Format == PlyFormat.Ascii) { return(ParseAscii(File.ReadAllLines(path).ToList(), headerParsed)); } else if (headerParsed.Format == PlyFormat.BinaryLittleEndian) { return(ParseBinaryLittleEndian(path, headerParsed)); } else // todo: support BinaryBigEndian { return(null); } }
public static PlyResult FromFile(string path) { List <string> header = File.ReadLines(path).TakeUntilIncluding(x => x == "end_header").ToList(); var headerParsed = new PlyHeader(header); switch (headerParsed.Format) { case PlyFormat.Ascii: return(ParseAscii(File.ReadAllLines(path).ToList(), headerParsed)); case PlyFormat.BinaryLittleEndian: return(ParseBinaryLittleEndian(path, headerParsed)); case PlyFormat.BinaryBigEndian: // todo: support BinaryBigEndian default: return(null); } }
private static PlyResult ParseAscii(List <string> plyFile, PlyHeader header) { PlyResult plyResult = new PlyResult(); plyResult.meshName = header.GlobalMeshInfoElement.GetName(); plyResult.meshColor = header.GloablMaterialElement.GetColor(); // TODO: order independent var headerEndIndex = plyFile.IndexOf("end_header"); var vertexStartIndex = headerEndIndex + 1; var faceStartIndex = vertexStartIndex + header.VertexElement.NElement; var lineStartIndex = faceStartIndex + header.FaceElement.NElement; var lineColorStartIndex = lineStartIndex + header.LineElement.NElement; header.VertexElement.ParseElement(plyFile.GetRange(vertexStartIndex, header.VertexElement.NElement), out plyResult.vertices, out plyResult.normals, out plyResult.colors); header.FaceElement.ParseElement(plyFile.GetRange(faceStartIndex, header.FaceElement.NElement), out plyResult.triangles); header.LineElement.ParseElement(plyFile.GetRange(lineStartIndex, header.LineElement.NElement), out plyResult.lines); header.LineColorElement.ParseElement(plyFile.GetRange(lineColorStartIndex, header.LineColorElement.NElement), out plyResult.lineColors); return(plyResult); }
private static List <int> GetTriangles(byte[] bytes, PlyHeader header) { var toSkip = header.VertexCount * GetByteCountPerVertex(header); var triangles = new List <int>(); int facesRead = 0; int bytesRead = 0; int bytesPerTriangleIndex = 4; while (facesRead < header.FaceCount) { var faceIndex = toSkip + bytesRead; var indexCount = bytes[faceIndex]; if (indexCount == 3) { for (int i = 0; i < indexCount; i++) { triangles.Add(System.BitConverter.ToInt32(bytes.SubArray(faceIndex + 1 + i * bytesPerTriangleIndex, bytesPerTriangleIndex), 0)); } bytesRead += 1 + indexCount * bytesPerTriangleIndex; } else if (indexCount == 4) { var tmp = new List <int>(); for (int i = 0; i < indexCount; i++) { tmp.Add(System.BitConverter.ToInt32(bytes.SubArray(faceIndex + 1 + i * bytesPerTriangleIndex, bytesPerTriangleIndex), 0)); } triangles.AddRange(QuadToTriangles(tmp)); bytesRead += 1 + indexCount * bytesPerTriangleIndex; } else { Debug.LogWarning("Warning: Found a face with more than 4 vertices, skipping..."); } facesRead++; } return(triangles); }