Skip to content

Commit bb6196c

Browse files
committed
add "set-id" to Fixed constrained vertices. then in Remesher, if two Fixed vertices have same set ID, we (optionally) allow that edge to be collapsed to midpoint. This allows refining embedded loops to some degree (although still limited as we still don't smooth fixed verts)
1 parent 40d3b5e commit bb6196c

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

mesh/MeshConstraints.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ public bool NoModifications {
4747
public struct VertexConstraint
4848
{
4949
public bool Fixed;
50+
public int FixedSetID; // in Remesher, we can allow two Fixed vertices with
51+
// same FixedSetID to be collapsed together
5052

51-
public VertexConstraint(bool isFixed)
53+
public VertexConstraint(bool isFixed, int setID = InvalidSetID)
5254
{
5355
Fixed = isFixed;
56+
FixedSetID = setID;
5457
}
5558

56-
static public readonly VertexConstraint Unconstrained = new VertexConstraint() { Fixed = false };
59+
public const int InvalidSetID = -1;
60+
static public readonly VertexConstraint Unconstrained = new VertexConstraint() { Fixed = false };
5761
}
5862

5963

mesh/Remesher.cs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public class Remesher {
1414
public bool EnableSplits = true;
1515
public bool EnableSmoothing = true;
1616

17-
1817
public double MinEdgeLength = 0.001f;
1918
public double MaxEdgeLength = 0.1f;
2019

@@ -25,6 +24,14 @@ public enum SmoothTypes {
2524
public SmoothTypes SmoothType = SmoothTypes.Uniform;
2625

2726

27+
// other options
28+
29+
// if true, then when two Fixed vertices have the same non-invalid SetID,
30+
// we treat them as not fixed and allow collapse
31+
public bool AllowCollapseFixedVertsWithSameSetID = true;
32+
33+
34+
2835
public Remesher(DMesh3 m) {
2936
mesh = m;
3037
}
@@ -97,25 +104,30 @@ ProcessResult ProcessEdge(int edgeID)
97104
Vector3d vB = mesh.GetVertex(b);
98105
double edge_len_sqr = (vA-vB).LengthSquared;
99106

100-
bool aFixed = vertex_is_fixed(a);
101-
bool bFixed = vertex_is_fixed(b);
102-
bool bothFixed = (aFixed && bFixed);
107+
// check if we should collapse, and also find which vertex we should collapse to,
108+
// in cases where we have constraints/etc
109+
int collapse_to = -1;
110+
bool bCanCollapse = EnableCollapses
111+
&& constraint.CanCollapse
112+
&& edge_len_sqr < MinEdgeLength*MinEdgeLength
113+
&& can_collapse(a, b, out collapse_to);
114+
103115

104116
// optimization: if edge cd exists, we cannot collapse or flip. look that up here?
105117
// funcs will do it internally...
106118
// (or maybe we can collapse if cd exists? edge-collapse doesn't check for it explicitly...)
107119

108120
// if edge length is too short, we want to collapse it
109121
bool bTriedCollapse = false;
110-
if ( EnableCollapses && constraint.CanCollapse && bothFixed == false && edge_len_sqr < MinEdgeLength*MinEdgeLength ) {
122+
if ( bCanCollapse ) {
111123

112124
int iKeep = b, iCollapse = a;
113125
Vector3d vNewPos = (vA + vB) * 0.5;
114126

115127
// if either vtx is fixed, collapse to that position
116-
if ( bFixed ) {
128+
if ( collapse_to == b ) {
117129
vNewPos = vB;
118-
} else if ( aFixed ) {
130+
} else if ( collapse_to == a ) {
119131
iKeep = a; iCollapse = b;
120132
vNewPos = vA;
121133
}
@@ -214,13 +226,46 @@ void update_constraints_after_split(int edgeID, int va, int vb, DMesh3.EdgeSplit
214226
// cannot do outside loop because then pair of fixed verts connected
215227
// by unconstrained edge will produce a new fixed vert, which is bad
216228
// (eg on minimal triangulation of capped cylinder)
217-
if (vertex_is_fixed(va) && vertex_is_fixed(vb))
229+
VertexConstraint ca = constraints.GetVertexConstraint(va);
230+
VertexConstraint cb = constraints.GetVertexConstraint(vb);
231+
if (ca.Fixed && cb.Fixed) {
232+
int nSetID = (ca.FixedSetID > 0 && ca.FixedSetID == cb.FixedSetID) ?
233+
ca.FixedSetID : VertexConstraint.InvalidSetID;
218234
constraints.SetOrUpdateVertexConstraint(splitInfo.vNew,
219-
new VertexConstraint(true));
235+
new VertexConstraint(true, nSetID));
236+
}
220237
}
221238
}
222239

223240

241+
bool can_collapse(int a, int b, out int collapse_to)
242+
{
243+
collapse_to = -1;
244+
if (constraints == null)
245+
return true;
246+
VertexConstraint ca = constraints.GetVertexConstraint(a);
247+
VertexConstraint cb = constraints.GetVertexConstraint(b);
248+
if (ca.Fixed == false && cb.Fixed == false)
249+
return true;
250+
if ( ca.Fixed == true && cb.Fixed == false ) {
251+
collapse_to = a;
252+
return true;
253+
}
254+
if ( cb.Fixed == true && ca.Fixed == false) {
255+
collapse_to = b;
256+
return true;
257+
}
258+
// if both fixed, and options allow, treat this edge as unconstrained (eg collapse to midpoint)
259+
// [RMS] tried picking a or b here, but something weird happens, where
260+
// eg cylinder cap will entirely erode away. Somehow edge lengths stay below threshold??
261+
if ( AllowCollapseFixedVertsWithSameSetID
262+
&& ca.FixedSetID >= 0
263+
&& ca.FixedSetID == cb.FixedSetID) {
264+
return true;
265+
}
266+
267+
return false;
268+
}
224269

225270

226271
bool vertex_is_fixed(int vid)
@@ -258,7 +303,7 @@ void FullProjectionPass()
258303
if (vertex_is_fixed(vID))
259304
continue;
260305
Vector3d curpos = mesh.GetVertex(vID);
261-
Vector3d projected = target.Project(curpos);
306+
Vector3d projected = target.Project(curpos, vID);
262307
mesh.SetVertex(vID, projected);
263308
}
264309
}

0 commit comments

Comments
 (0)