/// <summary> /// Write a mesh into an STL ascii file /// </summary> /// <param name="mesh"></param> /// <remarks> /// The mesh must be formed by triangles, quads are not accpeted for this format. <br/> /// The mesh must also contain a <see cref="LayerElementNormal"/> set to <see cref="MappingMode.ByPolygon"/> /// </remarks> public void WriteAscii(Mesh mesh) { this.validate(mesh); using (TextWriter tw = new StreamWriter(this._stream.Stream, new UTF8Encoding(false))) { tw.WriteLine($"solid {mesh.Name}"); LayerElementNormal normals = mesh.Layers.GetLayer <LayerElementNormal>(); for (int i = 0; i < mesh.Polygons.Count; i++) { XYZ normal = normals.Normals[i]; tw.WriteLine($" facet normal {(float)normal.X} {(float)normal.Y} {(float)normal.Z}"); tw.WriteLine($" outer loop"); foreach (int item in (Triangle)mesh.Polygons[i]) { var v = mesh.Vertices[item]; tw.WriteLine($" vertex {(float)v.X} {(float)v.Y} {(float)v.Z}"); } tw.WriteLine($" endloop"); tw.WriteLine($" endfacet"); } tw.WriteLine($"endsolid {mesh.Name}"); } }
public LayerElement BuildLayerElementNormal(FbxNode node) { LayerElementNormal layer = new LayerElementNormal(); foreach (FbxNode n in node) { switch (n.Name) { case "Normals": layer.Normals = this.arrToXYZ(this.arrToDoubleArray(n.Value as IEnumerable)); break; case "NormalsW": layer.Weights.AddRange(this.arrToDoubleArray(n.Value as IEnumerable)); break; default: if (!this.isCommonLayerField(layer, n)) { this.notify($"Unknow node while building LayerElement with name {n.Name}"); } break; } } return(layer); }
public FbxNode buildLayerElementNormal(LayerElementNormal layer) { FbxNode node = new FbxNode("LayerElementNormal", 0); node.Nodes.Add(new FbxNode("Version", 102)); buildLayerElement(node, layer); node.Nodes.Add(new FbxNode("Normals", layer.Normals.SelectMany(x => x.GetComponents()).ToArray())); return(node); }
public void SetNormals(LayerElementNormal pNormals) { if (normals.Get() != null) { elements.Remove(normals.Get()); } elements.Add(pNormals); }
/// <summary> /// Write a mesh into an STL binary file /// </summary> /// <param name="mesh"></param> /// <param name="header">Optional header parameter</param> /// <remarks> /// The mesh must be formed by triangles, quads are not accpeted for this format. <br/> /// The mesh must also contain a <see cref="LayerElementNormal"/> set to <see cref="MappingMode.ByPolygon"/> /// </remarks> public void WriteBinary(Mesh mesh, string header = null) { this.validate(mesh); if (string.IsNullOrEmpty(header)) { header = "File created by MeshIO.STL"; } else if (header.Length > 80) { throw new StlException("Header length must be 80 or less"); } header = header + new string('\0', 80 - header.Length); this._stream.Write(header, Encoding.UTF8); this._stream.Write(mesh.Polygons.Count); LayerElementNormal normals = mesh.Layers.GetLayer <LayerElementNormal>(); for (int i = 0; i < mesh.Polygons.Count; i++) { XYZ normal = normals.Normals[i]; this._stream.Write((float)normal.X); this._stream.Write((float)normal.Y); this._stream.Write((float)normal.Z); foreach (int item in (Triangle)mesh.Polygons[i]) { var v = mesh.Vertices[item]; this._stream.Write((float)v.X); this._stream.Write((float)v.Y); this._stream.Write((float)v.Z); } ushort attByteCount = 0; this._stream.Write(attByteCount); } }
/// <summary> /// Read the STL file /// </summary> /// <returns>mesh defined in the file</returns> public Mesh Read() { this._stream.Position = 0; string header = this._stream.ReadString(80); this.OnNotification?.Invoke(new NotificationArgs(header.Replace("\0", ""))); Mesh mesh = new Mesh(); LayerElementNormal normals = new LayerElementNormal(); mesh.Layers.Add(normals); int nTriangles = this._stream.ReadInt <LittleEndianConverter>(); if (this.checkStreamLenth(nTriangles)) { for (int i = 0; i < nTriangles; i++) { XYZ normal = new XYZ(this._stream.ReadSingle(), this._stream.ReadSingle(), this._stream.ReadSingle()); normals.Add(normal); XYZ v1 = new XYZ(this._stream.ReadSingle(), this._stream.ReadSingle(), this._stream.ReadSingle()); XYZ v2 = new XYZ(this._stream.ReadSingle(), this._stream.ReadSingle(), this._stream.ReadSingle()); XYZ v3 = new XYZ(this._stream.ReadSingle(), this._stream.ReadSingle(), this._stream.ReadSingle()); mesh.AddTriangles(v1, v2, v3); ushort attByteCount = this._stream.ReadUShort(); } } else { this._stream.Position = 0; string line = this._stream.ReadUntil('\n'); string name = Regex.Match(line, @"solid \s\n", options: RegexOptions.IgnoreCase).Value; mesh.Name = name; line = this._stream.ReadUntil('\n'); while (!line.Contains($"endsolid {name}")) { XYZ normal = this.readPoint(line, "facet normal"); normals.Add(normal); this.checkLine(this._stream.ReadUntil('\n'), "outer loop"); XYZ v1 = this.readPoint(this._stream.ReadUntil('\n'), "vertex"); XYZ v2 = this.readPoint(this._stream.ReadUntil('\n'), "vertex"); XYZ v3 = this.readPoint(this._stream.ReadUntil('\n'), "vertex"); mesh.AddTriangles(v1, v2, v3); this.checkLine(this._stream.ReadUntil('\n'), "endloop"); this.checkLine(this._stream.ReadUntil('\n'), "endfacet"); line = this._stream.ReadUntil('\n'); } } return(mesh); }