/// <summary> /// available after call to UpdateSection() /// </summary> public DMesh3 GetSectionMesh(double simplifyTol = 0.01) { DMesh3 mesh = new DMesh3(); if (localCurves.Loops == null) { return(mesh); } List <GeneralPolygon2d> solids = GetSolids(); foreach (GeneralPolygon2d poly in solids) { poly.Simplify(simplifyTol, simplifyTol / 10, true); TriangulatedPolygonGenerator gen = new TriangulatedPolygonGenerator() { Polygon = poly }; DMesh3 polyMesh = gen.Generate().MakeDMesh(); MeshTransforms.PerVertexTransform(polyMesh, (uv) => { return(frameL.FromPlaneUV((Vector2f)uv.xy, 2)); }); MeshEditor.Append(mesh, polyMesh); } if (OutputSpace != CoordSpace.ObjectCoords) { MeshTransforms.PerVertexTransform(mesh, (v) => { return(SceneTransforms.TransformTo((Vector3f)v, SO, CoordSpace.ObjectCoords, OutputSpace)); }); } return(mesh); }
/// <summary> /// Generates a row of cylinders tessellated w/ different chord lengths /// eg 10x1cm : CalibrationModelGenerator.MakePrintStepSizeTest(10.0f, 10.0f, 0.1, 1.0, 10); /// </summary> public static DMesh3 MakePrintStepSizeTest(double cylDiam, double cylHeight, double lowStep, double highStep, int nSteps) { double spacing = 2.0f; float r = (float)cylDiam * 0.5f; double cx = 0.5 * (nSteps * cylDiam + (nSteps - 1) * spacing); DMesh3 accumMesh = new DMesh3(); double cur_x = -cx + cylDiam / 2; for (int k = 0; k < nSteps; ++k) { double t = (double)k / (double)(nSteps - 1); double chord_len = (1.0 - t) * lowStep + (t) * highStep; int slices = (int)((MathUtil.TwoPI * r) / chord_len); CappedCylinderGenerator cylgen = new CappedCylinderGenerator() { BaseRadius = r, TopRadius = r, Height = (float)cylHeight, Slices = slices, NoSharedVertices = false }; DMesh3 cylMesh = cylgen.Generate().MakeDMesh(); MeshTransforms.Translate(cylMesh, -cylMesh.CachedBounds.Min.y * Vector3d.AxisY); MeshTransforms.Translate(cylMesh, cur_x * Vector3d.AxisX); cur_x += cylDiam + spacing; MeshEditor.Append(accumMesh, cylMesh); } MeshTransforms.ConvertYUpToZUp(accumMesh); return(accumMesh); }
public override fMesh MakeGeometry(AxisGizmoFlags widget) { switch (widget) { case AxisGizmoFlags.AxisTranslateY: if (MyAxisTranslateY == null) { Radial3DArrowGenerator arrowGen = new Radial3DArrowGenerator() { HeadLength = 2.0f, TipRadius = 0.1f, StickLength = 1.5f, Clockwise = true }; DMesh3 mesh = arrowGen.Generate().MakeDMesh(); MeshNormals.QuickCompute(mesh); MeshTransforms.Translate(mesh, 0.5 * Vector3d.AxisY); DMesh3 flip = new DMesh3(mesh); MeshTransforms.Rotate(flip, Vector3d.Zero, Quaterniond.AxisAngleD(Vector3d.AxisX, 180)); MeshEditor.Append(mesh, flip); MyAxisTranslateY = new fMesh(mesh); } return(MyAxisTranslateY); default: return(null); } }
public override void Apply() { if (current_result_is_partial) { PreviewSO.EditAndUpdateMesh((mesh) => { mesh.ReverseOrientation(); MeshEditor.Append(mesh, combineMesh); }, GeometryEditTypes.ArbitraryEdit); } base.Apply(); }
public DMesh3 GetCombinedMesh(int nLayerStep = 1) { DMesh3 fullMesh = new DMesh3(); double[] z = LayerMeshes.Keys.ToArray(); List <DMesh3>[] layers = LayerMeshes.Values.ToArray(); Array.Sort(z, layers); nLayerStep = MathUtil.Clamp(nLayerStep, 1, 999999); for (int li = 0; li < layers.Length; li += nLayerStep) { var meshlist = layers[li]; foreach (var mesh in meshlist) { MeshEditor.Append(fullMesh, mesh); } } return(fullMesh); }
public override void Apply() { if (current_result_is_partial) { PreviewSO.EditAndUpdateMesh((mesh) => { if (ShellDirection == ShellDirections.Outer) { combineMesh.ReverseOrientation(); } else if (ShellDirection == ShellDirections.Inner) { mesh.ReverseOrientation(); } MeshEditor.Append(mesh, combineMesh); }, GeometryEditTypes.ArbitraryEdit); } base.Apply(); }
public DMesh3 MakeElementsMesh(Polygon2d spanProfile, Polygon2d loopProfile) { var result = new DMesh3(); validate_topology(); foreach (EdgeSpan span in Spans) { DCurve3 curve = span.ToCurve(Mesh); var tubegen = new TubeGenerator(curve, spanProfile); MeshEditor.Append(result, tubegen.Generate().MakeDMesh()); } foreach (EdgeLoop loop in Loops) { DCurve3 curve = loop.ToCurve(Mesh); var tubegen = new TubeGenerator(curve, loopProfile); MeshEditor.Append(result, tubegen.Generate().MakeDMesh()); } return(result); }
public DMesh3 Make3DTubes(Interval1i layer_range, double merge_tol, double tube_radius) { Polygon2d tube_profile = Polygon2d.MakeCircle(tube_radius, 8); Frame3f frame = Frame3f.Identity; DMesh3 full_mesh = new DMesh3(); foreach (int layer_i in layer_range) { PlanarSlice slice = Slices[layer_i]; frame.Origin = new Vector3f(0, 0, slice.Z); foreach (GeneralPolygon2d gpoly in slice.Solids) { List <Polygon2d> polys = new List <Polygon2d>() { gpoly.Outer }; polys.AddRange(gpoly.Holes); foreach (Polygon2d poly in polys) { Polygon2d simpPoly = new Polygon2d(poly); simpPoly.Simplify(merge_tol, 0.01, true); if (simpPoly.VertexCount < 3) { Util.gBreakToDebugger(); } TubeGenerator tubegen = new TubeGenerator(simpPoly, frame, tube_profile) { NoSharedVertices = true }; DMesh3 tubeMesh = tubegen.Generate().MakeDMesh(); MeshEditor.Append(full_mesh, tubeMesh); } } } return(full_mesh); }
public static void test_sort_mesh_components() { DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_nested_spheres.obj"); MeshConnectedComponents components = new MeshConnectedComponents(mesh); components.FindConnectedT(); DSubmesh3Set componentMeshes = new DSubmesh3Set(mesh, components); LocalProfiler p = new LocalProfiler(); p.Start("sort"); MeshSpatialSort sorter = new MeshSpatialSort(); foreach (DSubmesh3 submesh in componentMeshes) { sorter.AddMesh(submesh.SubMesh, submesh); } sorter.Sort(); p.Stop("sort"); System.Console.WriteLine(p.AllTimes()); DMesh3 resultMesh = new DMesh3(); foreach (var solid in sorter.Solids) { if (solid.Outer.InsideOf.Count == 0) { MeshEditor.Append(resultMesh, solid.Outer.Mesh); } } TestUtil.WriteTestOutputMesh(resultMesh, "mesh_components.obj"); }
public static void test_tube_generator() { Polygon2d circle_path = Polygon2d.MakeCircle(50, 64); PolyLine2d arc_path = new PolyLine2d(circle_path.Vertices.Take(circle_path.VertexCount / 2)); Polygon2d irreg_path = new Polygon2d(); for (int k = 0; k < circle_path.VertexCount; ++k) { irreg_path.AppendVertex(circle_path[k]); k += k / 2; } PolyLine2d irreg_arc_path = new PolyLine2d(irreg_path.Vertices.Take(circle_path.VertexCount - 1)); Polygon2d square_profile = Polygon2d.MakeCircle(7, 32); square_profile.Translate(4 * Vector2d.One); //square_profile[0] = 20 * square_profile[0].Normalized; bool no_shared = true; WriteGeneratedMesh( new TubeGenerator(circle_path, Frame3f.Identity, square_profile) { WantUVs = true, NoSharedVertices = no_shared }, "tubegen_loop_standarduv.obj"); WriteGeneratedMesh( new TubeGenerator(irreg_path, Frame3f.Identity, square_profile) { WantUVs = true, NoSharedVertices = no_shared }, "tubegen_irregloop_standarduv.obj"); WriteGeneratedMesh( new TubeGenerator(arc_path, Frame3f.Identity, square_profile) { WantUVs = true, NoSharedVertices = no_shared }, "tubegen_arc_standarduv.obj"); WriteGeneratedMesh( new TubeGenerator(irreg_arc_path, Frame3f.Identity, square_profile) { WantUVs = true, NoSharedVertices = no_shared }, "tubegen_irregarc_standarduv.obj"); // append tube border around each hole of input mesh DMesh3 inMesh = TestUtil.LoadTestInputMesh("n_holed_bunny.obj"); Polygon2d bdrycirc = Polygon2d.MakeCircle(0.25, 6); MeshBoundaryLoops loops = new MeshBoundaryLoops(inMesh); foreach (EdgeLoop loop in loops) { DCurve3 curve = loop.ToCurve().ResampleSharpTurns(); TubeGenerator gen = new TubeGenerator(curve, bdrycirc) { NoSharedVertices = false }; MeshEditor.Append(inMesh, gen.Generate().MakeDMesh()); } TestUtil.WriteTestOutputMesh(inMesh, "boundary_tubes.obj"); }
public virtual void Update() { base.begin_update(); int start_timestamp = this.CurrentInputTimestamp; if (MeshSource == null) { throw new Exception("SeparateSolidsOp: must set valid MeshSource to compute!"); } ResultMeshes = null; try { DMesh3 meshIn = new DMesh3(MeshSource.GetDMeshUnsafe()); MeshConnectedComponents comp = new MeshConnectedComponents(meshIn); comp.FindConnectedT(); DSubmesh3Set subMeshes = new DSubmesh3Set(meshIn, comp); List <DMesh3> curMeshes = new List <DMesh3>(); foreach (var submesh in subMeshes) { curMeshes.Add(submesh.SubMesh); } if (group_nested_shells) { MeshSpatialSort sort = new MeshSpatialSort(); foreach (var mesh in curMeshes) { sort.AddMesh(mesh, mesh); } sort.Sort(); curMeshes.Clear(); foreach (var solid in sort.Solids) { DMesh3 outer = solid.Outer.Mesh; if (orient_nested_shells && is_outward_oriented(outer) == false) { outer.ReverseOrientation(); } foreach (var hole in solid.Cavities) { if (orient_nested_shells && hole.Mesh.CachedIsClosed && is_outward_oriented(hole.Mesh) == true) { hole.Mesh.ReverseOrientation(); } MeshEditor.Append(outer, hole.Mesh); } curMeshes.Add(outer); } } ResultMeshes = curMeshes; base.complete_update(); } catch (Exception) { ResultMeshes = new List <DMesh3>(); base.complete_update(); throw; } }
protected virtual void compute_shell_extrude() { DMesh3 mesh = new DMesh3(MeshSource.GetDMeshUnsafe()); MeshNormals.QuickCompute(mesh); if (shell_direction == ShellDirections.Symmetric) { double thickness = shell_thickness * 0.5; DMesh3 outerMesh = new DMesh3(mesh); MeshExtrudeMesh outerExtrude = new MeshExtrudeMesh(outerMesh); outerExtrude.ExtrudedPositionF = (v, n, vid) => { return(v + thickness * (Vector3d)n); }; if (outerExtrude.Extrude() == false) { throw new Exception("MeshShellOp.compute_shell_extrude: outer Extrude() returned false!"); } MeshEditor.RemoveTriangles(outerMesh, outerExtrude.InitialTriangles); MeshExtrudeMesh innerExtrude = new MeshExtrudeMesh(mesh); innerExtrude.IsPositiveOffset = false; innerExtrude.ExtrudedPositionF = (v, n, vid) => { return(v - thickness * (Vector3d)n); }; if (innerExtrude.Extrude() == false) { throw new Exception("MeshShellOp.compute_shell_extrude: inner Extrude() returned false!"); } MeshEditor.RemoveTriangles(mesh, innerExtrude.InitialTriangles); MeshEditor.Append(mesh, outerMesh); if (cached_is_closed == false) { // cheating! MergeCoincidentEdges merge = new MergeCoincidentEdges(mesh); merge.Apply(); } } else { double thickness = (shell_direction == ShellDirections.Outer) ? shell_thickness : -shell_thickness; MeshExtrudeMesh extrude = new MeshExtrudeMesh(mesh); extrude.IsPositiveOffset = (shell_direction == ShellDirections.Outer); extrude.ExtrudedPositionF = (v, n, vid) => { return(v + thickness * (Vector3d)n); }; if (extrude.Extrude() == false) { throw new Exception("MeshShellOp.compute_shell_extrude: Extrude() returned false!"); } if (shell_surface_only && cached_is_closed) { MeshEditor.RemoveTriangles(mesh, extrude.InitialTriangles); if (shell_direction == ShellDirections.Inner) { mesh.ReverseOrientation(); } if (shell_direction == ShellDirections.Inner || shell_direction == ShellDirections.Outer) { mesh.AttachMetadata("is_partial", new object()); } } } if (is_invalidated()) { return; } ResultMesh = mesh; }
public static void test_autorepair_thingi10k() { //const string THINGIROOT = "E:\\Thingi10K\\"; string WRITEPATH = "E:\\Thingi10K\\repair_fails\\"; //string[] files = File.ReadAllLines("E:\\Thingi10K\\current\\thingi10k_open.txt"); string[] files = File.ReadAllLines("C:\\git\\gsGeometryTests\\test_output\\thingi10k_autorepair_failures.txt"); //string[] files = new string[] { // "E:\\Thingi10K\\raw_meshes\\37011.stl" //}; SafeListBuilder <string> failures = new SafeListBuilder <string>(); int count = 0; int MAX_NUM_FILES = 10000; gParallel.ForEach(files, (filename) => { if (count > MAX_NUM_FILES) { return; } int i = count; Interlocked.Increment(ref count); if (i % 10 == 0) { System.Console.WriteLine("{0} / {1}", i, files.Length); } long start_ticks = DateTime.Now.Ticks; DMesh3Builder builder = new DMesh3Builder(); StandardMeshReader reader = new StandardMeshReader() { MeshBuilder = builder }; IOReadResult result = reader.Read(filename, ReadOptions.Defaults); if (result.code != IOCode.Ok) { System.Console.WriteLine("{0} FAILED TO READ!", filename); failures.SafeAdd(filename); return; } DMesh3 mesh = builder.Meshes[0]; for (int k = 1; k < builder.Meshes.Count; ++k) { MeshEditor.Append(mesh, builder.Meshes[k]); } DMesh3 before = new DMesh3(mesh); try { MeshAutoRepair repair = new MeshAutoRepair(mesh); repair.Apply(); } catch (Exception e) { System.Console.WriteLine("EXCEPTION {0} : {1}", filename, e.Message); failures.SafeAdd(filename); return; } if (mesh.IsClosed() == false) { failures.SafeAdd(filename); Util.WriteDebugMesh(before, WRITEPATH + Path.GetFileNameWithoutExtension(filename) + ".obj"); Util.WriteDebugMesh(mesh, WRITEPATH + Path.GetFileNameWithoutExtension(filename) + ".failed.obj"); return; } else { if (mesh.CheckValidity(false, FailMode.ReturnOnly) == false) { System.Console.WriteLine("INVALID {0}", filename); failures.SafeAdd(filename); Util.WriteDebugMesh(before, WRITEPATH + Path.GetFileNameWithoutExtension(filename) + ".obj"); Util.WriteDebugMesh(mesh, WRITEPATH + Path.GetFileNameWithoutExtension(filename) + ".invalid.obj"); return; } } }); //foreach (string failure in failures.Result) { // System.Console.WriteLine("FAIL: {0}", failure); //} System.Console.WriteLine("repaired {0} of {1}", files.Length - failures.Result.Count, files.Length); TestUtil.WriteTestOutputStrings(make_strings(failures), "thingi10k_autorepair_failures_new.txt"); }
protected virtual DMesh3 compute_wrap() { DMesh3 meshIn = MeshSource.GetDMeshUnsafe(); double unsigned_offset = Math.Abs(distance); if (cached_sdf == null || unsigned_offset > cached_sdf_max_offset || grid_cell_size != cached_sdf.CellSize) { DMeshAABBTree3 use_spatial = input_spatial; CachingMeshSDF sdf = new CachingMeshSDF(meshIn, grid_cell_size, use_spatial); sdf.MaxOffsetDistance = 2 * (float)unsigned_offset; sdf.CancelF = is_invalidated; sdf.Initialize(); if (is_invalidated()) { return(null); } cached_sdf = sdf; cached_sdf_max_offset = unsigned_offset; cached_sdf_bounds = meshIn.CachedBounds; } var grid_iso = new CachingMeshSDFImplicit(cached_sdf); // currently MCPro-Continuation does not work w/ non-zero // isovalues, so we have to shift our target offset externally var iso = new ImplicitOffset3d() { A = grid_iso, Offset = distance }; MarchingCubesPro c = new MarchingCubesPro(); c.Implicit = iso; c.Bounds = cached_sdf_bounds; c.CubeSize = mesh_cell_size; c.Bounds.Expand(distance + 3 * c.CubeSize); c.CancelF = is_invalidated; c.GenerateContinuation(offset_seeds(meshIn, distance)); if (is_invalidated()) { return(null); } Reducer r = new Reducer(c.Mesh); r.FastCollapsePass(c.CubeSize * 0.5, 3, true); if (is_invalidated()) { return(null); } if (min_component_volume > 0) { MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume); } if (is_invalidated()) { return(null); } DMesh3 offsetMesh = c.Mesh; MeshConnectedComponents comp = new MeshConnectedComponents(offsetMesh); comp.FindConnectedT(); if (is_invalidated()) { return(null); } DSubmesh3Set subMeshes = new DSubmesh3Set(offsetMesh, comp); if (is_invalidated()) { return(null); } MeshSpatialSort sort = new MeshSpatialSort(); foreach (var subMesh in subMeshes) { sort.AddMesh(subMesh.SubMesh, subMesh); } sort.Sort(); if (is_invalidated()) { return(null); } DMesh3 outerMesh = new DMesh3(); foreach (var solid in sort.Solids) { DMesh3 outer = solid.Outer.Mesh; //if (is_outward_oriented(outer) == false) // outer.ReverseOrientation(); MeshEditor.Append(outerMesh, outer); } if (is_invalidated()) { return(null); } return(compute_inset(outerMesh)); }
static void Main(string[] args) { CommandArgumentSet arguments = new CommandArgumentSet(); arguments.Register("-tcount", int.MaxValue); arguments.Register("-percent", 50.0f); arguments.Register("-v", false); arguments.Register("-output", ""); if (arguments.Parse(args) == false) { return; } if (arguments.Filenames.Count != 1) { print_usage(); return; } string inputFilename = arguments.Filenames[0]; if (!File.Exists(inputFilename)) { System.Console.WriteLine("File {0} does not exist", inputFilename); return; } string outputFilename = Path.GetFileNameWithoutExtension(inputFilename); string format = Path.GetExtension(inputFilename); outputFilename = outputFilename + ".reduced" + format; if (arguments.Saw("-output")) { outputFilename = arguments.Strings["-output"]; } int triCount = int.MaxValue; if (arguments.Saw("-tcount")) { triCount = arguments.Integers["-tcount"]; } float percent = 50.0f; if (arguments.Saw("-percent")) { percent = arguments.Floats["-percent"]; } bool verbose = false; if (arguments.Saw("-v")) { verbose = arguments.Flags["-v"]; } List <DMesh3> meshes; try { DMesh3Builder builder = new DMesh3Builder(); IOReadResult result = StandardMeshReader.ReadFile(inputFilename, ReadOptions.Defaults, builder); if (result.code != IOCode.Ok) { System.Console.WriteLine("Error reading {0} : {1}", inputFilename, result.message); return; } meshes = builder.Meshes; } catch (Exception e) { System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message); return; } if (meshes.Count == 0) { System.Console.WriteLine("file did not contain any valid meshes"); return; } DMesh3 mesh = meshes[0]; for (int k = 1; k < meshes.Count; ++k) { MeshEditor.Append(mesh, meshes[k]); } if (mesh.TriangleCount == 0) { System.Console.WriteLine("mesh does not contain any triangles"); return; } if (verbose) { System.Console.WriteLine("initial mesh contains {0} triangles", mesh.TriangleCount); } Reducer r = new Reducer(mesh); if (triCount < int.MaxValue) { if (verbose) { System.Console.Write("reducing to {0} triangles...", triCount); } r.ReduceToTriangleCount(triCount); } else { int nT = (int)((float)mesh.TriangleCount * percent / 100.0f); nT = MathUtil.Clamp(nT, 1, mesh.TriangleCount); if (verbose) { System.Console.Write("reducing to {0} triangles...", nT); } r.ReduceToTriangleCount(nT); } if (verbose) { System.Console.WriteLine("done!"); } try { IOWriteResult wresult = StandardMeshWriter.WriteMesh(outputFilename, mesh, WriteOptions.Defaults); if (wresult.code != IOCode.Ok) { System.Console.WriteLine("Error writing {0} : {1}", inputFilename, wresult.message); return; } } catch (Exception e) { System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message); return; } return; }
public static void Main(string[] args) { CommandArgumentSet arguments = new CommandArgumentSet(); //arguments.Register("-tcount", int.MaxValue); //arguments.Register("-percent", 50.0f); //arguments.Register("-v", false); arguments.Register("-output", ""); if (arguments.Parse(args) == false) { return; } if (arguments.Filenames.Count != 1) { print_usage(); return; } string inputFilename = arguments.Filenames[0]; if (!File.Exists(inputFilename)) { System.Console.WriteLine("File {0} does not exist", inputFilename); return; } string outputFilename = Path.GetFileNameWithoutExtension(inputFilename); string format = Path.GetExtension(inputFilename); outputFilename = outputFilename + ".repaired" + format; if (arguments.Saw("-output")) { outputFilename = arguments.Strings["-output"]; } //int triCount = int.MaxValue; //if (arguments.Saw("-tcount")) // triCount = arguments.Integers["-tcount"]; //float percent = 50.0f; //if (arguments.Saw("-percent")) // percent = arguments.Floats["-percent"]; bool verbose = true; //if (arguments.Saw("-v")) // verbose = arguments.Flags["-v"]; List <DMesh3> meshes; try { DMesh3Builder builder = new DMesh3Builder(); IOReadResult result = StandardMeshReader.ReadFile(inputFilename, ReadOptions.Defaults, builder); if (result.code != IOCode.Ok) { System.Console.WriteLine("Error reading {0} : {1}", inputFilename, result.message); return; } meshes = builder.Meshes; } catch (Exception e) { System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message); return; } if (meshes.Count == 0) { System.Console.WriteLine("file did not contain any valid meshes"); return; } DMesh3 mesh = meshes[0]; for (int k = 1; k < meshes.Count; ++k) { MeshEditor.Append(mesh, meshes[k]); } if (mesh.TriangleCount == 0) { System.Console.WriteLine("mesh does not contain any triangles"); return; } if (verbose) { System.Console.WriteLine("initial mesh contains {0} triangles", mesh.TriangleCount); } if (verbose) { System.Console.WriteLine("Repairing...", mesh.TriangleCount); } MeshAutoRepair repair = new MeshAutoRepair(mesh); repair.RemoveMode = MeshAutoRepair.RemoveModes.None; bool bOK = repair.Apply(); if (verbose) { if (bOK == false) { System.Console.WriteLine("repair failed!"); } else { System.Console.WriteLine("done! repaired mesh contains {0} triangles", mesh.TriangleCount); } } try { IOWriteResult wresult = StandardMeshWriter.WriteMesh(outputFilename, mesh, WriteOptions.Defaults); if (wresult.code != IOCode.Ok) { System.Console.WriteLine("Error writing {0} : {1}", inputFilename, wresult.message); return; } } catch (Exception e) { System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message); return; } return; }
public static void test_write_solids() { //string FORMAT = ".obj"; string FORMAT = ".g3mesh"; string WRITEPATH = "E:\\Thingi10K\\closed\\"; string[] files = File.ReadAllLines("E:\\Thingi10K\\current\\thingi10k_closed.txt"); SafeListBuilder <string> failures = new SafeListBuilder <string>(); if (!Directory.Exists(WRITEPATH)) { Directory.CreateDirectory(WRITEPATH); } int k = 0; gParallel.ForEach(files, (filename) => { int i = k; Interlocked.Increment(ref k); if (i % 500 == 0) { System.Console.WriteLine("{0} : {1}", i, files.Length); } long start_ticks = DateTime.Now.Ticks; DMesh3Builder builder = new DMesh3Builder(); StandardMeshReader reader = new StandardMeshReader() { MeshBuilder = builder }; IOReadResult result = reader.Read(filename, ReadOptions.Defaults); if (result.code != IOCode.Ok) { System.Console.WriteLine("{0} FAILED!", filename); failures.SafeAdd(filename); return; } DMesh3 combineMesh = new DMesh3(); if (builder.Meshes.Count == 1) { combineMesh = builder.Meshes[0]; } else { foreach (DMesh3 mesh in builder.Meshes) { MeshEditor.Append(combineMesh, mesh); } } if (combineMesh.IsClosed() == false) { MergeCoincidentEdges closeCracks = new MergeCoincidentEdges(combineMesh); closeCracks.Apply(); } if (combineMesh.IsClosed() == false) { System.Console.WriteLine("NOT CLOSED: {0}", filename); return; } string outPath = Path.Combine(WRITEPATH, Path.GetFileNameWithoutExtension(filename) + FORMAT); StandardMeshWriter.WriteMesh(outPath, combineMesh, WriteOptions.Defaults); }); }