/// <summary> /// Adds a property to a PLY file descriptor. /// </summary> /// <param name="plyFile"></param> /// <param name="words"></param> private static void AddProperty(PlyFile plyFile, string[] words) { var property = new PlyProperty(); if (words[1] == "list") { property.CountExternal = GetPropertyType(words[2]); property.ExternalType = GetPropertyType(words[3]); property.Name = words[4]; property.IsList = true; } else { property.ExternalType = GetPropertyType(words[1]); property.Name = words[2]; property.IsList = false; } // Add this property to the list of properties of the current element. plyFile.Elements[plyFile.Elements.Count - 1].Properties.Add(property); }
private static void ParseHeader(StreamReader reader, PlyFile plyFile, string[] words, string originalLine) { while (words != null) { // Parse words. switch (words[0]) { case "format": if (words.Length != 3) throw new Exception("Invalid header: format."); switch (words[1]) { case "ascii": plyFile.FileType = PlyFileType.Ascii; break; case "binary_little_endian": plyFile.FileType = PlyFileType.BinaryLittleEndian; break; case "binary_big_endian": plyFile.FileType = PlyFileType.BinaryBigEndian; break; default: throw new Exception("Invalid header: format."); } plyFile.Version = Convert.ToSingle(words[2]); break; case "element": AddElement(plyFile, words); break; case "property": AddProperty(plyFile, words); break; case "comment": AddComment(plyFile, originalLine); break; case "obj_info": AddObjInfo(plyFile, originalLine); break; case "end_header": return; } words = GetWords(reader, out originalLine); } }
/// <summary> /// Adds some object information to a PLY file descriptor. /// </summary> /// <param name="plyFile"></param> /// <param name="line"></param> private static void AddObjInfo(PlyFile plyFile, string line) { // Skip over 'obj_info' and leading spaces and tabs. int i = 8; while (line[i] == ' ' || line[i] == '\t') i++; plyFile.ObjectInformationItems.Add(line.Substring(i)); }
/// <summary> /// Adds an element to a PLY file descriptor. /// </summary> /// <param name="plyFile"></param> /// <param name="words"></param> private static void AddElement(PlyFile plyFile, string[] words) { plyFile.Elements.Add(new PlyElement { Name = words[1], Num = Convert.ToInt32(words[2]) }); }
/// <summary> /// Adds a comment to a PLY file descriptor. /// </summary> /// <param name="plyFile"></param> /// <param name="line"></param> private static void AddComment(PlyFile plyFile, string line) { // Skip over 'comment' and leading spaces and tabs. int i = 7; while (line[i] == ' ' || line[i] == '\t') i++; plyFile.Comments.Add(line.Substring(i)); }
public override Scene ImportFile(FileStream fileStream, string fileName) { var scene = new Scene(); var mesh = new Mesh(); scene.Meshes.Add(mesh); // Reading materials from PLY files is not supported yet. var material = new Material(); scene.Materials.Add(material); mesh.Material = material; // Create record for this object. var plyFile = new PlyFile(); // Read and parse the file's header. var reader = new StreamReader(fileName); string originalLine; string[] words = GetWords(reader, out originalLine); if (words == null || words[0] != "ply") throw new Exception("Missing header"); ParseHeader(reader, plyFile, words, originalLine); if (plyFile.FileType != PlyFileType.Ascii) throw new Exception("Binary files not currently supported"); // Go through each kind of element that we learned is in the file // and read them. foreach (var element in plyFile.Elements) { for (int i = 0; i < element.Num; i++) { words = GetWords(reader, out originalLine); if (words == null) throw new Exception("Unexpected end of file"); var elementValue = new PlyElementValue(); int whichWord = 0; foreach (var property in element.Properties) { int intVal; uint uintVal; double doubleVal; if (property.IsList) { GetAsciiItem(words[whichWord++], property.CountExternal, out intVal, out uintVal, out doubleVal); var listCount = intVal; for (int j = 0; j < listCount; j++) { var propertyValue = GetAsciiItem(words[whichWord++], property.ExternalType, out intVal, out uintVal, out doubleVal); elementValue.PropertyValues.Add(propertyValue); } } else { var propertyValue = GetAsciiItem(words[whichWord++], property.ExternalType, out intVal, out uintVal, out doubleVal); elementValue.PropertyValues.Add(propertyValue); } } element.ElementValues.Add(elementValue); } } // Now read vertex and face information. foreach (var element in plyFile.Elements) { switch (element.Name) { case "vertex" : int xIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "x")); int yIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "y")); int zIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "z")); int nxIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "nx")); int nyIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "ny")); int nzIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "nz")); int sIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "s")); int tIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "t")); foreach (var elementValue in element.ElementValues) { if (xIndex != -1 && yIndex != -1 && zIndex != -1) mesh.Positions.Add(new Point3D( (float) elementValue.PropertyValues[xIndex], (float) elementValue.PropertyValues[yIndex], (float) elementValue.PropertyValues[zIndex])); if (nxIndex != -1 && nyIndex != -1 && nzIndex != -1) mesh.Normals.Add(new Vector3D( (float) elementValue.PropertyValues[nxIndex], (float) elementValue.PropertyValues[nyIndex], (float) elementValue.PropertyValues[nzIndex])); if (sIndex != -1 && tIndex != -1) mesh.TextureCoordinates.Add(new Point3D( (float)elementValue.PropertyValues[sIndex], (float)elementValue.PropertyValues[tIndex], 0)); } break; case "face" : foreach (var elementValue in element.ElementValues) { if (elementValue.PropertyValues.Count != 3) throw new Exception("Only triangle faces are currently supported"); mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[0])); mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[1])); mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[2])); } break; } } reader.Close(); return scene; }
public override Scene ImportFile(FileStream fileStream, string fileName) { var scene = new Scene(); var mesh = new Mesh(); scene.Meshes.Add(mesh); // Reading materials from PLY files is not supported yet. var material = new Material(); scene.Materials.Add(material); mesh.Material = material; // Create record for this object. var plyFile = new PlyFile(); // Read and parse the file's header. var reader = new StreamReader(fileName); string originalLine; string[] words = GetWords(reader, out originalLine); if (words == null || words[0] != "ply") { throw new Exception("Missing header"); } ParseHeader(reader, plyFile, words, originalLine); if (plyFile.FileType != PlyFileType.Ascii) { throw new Exception("Binary files not currently supported"); } // Go through each kind of element that we learned is in the file // and read them. foreach (var element in plyFile.Elements) { for (int i = 0; i < element.Num; i++) { words = GetWords(reader, out originalLine); if (words == null) { throw new Exception("Unexpected end of file"); } var elementValue = new PlyElementValue(); int whichWord = 0; foreach (var property in element.Properties) { int intVal; uint uintVal; double doubleVal; if (property.IsList) { GetAsciiItem(words[whichWord++], property.CountExternal, out intVal, out uintVal, out doubleVal); var listCount = intVal; for (int j = 0; j < listCount; j++) { var propertyValue = GetAsciiItem(words[whichWord++], property.ExternalType, out intVal, out uintVal, out doubleVal); elementValue.PropertyValues.Add(propertyValue); } } else { var propertyValue = GetAsciiItem(words[whichWord++], property.ExternalType, out intVal, out uintVal, out doubleVal); elementValue.PropertyValues.Add(propertyValue); } } element.ElementValues.Add(elementValue); } } // Now read vertex and face information. foreach (var element in plyFile.Elements) { switch (element.Name) { case "vertex": int xIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "x")); int yIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "y")); int zIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "z")); int nxIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "nx")); int nyIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "ny")); int nzIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "nz")); int sIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "s")); int tIndex = element.Properties.IndexOf(element.Properties.SingleOrDefault(p => p.Name == "t")); foreach (var elementValue in element.ElementValues) { if (xIndex != -1 && yIndex != -1 && zIndex != -1) { mesh.Positions.Add(new Point3D( (float)elementValue.PropertyValues[xIndex], (float)elementValue.PropertyValues[yIndex], (float)elementValue.PropertyValues[zIndex])); } if (nxIndex != -1 && nyIndex != -1 && nzIndex != -1) { mesh.Normals.Add(new Vector3D( (float)elementValue.PropertyValues[nxIndex], (float)elementValue.PropertyValues[nyIndex], (float)elementValue.PropertyValues[nzIndex])); } if (sIndex != -1 && tIndex != -1) { mesh.TextureCoordinates.Add(new Point3D( (float)elementValue.PropertyValues[sIndex], (float)elementValue.PropertyValues[tIndex], 0)); } } break; case "face": foreach (var elementValue in element.ElementValues) { if (elementValue.PropertyValues.Count != 3) { throw new Exception("Only triangle faces are currently supported"); } mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[0])); mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[1])); mesh.Indices.Add(Convert.ToInt32(elementValue.PropertyValues[2])); } break; } } reader.Close(); return(scene); }