Skip to content

Commit

Permalink
Remesh and Subdivide: update notFlippable edges (#1345)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fedr authored Jun 20, 2023
1 parent 25904f1 commit 4c2b450
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 13 deletions.
13 changes: 7 additions & 6 deletions source/MRMesh/MRMeshDecimate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,18 +829,19 @@ bool remesh( MR::Mesh& mesh, const RemeshSettings & settings )
decs.progressCallback = subprogress( settings.progressCallback, 0.5f, 0.95f );
decs.preCollapse = settings.preCollapse;
decimateMesh( mesh, decs );
if ( settings.notFlippable )
mesh.topology.excludeLoneEdges( *settings.notFlippable );
if ( !reportProgress( settings.progressCallback, 0.95f ) )
return false;

if ( settings.finalRelaxIters > 0 )
{
VertBitSet innerVerts;
// even if region is not given, we need to exclude mesh boundary from relaxation
VertBitSet innerVerts = getInnerVerts( mesh.topology, settings.region );
if ( settings.notFlippable )
innerVerts -= getIncidentVerts( mesh.topology, *settings.notFlippable );
MeshRelaxParams rp;
if ( settings.region )
{
innerVerts = getInnerVerts( mesh.topology, *settings.region );
rp.region = &innerVerts;
}
rp.region = &innerVerts;
rp.iterations = settings.finalRelaxIters;
relax( mesh, rp, subprogress( settings.progressCallback, 0.95f, 1.0f ) );
}
Expand Down
5 changes: 3 additions & 2 deletions source/MRMesh/MRMeshDecimate.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ struct RemeshSettings
int finalRelaxIters = 0;
/// Region on mesh to be changed, it is updated during the operation
FaceBitSet * region = nullptr;
/// Edges specified by this bit-set will never be flipped
const UndirectedEdgeBitSet* notFlippable = nullptr;
/// Edges specified by this bit-set will never be flipped, but they can be split or eliminated during decimation
/// so it is updated during the operation; also the vertices incident to these edges are exluded from relaxation
UndirectedEdgeBitSet* notFlippable = nullptr;
/// whether to pack mesh at the end
bool packMesh = false;
/// this function is called each time edge (e) is split into (e1->e), but before the ring is made Delone
Expand Down
2 changes: 2 additions & 0 deletions source/MRMesh/MRMeshSubdivide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ int subdivideMesh( Mesh & mesh, const SubdivideSettings & settings )
settings.onVertCreated( newVertId );
if ( settings.onEdgeSplit )
settings.onEdgeSplit( e1, e );
if ( settings.notFlippable && settings.notFlippable->test( e.undirected() ) )
settings.notFlippable->autoResizeSet( e1.undirected() );
++splitsDone;
makeDeloneOriginRing( mesh, e, {
.maxDeviationAfterFlip = settings.maxDeviationAfterFlip,
Expand Down
4 changes: 2 additions & 2 deletions source/MRMesh/MRMeshSubdivide.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ struct SubdivideSettings
float maxAngleChangeAfterFlip = 10;
/// Region on mesh to be subdivided, it is updated during the operation
FaceBitSet * region = nullptr;
/// Edges specified by this bit-set will never be flipped
const UndirectedEdgeBitSet* notFlippable = nullptr;
/// Edges specified by this bit-set will never be flipped, but they can be split so it is updated during the operation
UndirectedEdgeBitSet* notFlippable = nullptr;
/// New vertices appeared during subdivision will be added here
VertBitSet * newVerts = nullptr;
/// If false do not touch border edges (cannot subdivide lone faces)\n
Expand Down
9 changes: 7 additions & 2 deletions source/MRMesh/MRRegionBoundary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ VertBitSet getIncidentVerts( const MeshTopology & topology, const FaceBitSet & f
return res;
}

VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & faces )
VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet * region )
{
MR_TIMER
VertBitSet res = topology.getValidVerts();
Expand All @@ -247,7 +247,7 @@ VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & face
for ( auto e : orgRing( topology, v ) )
{
auto f = topology.left( e );
if ( !f.valid() || !faces.test( f ) )
if ( !f.valid() || ( region && !region->test( f ) ) )
{
res.reset( v );
break;
Expand All @@ -257,6 +257,11 @@ VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & face
return res;
}

VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & region )
{
return getInnerVerts( topology, &region );
}

const VertBitSet & getIncidentVerts( const MeshTopology & topology, const FaceBitSet * faces, VertBitSet & store )
{
MR_TIMER
Expand Down
4 changes: 3 additions & 1 deletion source/MRMesh/MRRegionBoundary.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ namespace MR
// otherwise performs store = getIncidentVerts( topology, *faces ) and returns reference on store
[[nodiscard]] MRMESH_API const VertBitSet & getIncidentVerts( const MeshTopology & topology, const FaceBitSet * faces, VertBitSet & store );
// composes the set of all vertices not on the boundary of a hole and with all their adjacent faces in given set
[[nodiscard]] MRMESH_API VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & faces );
[[nodiscard]] MRMESH_API VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet * region );
// composes the set of all vertices not on the boundary of a hole and with all their adjacent faces in given set
[[nodiscard]] MRMESH_API VertBitSet getInnerVerts( const MeshTopology & topology, const FaceBitSet & region );
// composes the set of all boundary vertices for given region (or whole mesh if !region)
[[nodiscard]] MRMESH_API VertBitSet getBoundaryVerts( const MeshTopology & topology, const FaceBitSet * region = nullptr );

Expand Down

0 comments on commit 4c2b450

Please sign in to comment.