SubD Edge & Vertex Tags (Creasing Programmatically)

Hi All, @stevebaer,

I am unwelding specific mesh edges with Python in a GH component to achieve creased SubD edges. SubD conversion is done with GH’s Subd from Mesh component. The mesh has Ngons with 5 and 6 vertices. UnweldEdge() destroys the Ngons. I am trying to store the Ngons and add them again after UnweldEdge(). This results in an invalid mesh and SubD from Mesh reverts to triangulating the Ngon faces. Mesh edges look ok though. With the original mesh, Subd from Mesh respects the Ngon faces (DEBUG output). How can I keep the Ngon intact while unwelding the edges?

Any other way to crease edges programmatically? As far as I understood from @dalelear the relevant methods for this are not yet exposed in rhcommon:

Edit: I extracted the relevant part of the geometry. It is internalized in the below GH file.

Any help is highly appreciated.
Thanks - S

1075_210602_RFD-CustomCreaseTest_SO.gh (16.1 KB)

def ngon_tag(mesh, indices):
    ngs = []
    for ng in mesh.Ngons:
        if ng.BoundaryVertexCount > 4:
            ngs.append(ng)
    # After UnweldEdge Ngons are gone
    res = mesh.UnweldEdge(indices, True)
    # AddNgons recreates Ngons but results in an invalid mesh and subsequently 
    # GH SubD from Mesh component triangulates Ngons with more than 4 vertices.
    mesh.Ngons.AddNgons(ngs)
    return mesh

Subd from Mesh with orignal mesh, Ngons respected:

Subd from Mesh after above Python code, Ngons triangulated, creases as intended:

Creasing edges is done by setting EdgeTag information. See
https://developer.rhino3d.com/api/RhinoCommon/html/P_Rhino_Geometry_SubDEdge_Tag.htm

There is also a SetEdgeTags function on the SubDEdgeList that is available in Rhino 7.7. This function is the preferred approach to setting creases for a set of edges.

1 Like

Hi @stevebaer, @DavidRutten

Thanks for adding SetEdgeTags to rhcommon. The C# component below uses it. Creasing decisions are based on points at the control polygon edges middle point (point at middle → edge is creased).
1075_210602_RFD-SubdEdgeTagWSearch_SO.gh (11.5 KB)


Some issues persist that I cannot resolve.

Issue 1
The SubdDEdges component generates an Object reference not set to an instance of an object error. I suspect this is caused by caching: When I copied the C# component in another definition and connected the inputs, SubDEdges worked. (Edit: ) Any upstream change before the C# component brings back the error. Output of the C# component superficially looks good. I tried calling ClearEvaluationCache and UpdateAllTagsAndSectorCoefficients in all possible combinations. Still getting the same error.

Issue 2
After baking the output of the C# component, we get weird shading behavior. Arctic mode is extremely slow and artifacts show on the SubD. This does not happen if we bake the SubD before the C# component. We have seen this before with modeled SubDs, but it was resolved by a recent update.

Issue 3
In Python components SetEdgeTags results in the Multiple targets could match error... . Also, SetEdgeTags is undocumented?

This function was added to Rhino 7.7 which is still not the official release until next week. Once we release 7.7, we will update the RhinoCommon API docs.

1 Like

I forgot I am using the RC updates. Thanks for the reminder.

Just changed my post above to sum up everything regarding EdgeTags.

Silvano, that’s a nice way with your script!

@stevebaer this would be a useful command …

1 Like

@stevebaer
Is there an equivalent method to SetEdgeTags() for SubD.Vertices in rhinocommon?

I have to crease some vertices, but not all of them, around an open edge loop. Please see the following sketch. Vertices to be creased are encircled in red.

The following results in an invalid SubD. I guess, as with the EdgeTags, this needs an implementation from your end to call the correct C++ methods.

    // Crease vertices
    SubDVertex sv = S.Vertices.First;
    while (sv != null)
    {
      sv.Tag = SubDVertexTag.Corner;
      sv = sv.Next;
    }

Please see the following test file:
CreaseVertex.gh (8.6 KB)

Thanks

@stevebaer I was able to solve the invalid SubD with the below. Is this as it is supposed to be done?

S is a SubD object.

// Crease vertices
SubDVertex sv = S.Vertices.First;
while (sv != null)
{
    sv.Tag = SubDVertexTag.Corner;
    sv = sv.Next;
}
// Fixes invalid output caused by sv.Tag = SubDVertexTag.Corner from above
S.ClearEvaluationCache();
S.UpdateAllTagsAndSectorCoefficients();

Amazing! I have been looking for this solution for a while! I added having specific points as corners.
CreaseVertex.gh (19.4 KB)

3 Likes

thanks for your code @lasathrs, please is there a way to analyse the closest subD vertex or add tolerance but within the code? sometimes it doesn’t detect some PC points? thank you!

hi @lasathrs @silvano in this example the First SubD make Inset but the Corner Point in your Script doesn’t work to result SubD


is there solution for it?
Crease Corner.gh (22.7 KB)

I updated the little script to include tolerance, I tested it and it works for the one point but you might need to adjust your SubD a little
Crease Corner_LS.gh (21.7 KB)

1 Like

hi @lasathrs Thanks’ ;; @Mahdiyar
i Think for Best Result To CreaseSubd Need EdgeTag and VertexTag together
i Try it But Not results Yet

Crease Corner_LS-Rev 2.gh (23.2 KB)

private void RunScript(SubD S, List<Point3d> PC, double T, string EdgeTag, ref object SO, ref object B)
  {
    SubDVertex sv = S.Vertices.First;
    var eg = S.Edges.First();
    for(int i = 0; i < S.Vertices.Count; i++)
    {
      if(i != 0)
      {
        sv = sv.Next;
      }
      if(PC.Exists(x => sv.ControlNetPoint.DistanceTo(x) < T))
      {
        sv.Tag = SubDVertexTag.Corner;
        eg.Tag = SubDEdgeTag.Crease;
      }
    }
    S.ClearEvaluationCache();
    S.UpdateAllTagsAndSectorCoefficients();

    SO = S;
    B = eg.GetType();}

in fact what’s the entrance EdgeTag?
have you any Suggestions?

1 Like