public DMesh3 remesh_constraints_fixedverts(int iterations, DMesh3 mesh, double min, double max, double angle) { AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > angle) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.Precompute(); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = min; r.MaxEdgeLength = max; r.EnableSmoothing = true; r.SmoothSpeedT = 1; for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); mesh.CheckValidity(); } return(mesh); }
public static DMesh3 MakeRemeshedCappedCylinder(double fResFactor = 1.0) { DMesh3 mesh = MakeCappedCylinder(false, 128); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new g3.Vector3f(1, 2, 1)); // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; MeshConstraints cons = new MeshConstraints(); EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = 0.1f * fResFactor; r.MaxEdgeLength = 0.2f * fResFactor; r.EnableSmoothing = true; r.SmoothSpeedT = 0.5f; for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); } return(mesh); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { bool flip = true; bool collapse = true; bool split = true; bool topology = true; DA.GetData(0, ref flip); DA.GetData(1, ref collapse); DA.GetData(2, ref split); DA.GetData(3, ref topology); EdgeRefineFlags constraint = EdgeRefineFlags.NoConstraint; if (!flip) { constraint = constraint | EdgeRefineFlags.NoFlip; } if (!collapse) { constraint = constraint | EdgeRefineFlags.NoCollapse; } if (!split) { constraint = constraint | EdgeRefineFlags.NoSplit; } if (topology) { constraint = constraint | EdgeRefineFlags.PreserveTopology; } DA.SetData(0, (int)constraint); }
public EdgeConstraint(EdgeRefineFlags rflags, IProjectionTarget target) { refineFlags = rflags; Target = target; }
public IProjectionTarget Target; // edge is associated with this projection Target. // Currently only used as information, we do not explicitly // project edges onto targets (must also set VertexConstraint) public EdgeConstraint(EdgeRefineFlags rflags) { refineFlags = rflags; Target = null; }
public EdgeConstraint(EdgeRefineFlags rflags, IProjectionTarget target) { refineFlags = rflags; Target = target; TrackingSetID = -1; }
public int TrackingSetID; // not actually a constraint, but allows is to find descendents // of an constraind input edge public EdgeConstraint(EdgeRefineFlags rflags) { refineFlags = rflags; Target = null; TrackingSetID = -1; }
public static void test_reduce_constraints_fixedverts() { int Slices = 128; DMesh3 mesh = TestUtil.MakeCappedCylinder(false, Slices); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1)); mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_before.obj"); } // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.PreserveTopology; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags) { TrackingSetID = 1 }); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Reducer r = new Reducer(mesh); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.ReduceToTriangleCount(50); mesh.CheckValidity(); if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_after.obj"); } }
public static Mesh RemeshTest(Mesh inMesh, double fResScale = 1.0, int iterations = 50) { inMesh.Faces.ConvertQuadsToTriangles(); DMesh3 mesh = inMesh.ToDMesh3(); mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.Precompute(); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = 0.5 * fResScale; r.MaxEdgeLength = 1.0 * fResScale; r.EnableSmoothing = true; r.SmoothSpeedT = 0.5; try { for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); // mesh.CheckValidity(); } } catch { // ignore } return(mesh.ToRhinoMesh()); }
public static DMesh3 RemeshMesh(g3.DMesh3 mesh, float minEdgeLength, float maxEdgeLength, float contraintAngle, float smoothSpeed, int smoothPasses, List <Line3d> constrainedLines) { // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; MeshConstraints cons = new MeshConstraints(); EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); Index2i ev = mesh.GetEdgeV(eid); if (fAngle > contraintAngle) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); // TODO Ids based off of ?? What? int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } Vector3d p1 = mesh.GetVertex(ev.a); Vector3d p2 = mesh.GetVertex(ev.b); foreach (var v in constrainedLines) { if (p1.CompareTo(v.Origin) == 0) { Vector3d p = v.PointAt(1.0); if (p2.CompareTo(p) == 0) { cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained); break; } } } foreach (var v in constrainedLines) { if (p2.CompareTo(v.Origin) == 0) { Vector3d p = v.PointAt(1.0); if (p1.CompareTo(p) == 0) { cons.SetOrUpdateEdgeConstraint(eid, EdgeConstraint.FullyConstrained); break; } } } } Remesher r = new Remesher(mesh); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = minEdgeLength; //0.1f; r.MaxEdgeLength = maxEdgeLength; // 0.2f; r.EnableSmoothing = true; r.SmoothSpeedT = smoothSpeed; // .5; for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20 { r.BasicRemeshPass(); } return(mesh); }
// public static DMesh3 RemeshMeshNew(g3.DMesh3 mesh, float minEdgeLength, float maxEdgeLength, float contraintAngle, float smoothSpeed, int smoothPasses, g3.DMesh3 projectMeshInput = null, float projectAmount = 1.0f, float projectedDistance = float.MaxValue) { g3.DMesh3 projectMesh = projectMeshInput; if (projectMesh == null) { projectMesh = mesh; } DMesh3 projectMeshCopy = new DMesh3(projectMesh); DMeshAABBTree3 treeProject = new DMeshAABBTree3(projectMeshCopy); treeProject.Build(); GopherMeshProjectionTarget targetProject = new GopherMeshProjectionTarget() { Mesh = projectMeshCopy, Spatial = treeProject, amount = projectAmount, maxDistance = projectedDistance }; MeshConstraints cons = new MeshConstraints(); EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > contraintAngle) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); //int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2; //int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true)); } } // TODO Constrain Vertices too far away foreach (int vid in mesh.VertexIndices()) { var v = mesh.GetVertex(vid); //v.Distance() //targetProject.Project() } Remesher rProjected = new Remesher(mesh); rProjected.SetExternalConstraints(cons); rProjected.SetProjectionTarget(targetProject); rProjected.Precompute(); rProjected.EnableFlips = rProjected.EnableSplits = rProjected.EnableCollapses = true; rProjected.MinEdgeLength = minEdgeLength; //0.1f; rProjected.MaxEdgeLength = maxEdgeLength; // 0.2f; rProjected.EnableSmoothing = true; rProjected.SmoothSpeedT = smoothSpeed; // .5; if (projectMeshInput != null) { float bestSmoothPassProjectAmount = projectAmount / smoothPasses; float testbestSmoothPassProjectAmount = float.MaxValue; for (float smoothPassProjectAmount = -.1f; smoothPassProjectAmount < 1.1f; smoothPassProjectAmount += 0.005f) { double test = 0; for (int i = 0; i < smoothPasses; i++) { test = 1.0 * smoothPassProjectAmount + test * (1 - smoothPassProjectAmount); } if (Math.Abs(test - projectAmount) < Math.Abs(testbestSmoothPassProjectAmount - projectAmount)) { bestSmoothPassProjectAmount = (float)smoothPassProjectAmount; testbestSmoothPassProjectAmount = (float)test; } } targetProject.amount = bestSmoothPassProjectAmount; targetProject.maxDistance = projectedDistance; for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20 { rProjected.BasicRemeshPass(); } } else { for (int k = 0; k < smoothPasses; ++k) // smoothPasses = 20 { rProjected.BasicRemeshPass(); } } return(mesh); }
public static void test_remesh_constraints_vertcurves() { int Slices = 16; DMesh3 mesh = TestUtil.MakeCappedCylinder(false, Slices); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1)); //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(0.25); //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(1.0); mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget mesh_target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; // cylinder projection target CylinderProjectionTarget cyl_target = new CylinderProjectionTarget() { Cylinder = new Cylinder3d(new Vector3d(0, 1, 0), Vector3d.AxisY, 1, 2) }; //IProjectionTarget target = mesh_target; IProjectionTarget target = cyl_target; // construct projection target circles CircleProjectionTarget bottomCons = new CircleProjectionTarget() { Circle = new Circle3d(bounds.Center, 1.0) }; bottomCons.Circle.Center.y = bounds.Min.y; CircleProjectionTarget topCons = new CircleProjectionTarget() { Circle = new Circle3d(bounds.Center, 1.0) }; topCons.Circle.Center.y = bounds.Max.y; if (WriteDebugMeshes) { TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_before.obj"); } // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; bool bConstrainVertices = true; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { Index2i ev = mesh.GetEdgeV(eid); Vector3d ev0 = mesh.GetVertex(ev[0]); Vector3d ev1 = mesh.GetVertex(ev[1]); CircleProjectionTarget loopTarget = null; if (ev0.y > bounds.Center.y && ev1.y > bounds.Center.y) { loopTarget = topCons; } else if (ev0.y < bounds.Center.y && ev1.y < bounds.Center.y) { loopTarget = bottomCons; } cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags, loopTarget)); if (bConstrainVertices && loopTarget != null) { cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(loopTarget)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(loopTarget)); } } } Remesher r = new Remesher(mesh); //r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.Precompute(); r.ENABLE_PROFILING = true; var stopwatch = Stopwatch.StartNew(); //double fResScale = 1.0f; double fResScale = 0.5f; r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = 0.1f * fResScale; r.MaxEdgeLength = 0.2f * fResScale; r.EnableSmoothing = true; r.SmoothSpeedT = 1.0f; try { for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); mesh.CheckValidity(); } } catch { // continue; } stopwatch.Stop(); System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed); if (WriteDebugMeshes) { TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_after.obj"); } }
public static void test_remesh_constraints_fixedverts() { int Slices = 128; DMesh3 mesh = TestUtil.MakeCappedCylinder(false, Slices); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1)); mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; if (WriteDebugMeshes) { TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_before.obj"); } // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.Precompute(); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); var stopwatch = Stopwatch.StartNew(); //double fResScale = 1.0f; double fResScale = 0.5f; r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = 0.1f * fResScale; r.MaxEdgeLength = 0.2f * fResScale; r.EnableSmoothing = true; r.SmoothSpeedT = 0.5f; try { for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); mesh.CheckValidity(); } } catch { // ignore } stopwatch.Stop(); System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed); if (WriteDebugMeshes) { TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_after.obj"); } }
public DMesh3 remesh_constraints_vertcurves(int iterations, DMesh3 mesh, double min, double max, double angle) { mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget mesh_target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; // cylinder projection target CylinderProjectionTarget cyl_target = new CylinderProjectionTarget() { Cylinder = new Cylinder3d(new Vector3D(0, 1, 0), Vector3D.AxisY, 1, 2) }; //IProjectionTarget target = mesh_target; IProjectionTarget target = cyl_target; // construct projection target circles CircleProjectionTarget bottomCons = new CircleProjectionTarget() { Circle = new Circle3d(bounds.Center, 1.0) }; bottomCons.Circle.Center.y = bounds.Min.y; CircleProjectionTarget topCons = new CircleProjectionTarget() { Circle = new Circle3d(bounds.Center, 1.0) }; topCons.Circle.Center.y = bounds.Max.y; // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; bool bConstrainVertices = true; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { Index2i ev = mesh.GetEdgeV(eid); Vector3D ev0 = mesh.GetVertex(ev[0]); Vector3D ev1 = mesh.GetVertex(ev[1]); CircleProjectionTarget loopTarget = null; if (ev0.y > bounds.Center.y && ev1.y > bounds.Center.y) { loopTarget = topCons; } else if (ev0.y < bounds.Center.y && ev1.y < bounds.Center.y) { loopTarget = bottomCons; } cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags, loopTarget)); if (bConstrainVertices && loopTarget != null) { cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(loopTarget)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(loopTarget)); } } } Remesher r = new Remesher(mesh); //r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.Precompute(); r.ENABLE_PROFILING = true; r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = min; r.MaxEdgeLength = max; r.EnableSmoothing = true; r.SmoothSpeedT = 1.0f; for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); mesh.CheckValidity(); } return(mesh); }