Skip to content

Commit

Permalink
handled issue that would create non-manifold edges (or holes, w/ dmes…
Browse files Browse the repository at this point in the history
…h3) when merging back in a remeshed sub-region. See comments, it is a non-trivial problem, difficult to detect more efficiently.
  • Loading branch information
rms80 committed Feb 7, 2017
1 parent f9d39e8 commit 4c9b4bf
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 5 deletions.
14 changes: 12 additions & 2 deletions mesh/MeshEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,16 @@ public bool RemoveTriangles(int[] triangles, bool bRemoveIsolatedVerts)
// new_tris should be set to TriangleCount (ie it is not necessarily a map)
// For new_verts, if we used an existing bdry vtx instead, we set the value to -(existing_index+1),
// otherwise the value is new_index (+1 is to handle 0)
public void ReinsertSubmesh(DSubmesh3 sub, ref int[] new_tris, out IndexMap SubToNewV)
//
// Returns true if submesh successfully inserted, false if any triangles failed
// (which happens if triangle would result in non-manifold mesh)
public bool ReinsertSubmesh(DSubmesh3 sub, ref int[] new_tris, out IndexMap SubToNewV)
{
if (sub.BaseBorderV == null)
throw new Exception("MeshEditor.ReinsertSubmesh: Submesh does not have required boundary info. Call ComputeBoundaryInfo()!");

DMesh3 submesh = sub.SubMesh;
bool bAllOK = true;

IndexFlagSet done_v = new IndexFlagSet(submesh.MaxVertexID, submesh.TriangleCount/2);
SubToNewV = new IndexMap(submesh.MaxVertexID, submesh.VertexCount);
Expand Down Expand Up @@ -217,12 +221,18 @@ public void ReinsertSubmesh(DSubmesh3 sub, ref int[] new_tris, out IndexMap SubT
new_t[j] = new_v;
}

Debug.Assert(Mesh.FindTriangle(new_t.a, new_t.b, new_t.c) == DMesh3.InvalidID);

int new_tid = Mesh.AppendTriangle(new_t, gid);
Debug.Assert(new_tid != DMesh3.InvalidID && new_tid != DMesh3.NonManifoldID);
if ( ! Mesh.IsTriangle(new_tid) )
bAllOK = false;

if (new_tris != null)
new_tris[nti++] = new_tid;
}


return bAllOK;
}


Expand Down
66 changes: 63 additions & 3 deletions mesh/RegionRemesher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;


namespace g3
Expand All @@ -15,7 +16,6 @@ public class RegionRemesher : Remesher

int[] cur_base_tris;


public RegionRemesher(DMesh3 mesh, int[] regionTris)
{
BaseMesh = mesh;
Expand All @@ -34,17 +34,77 @@ public RegionRemesher(DMesh3 mesh, int[] regionTris)



public void BackPropropagate()
// After remeshing we may create an internal edge between two boundary vertices [a,b].
// Those vertices will be merged with vertices c and d in the base mesh. If the edge
// [c,d] already exists in the base mesh, then after the merge we would have at least
// 3 triangles at this edge. Dang.
//
// A common example is a 'fin' triangle that would duplicate a
// 'fin' on the border of the base mesh after removing the submesh, but this situation can
// arise anywhere (eg think about one-triangle-wide strips).
//
// This is very hard to remove, but we can at least avoid creating non-manifold edges (which
// with the current DMesh3 will be prevented, hence leaving a hole) by splitting the
// internal edge in the submesh (which presumably we were remeshing anyway, so changes are ok).
public void RepairPossibleNonManifoldEdges()
{
// [TODO] do we need to repeat this more than once? I don't think so...

// repair submesh
int NE = Region.SubMesh.MaxEdgeID;
List<int> split_edges = new List<int>();
for ( int eid = 0; eid < NE; ++eid ) {
if (Region.SubMesh.IsEdge(eid) == false)
continue;
if (Region.SubMesh.edge_is_boundary(eid))
continue;
Index2i edgev = Region.SubMesh.GetEdgeV(eid);
if (Region.SubMesh.vertex_is_boundary(edgev.a) && Region.SubMesh.vertex_is_boundary(edgev.b)) {
// ok, we have an internal edge where both verts are on the boundary
// now check if it is an edge in the base mesh
int base_a = Region.SubToBaseV[edgev.a];
int base_b = Region.SubToBaseV[edgev.b];
Debug.Assert(Region.BaseMesh.IsVertex(base_a) && Region.BaseMesh.IsVertex(base_b));
int base_eid = Region.BaseMesh.FindEdge(base_a, base_b);
if ( base_eid != DMesh3.InvalidID )
split_edges.Add(eid);
}
}

// split any problem edges we found and repeat this loop
for ( int i = 0; i < split_edges.Count; ++i ) {
DMesh3.EdgeSplitInfo split_info;
Region.SubMesh.SplitEdge(split_edges[i], out split_info);
}
}



// Remove the original submesh region and merge in the remeshed version.
// You can call this multiple times as the base-triangle-set is updated.
//
// By default, we allow the submesh to be modified to prevent creation of
// non-manifold edges. You can disable this, however then some of the submesh
// triangles may be discarded.
//
// Returns false if there were errors in insertion, ie if some triangles
// failed to insert. Does not revert changes that were successful.
public bool BackPropropagate(bool bAllowSubmeshRepairs = true)
{
if (bAllowSubmeshRepairs)
RepairPossibleNonManifoldEdges();

// remove existing submesh triangles
MeshEditor editor = new MeshEditor(BaseMesh);
editor.RemoveTriangles(cur_base_tris, true);

// insert new submesh
int[] new_tris = new int[Region.SubMesh.TriangleCount];
IndexMap mapV;
editor.ReinsertSubmesh(Region, ref new_tris, out mapV);
bool bOK = editor.ReinsertSubmesh(Region, ref new_tris, out mapV);
cur_base_tris = new_tris;

return bOK;
}


Expand Down

0 comments on commit 4c9b4bf

Please sign in to comment.