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> /// add topological edges/vertices as constraints for remeshing /// </summary> public void AddRemeshConstraints(MeshConstraints constraints) { validate_topology(); int set_index = 10; foreach (EdgeSpan span in Spans) { var target = new DCurveProjectionTarget(span.ToCurve()); MeshConstraintUtil.ConstrainVtxSpanTo(constraints, Mesh, span.Vertices, target, set_index++); } foreach (EdgeLoop loop in Loops) { var target = new DCurveProjectionTarget(loop.ToCurve()); MeshConstraintUtil.ConstrainVtxLoopTo(constraints, Mesh, loop.Vertices, target, set_index++); } VertexConstraint corners = VertexConstraint.Pinned; corners.FixedSetID = -1; foreach (int vid in JunctionVertices) { if (constraints.HasVertexConstraint(vid)) { VertexConstraint v = constraints.GetVertexConstraint(vid); v.Target = null; v.Fixed = true; v.FixedSetID = -1; constraints.SetOrUpdateVertexConstraint(vid, v); } else { constraints.SetOrUpdateVertexConstraint(vid, corners); } } }
void remove_old_vertices(int[] MapV, DMesh3 mesh) { HashSet <int> keepV = new HashSet <int>(); for (int k = 0; k < MapV.Length; ++k) { if (MapV[k] != DMesh3.InvalidID) { keepV.Add(MapV[k]); } } Remesher r = new Remesher(mesh); //r.EnableCollapses = false; //r.EnableSplits = false; //r.EnableFlips = false; r.SmoothSpeedT = 1.0; //r.EnableSmoothing = false; r.PreventNormalFlips = true; r.SetTargetEdgeLength(1.0); //r.EnableSmoothing = false; MeshConstraints c = new MeshConstraints(); foreach (int vid in keepV) { c.SetOrUpdateVertexConstraint(vid, VertexConstraint.Pinned); } r.SetExternalConstraints(c); double minE, maxE, avgE; MeshQueries.EdgeLengthStats(mesh, out minE, out maxE, out avgE); r.SetTargetEdgeLength(avgE * .3); for (int k = 0; k < 10; ++k) { r.BasicRemeshPass(); } //int iter = 0; //while (iter++ < 10) { // r.SetTargetEdgeLength(iter * 1.0); // for (int k = 0; k < 10; ++k) // r.BasicRemeshPass(); //} }
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); }
protected override void SolveInstance(IGH_DataAccess DA) { Mesh m = DA.Fetch <Mesh>("Mesh"); bool fixEdges = DA.Fetch <bool>("FixEdges"); double l = DA.Fetch <double>("EdgeLength"); int iterations = DA.Fetch <int>("Iterations"); List <Point3d> fixPt = DA.FetchList <Point3d>("FixPt"); bool project = DA.Fetch <bool>("Project"); bool loops = DA.Fetch <bool>("Loops"); Mesh mesh = m.DuplicateMesh(); mesh.Faces.ConvertQuadsToTriangles(); double len = (l == 0) ? mesh.GetBoundingBox(false).Diagonal.Length * 0.1 : l; //r.PreventNormalFlips = true; List <int> ids = new List <int>(); Point3d[] pts = mesh.Vertices.ToPoint3dArray(); foreach (Point3d p in fixPt) { ids.Add(NGonsCore.PointUtil.ClosestPoint(p, pts)); } DMesh3 dmesh = mesh.ToDMesh3(); Remesher r = new Remesher(dmesh); r.Precompute(); r.SetTargetEdgeLength(len); r.SmoothSpeedT = 0.5; if (project) { r.SetProjectionTarget(MeshProjectionTarget.Auto(dmesh)); } r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.EnableSmoothing = true; MeshConstraints cons = new MeshConstraints(); if (ids.Count > 0) { foreach (int id in ids) { //cons.SetOrUpdateVertexConstraint(id, new VertexConstraint(true, 1)); cons.SetOrUpdateVertexConstraint(id, VertexConstraint.Pinned); } } r.SetExternalConstraints(cons); r.Precompute(); if (fixEdges) { //r.SetExternalConstraints(new MeshConstraints()); MeshConstraintUtil.FixAllBoundaryEdges(r); MeshConstraintUtil.FixAllBoundaryEdges_AllowSplit(cons, dmesh, 0); //MeshConstraintUtil.FixAllBoundaryEdges_AllowCollapse(cons, dmesh, 0); } if (loops) { MeshConstraintUtil.PreserveBoundaryLoops(r); //project to edge //MeshConstraintUtil.PreserveBoundaryLoops(cons,dmesh);//project to edge } r.SetExternalConstraints(cons); for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); } //output if (ids.Count > 0 && !fixEdges) { this.Message = "Vertices"; } else if (ids.Count == 0 && fixEdges) { this.Message = "Edges"; } else if (ids.Count > 0 && fixEdges) { this.Message = "Vertices + Edges"; } else { this.Message = ""; } dmesh = new DMesh3(dmesh, true); Mesh rmesh = dmesh.ToRhinoMesh(); if (loops) { Mesh mesh_ = rmesh.DuplicateMesh(); Rhino.IndexPair[] closestEdges = new Rhino.IndexPair[fixPt.Count]; int counter = 0; foreach (Point3d p in fixPt) { double[] d = new double[rmesh.TopologyEdges.Count]; int[] eid = new int[rmesh.TopologyEdges.Count]; for (int i = 0; i < rmesh.TopologyEdges.Count; i++) { if (rmesh.TopologyEdges.GetConnectedFaces(i).Length == 1) { Line line = rmesh.TopologyEdges.EdgeLine(i); line.ClosestPoint(p, true); d[i] = line.ClosestPoint(p, true).DistanceToSquared(p); //line.From.DistanceToSquared(p) + line.To.DistanceToSquared(p); } else { d[i] = 99999; } eid[i] = i; } Array.Sort(d, eid); closestEdges[counter++] = rmesh.TopologyEdges.GetTopologyVertices(eid[0]); } for (int i = 0; i < fixPt.Count; i++) { mesh_.Vertices.Add(fixPt[i]); mesh_.Faces.AddFace(rmesh.Vertices.Count + i, closestEdges[i].I, closestEdges[i].J); } rmesh = mesh_; } rmesh.UnifyNormals(); rmesh.RebuildNormals(); // rmesh.UnifyNormals(); DA.SetData(0, rmesh); }
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); }