public static void WriteFast(string path, StlModel model) { StringBuilder sb = new StringBuilder(); var vertices = model.vertices; var normals = model.normals; int tris = model.normals.Count; sb.Append("solid ").Append(model.name); for (int i = 0; i < tris; i++) { var n = normals[i]; sb.Append("\r\n").Append(" facet normal ").Append(n.x).Append(" ").Append(n.y).Append(" ").Append(n.z); sb.Append("\r\n").Append(" outer loop"); for (int j = 0; j < 3; j++) { var v = vertices[i * 3 + j]; sb.Append("\r\n").Append(" vertex ").Append(v.x).Append(" ").Append(v.y).Append(" ") .Append(v.z); } sb.Append("\r\n").Append(" endloop"); sb.Append("\r\n").Append(" endfacet"); } sb.Append("\r\n endsolid"); File.WriteAllText(path, sb.ToString()); }
public static void Write(string path, StlModel model) { List <string> lines = new List <string>(1024); var vertices = model.vertices; var normals = model.normals; int tris = model.normals.Count; lines.Add($"solid {model.name}"); for (int i = 0; i < tris; i++) { var n = normals[i].ToStringFull(); lines.Add($" facet normal {n}"); lines.Add(" outer loop"); for (int j = 0; j < 3; j++) { lines.Add($" vertex {vertices[i*3 + j].ToStringFull()}"); } lines.Add(" endloop"); lines.Add(" endfacet"); } lines.Add("endsolid"); File.WriteAllLines(path, lines); }
public static StlModel Read(string path) { var lines = File.ReadAllLines(path).Select(line => line.Trim()).ToArray(); var name = lines[0].Replace("solid ", "").Trim(); List <Vector> vertices = new List <Vector>(1024); List <Vector> normals = new List <Vector>(512); for (int i = 1; i < lines.Length; i += 7) { var line = lines[i].Replace("facet normal", "").Trim(); if (line.Contains("endsolid")) { // end of file break; } var normal = Vector.Parse(line); normals.Add(normal); for (int j = i + 2; j < i + 5; j++) { line = lines[j].Replace("vertex ", "").Trim(); var vertex = Vector.Parse(line); vertices.Add(vertex); } } var model = new StlModel(name, vertices, normals); return(model); }
// Convert geometry from STL format to mesh format. public static Mesh StlModelToMesh(StlModel model) { var verts = model.vertices; var norms = model.normals; int triCount = model.TriangleCount; // Hashmap used to keep track of overlapping vertices and share them between triangles. Dictionary <Vector, int> hash = new Dictionary <Vector, int>(); List <Vector> vertices = new List <Vector>(); List <Vector> normals = new List <Vector>(); List <int> indices = new List <int>(); for (int i = 0; i < triCount; i++) { var norm = norms[i].Normalized; for (int j = 0; j < 3; j++) { var v = verts[i * 3 + j]; if (hash.TryGetValue(v, out var sharedIndex)) { // An overlapping vertex had already been seen, use shared index. indices.Add(sharedIndex); // Accumulate normals of triangles using the same vertex normals[sharedIndex] += norm; } else { // New vertex int index = vertices.Count; vertices.Add(v); normals.Add(norm); indices.Add(index); hash.Add(v, index); } } } // Normalize the accumulated normal for each vertex, not the most accurate solution but okay in this case. for (int i = 0; i < normals.Count; i++) { normals[i] = normals[i].Normalized; } var mesh = new Mesh(model.name, vertices, normals, indices); return(mesh); }
// Convert geometry from mesh format to STL format. public static StlModel MeshToStlModel(Mesh mesh) { var triCount = mesh.TriangleCount; List <Vector> vertices = new List <Vector>(); List <Vector> normals = new List <Vector>(); for (int i = 0; i < triCount; i++) { var i0 = mesh.indices[i * 3 + 0]; var i1 = mesh.indices[i * 3 + 1]; var i2 = mesh.indices[i * 3 + 2]; var v0 = mesh.vertices[i0]; var v1 = mesh.vertices[i1]; var v2 = mesh.vertices[i2]; var n0 = mesh.normals[i0]; var n1 = mesh.normals[i1]; var n2 = mesh.normals[i2]; vertices.Add(v0); vertices.Add(v1); vertices.Add(v2); var nMean = (n0 + n1 + n2).Normalized; var r1 = (v1 - v0).Normalized; var r2 = (v2 - v0).Normalized; // Normal of the triangle is either nCross or -nCross but we are not sure about the r1 and r2 direction // at this point. Compare with the mean normal of corner vertices to deduce the direction. var nCross = Vector.Cross(r1, r2); var dot = Vector.Dot(nCross, nMean); var n = dot > 0 ? nCross : -nCross; normals.Add(n.Normalized); } var stlModel = new StlModel(mesh.name, vertices, normals); return(stlModel); }