// This function does local remeshing around a boundary loop within a fixed # of // rings, to try to 'massage' it into a cleaner shape/topology // [TODO] use geodesic distance instead of fixed # of rings? public static void cleanup_boundary(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop, double target_edge_len, int nRings = 3) { Debug.Assert(loop.IsBoundaryLoop()); MeshFaceSelection roi = new MeshFaceSelection(mesh); roi.SelectVertexOneRings(loop.Vertices); for (int i = 0; i < nRings; ++i) { roi.ExpandToOneRingNeighbours(); } roi.LocalOptimize(true, true); RegionRemesher r = new RegionRemesher(mesh, roi.ToArray()); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = target_edge_len; r.MaxEdgeLength = 2 * target_edge_len; r.EnableSmoothing = true; r.SmoothSpeedT = 0.1f; for (int k = 0; k < nRings * 3; ++k) { r.BasicRemeshPass(); } Debug.Assert(mesh.CheckValidity()); r.BackPropropagate(); }
// smooths embedded loop in mesh, by first smoothing edge loop and then // smoothing vertex neighbourhood // [TODO] geodesic nbrhoold instead of # of rings // [TODO] reprojection? public static void smooth_loop(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop, int nRings) { MeshFaceSelection roi_t = new MeshFaceSelection(mesh); roi_t.SelectVertexOneRings(loop.Vertices); for (int i = 0; i < nRings; ++i) { roi_t.ExpandToOneRingNeighbours(); } roi_t.LocalOptimize(true, true); MeshVertexSelection roi_v = new MeshVertexSelection(mesh); roi_v.SelectTriangleVertices(roi_t.ToArray()); roi_v.Deselect(loop.Vertices); MeshLoopSmooth loop_smooth = new MeshLoopSmooth(mesh, loop); loop_smooth.Rounds = 1; MeshIterativeSmooth mesh_smooth = new MeshIterativeSmooth(mesh, roi_v.ToArray(), true); mesh_smooth.Rounds = 1; for (int i = 0; i < 10; ++i) { loop_smooth.Smooth(); mesh_smooth.Smooth(); } }
public SimpleHoleFiller(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop) { Mesh = mesh; Loop = loop; NewVertex = NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID; NewTriangles = null; }
public MeshBoundaryLoops(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, bool bAutoCompute = true) { this.Mesh = mesh; if (bAutoCompute) { Compute(); } }
public MeshExtrusion(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop) { Mesh = mesh; Loop = loop; PositionF = (pos, normal, idx) => { return(pos + Vector3D.AxisY); }; }
public MeshLoopSmooth(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop) { Mesh = mesh; Loop = loop; SmoothedPostions = new Vector3D[Loop.Vertices.Length]; ProjectF = null; }
void Append_mesh() { if (Meshes == null || Meshes.Count == 0) { Meshes = new List <NGonsCore.geometry3Sharp.mesh.DMesh3>(); } cur_mesh = new NGonsCore.geometry3Sharp.mesh.DMesh3(MeshComponents.VertexNormals); if (ColorSourceF != null) { cur_mesh.EnableVertexColors(Colorf.White); } Meshes.Add(cur_mesh); }
// local mesh smooth applied to all vertices in N-rings around input list public static void smooth_region(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, IEnumerable <int> vertices, int nRings) { MeshFaceSelection roi_t = new MeshFaceSelection(mesh); roi_t.SelectVertexOneRings(vertices); for (int i = 0; i < nRings; ++i) { roi_t.ExpandToOneRingNeighbours(); } roi_t.LocalOptimize(true, true); MeshVertexSelection roi_v = new MeshVertexSelection(mesh); roi_v.SelectTriangleVertices(roi_t.ToArray()); MeshIterativeSmooth mesh_smooth = new MeshIterativeSmooth(mesh, roi_v.ToArray(), true); mesh_smooth.Alpha = 0.2f; mesh_smooth.Rounds = 10; mesh_smooth.Smooth(); }
public void MakeMesh(NGonsCore.geometry3Sharp.mesh.DMesh3 m) { int nV = vertices.Count; for (int i = 0; i < nV; ++i) { NewVertexInfo ni = new NewVertexInfo() { v = vertices[i] }; if (WantNormals) { ni.bHaveN = true; ni.n = normals[i]; } if (WantUVs) { ni.bHaveUV = true; ni.uv = uv[i]; } int vID = m.AppendVertex(ni); Util.gDevAssert(vID == i); } int nT = triangles.Count; if (WantGroups && groups != null && groups.Length == nT) { for (int i = 0; i < nT; ++i) { m.AppendTriangle(triangles[i], groups[i]); } } else { for (int i = 0; i < nT; ++i) { m.AppendTriangle(triangles[i]); } } }
// Modes: 0: centroids, 1: any vertex, 2: 2 vertices, 3: all vertices // ContainF should return true if 3D position is in set (eg inside box, etc) // If mode = 0, will be called with (centroid, tri_idx) // If mode = 1/2/3, will be called with (vtx_pos, vtx_idx) // AddF is called with triangle IDs that are in set public static void TrianglesContained(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, Func <Vector3D, int, bool> ContainF, Action <int> AddF, int nMode = 0) { BitArray inV = null; if (nMode != 0) { inV = new BitArray(mesh.MaxVertexID); foreach (int vid in mesh.VertexIndices()) { if (ContainF(mesh.GetVertex(vid), vid)) { inV[vid] = true; } } } foreach (int tid in mesh.TriangleIndices()) { Index3i tri = mesh.GetTriangle(tid); bool bIn = false; if (nMode == 0) { if (ContainF(mesh.GetTriCentroid(tid), tid)) { bIn = true; } } else { int countIn = (inV[tri.a] ? 1 : 0) + (inV[tri.b] ? 1 : 0) + (inV[tri.c] ? 1 : 0); bIn = (countIn >= nMode); } if (bIn) { AddF(tid); } } }
public MeshRegionBoundaryLoops(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] RegionTris, bool bAutoCompute = true) { this.Mesh = mesh; // make flag set for included triangles triangles = new IndexFlagSet(mesh.MaxTriangleID, RegionTris.Length); for (int i = 0; i < RegionTris.Length; ++i) { triangles[RegionTris[i]] = true; } // make flag set for included edges // NOTE: this currently processes non-boundary-edges twice. Could // avoid w/ another IndexFlagSet, but the check is inexpensive... edges = new IndexFlagSet(mesh.MaxEdgeID, RegionTris.Length); for (int i = 0; i < RegionTris.Length; ++i) { int tid = RegionTris[i]; Index3i te = Mesh.GetTriEdges(tid); for (int j = 0; j < 3; ++j) { int eid = te[j]; if (!edges.Contains(eid)) { Index2i et = mesh.GetEdgeT(eid); if (et.b == NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID || triangles[et.a] != triangles[et.b]) { edges.Add(eid); } } } } if (bAutoCompute) { Compute(); } }
public static void WriteDebugMeshAndMarkers(IMesh mesh, List <Vector3D> Markers, string sPath) { WriteOptions options = WriteOptions.Defaults; options.bWriteGroups = true; List <WriteMesh> meshes = new List <WriteMesh>() { new WriteMesh(mesh) }; double size = BoundsUtil.Bounds(mesh).Diagonal.Length * 0.01f; foreach (Vector3D v in Markers) { TrivialBox3Generator boxgen = new TrivialBox3Generator(); boxgen.Box = new Box3d(v, size * Vector3D.One); boxgen.Generate(); DMesh3 m = new DMesh3(); boxgen.MakeMesh(m); meshes.Add(new WriteMesh(m)); } StandardMeshWriter.WriteFile(sPath, meshes, options); }
public static ValidationStatus IsBoundaryLoop(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop) { int N = loop.Vertices.Length; for (int i = 0; i < N; ++i) { if (!mesh.Vertex_is_boundary(loop.Vertices[i])) { return(ValidationStatus.NotBoundaryVertex); } } for (int i = 0; i < N; ++i) { int a = loop.Vertices[i]; int b = loop.Vertices[(i + 1) % N]; int eid = mesh.FindEdge(a, b); if (eid == NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { return(ValidationStatus.VerticesNotConnectedByEdge); } if (mesh.IsBoundaryEdge(eid) == false) { return(ValidationStatus.NotBoundaryEdge); } Index2i ev = mesh.GetOrientedBoundaryEdgeV(eid); if (!(ev.a == a && ev.b == b)) { return(ValidationStatus.IncorrectLoopOrientation); } } return(ValidationStatus.Ok); }
public static ValidationStatus IsEdgeLoop(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop loop) { int N = loop.Vertices.Length; for (int i = 0; i < N; ++i) { if (!mesh.IsVertex(loop.Vertices[i])) { return(ValidationStatus.NotAVertex); } } for (int i = 0; i < N; ++i) { int a = loop.Vertices[i]; int b = loop.Vertices[(i + 1) % N]; int eid = mesh.FindEdge(a, b); if (eid == NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { return(ValidationStatus.VerticesNotConnectedByEdge); } } return(ValidationStatus.Ok); }
/// <summary> /// Cut mesh with plane. Assumption is that plane normal is Z value. /// </summary> public MeshPlaneCut(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, Vector3D origin, Vector3D normal) { Mesh = mesh; PlaneOrigin = origin; PlaneNormal = normal; }
public MeshLoopClosure(NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, EdgeLoop border_loop) { Mesh = mesh; InitialBorderLoop = border_loop; }