Introducing TriRemesh - high quality triangular and hexagonal remeshing and shrink wrapping

Thanks @Anders,
I was forgetting about this way with NodeInCode. I’ll still work on exposing the remeshing methods directly too, as I think there are some options in there that didn’t make sense to have on the component, but might be useful in a script, such as separating the different topology update steps from the vertex smoothing and projection steps.

@mdesign
For your point 1. - yes curves set as features should always be preserved. Just set Sharp=True.
About point 2. - Combining this remeshing with isosurfacing is something I am looking at for future versions. You can currently use some other isosurfacing tool such as Dendro and pass the result to TriRemesh, but I think combining these steps into one script could potentially make it faster, as the remeshing could pull to the distance field directly.

@eghbalpourf - There’s no need to include the naked vertices as feature inputs - boundaries of open meshes are always treated as features.
To make curves on a flat surface features, the input mesh needs edges on these curves


triremesh_internalcurve.gh (7.3 KB)

This and the issue of inserting internal vertices is also covered in this other reply further up this thread.

4 Likes

thanks @DanielPiker

Thanks for your answer. I`m not sure If I understood you well. Has TriRemesh distance option in it?

No, there is not currently a distance option.
Right now you can use Dendro to do the offset, then remesh that.


offsetremesh.gh (147.0 KB)

1 Like

It looks very nice. Thanks a lot for showing me that. This is exactly what I wanted to achieve. I hope that in future there will be a tool to do this without GH (pure Rhino command) to have the possibility of doing that on very complex meshes (high poly models from Zbrush). After that, it will be possible to remove MeshMixer from hard drive :wink: I will try higher poly count also on GH maybe it will work.

I used that kind of hollowing on my sculpt below:

This is quite easy example to hollow but I have also much more complicated with big sizes. But it saves a lot of money.

Edit: I’ve frozen GH on the first try :slight_smile: 40MB mesh. MeshMixer does it during about 10-20 minutes with reasonable quality. I would like to replace it with Rhino (I`m not saying about that lion but mor complicated example - not posted here). MeshMixer is one leg dead :wink:

Edit2: I’ve left Dendro alone and only inner calculation and it`s almost ok.

3 Likes

Hello,

I got a task where triremesh could help me produce good quality meshes but I struggle with at least one part of the process.

In short: I am trying to fill gaps between two meshes and have one mesh without any naked vertices inside.

This file is just an example, my geometries will vary a lot.

GH File: Triremesh test.gh (1.5 MB)

  1. Starting two meshes

  2. To connect meshes I used loft and then remeshed input.


    Result of a loft between meshes (remeshed)

  3. Because the polyline edge of the bottom part may have a different number of vertices than the edge of the upper, smaller mesh I tried to stitch meshes together with the use of script from that post:
    Join the vertices of two different meshes? - #11 by DanielPiker
    but I always have some naked vertices nonetheless.


    Stitched meshes and naked vertices marked in blue.

My goal is to have one good quality triremeshed mesh which I can then take to Blender and sculpt in it or use in Rhino to trim, offset, etc.

My problems:

a) even if I stitch meshes and align vertices I still have inner naked vertices/edges. If I would take mesh like that and sculpt in it I will have visible gaps.
b) preservation of vertex normals after stitching (it may be rendered afterward so bad vertex normals are a bit of a problem)
c) method of connecting meshes - I doubt that my method based on lofting edges and then turning surface into mesh is the most optimal one, but I couldn’t find any better solution (note that my meshes may not be planar). Do you have any suggestions for a better method to “patch” meshes?

1 Like

Hi @Czaja

Here’s a different way of joining between two meshes so the vertices match
connectmeshes.gh (30.2 KB)

It uses a script I wrote for bridging a mesh between loops of points with different counts.
I still need to expose a setting in the remeshing to let you choose when to allow splitting of feature edges. Without this it isn’t guaranteed there won’t ever be a mismatch between the parts being joined, but when the same target edge length is being used for both parts it should be unlikely.

There’s also a bit in the definition above showing how to use the Shell goal for if you want to join the meshes with tangent continuity. (I’m also working on a way of doing this sort of fairing within the remeshing part).

I’d be interested to hear more about your intended workflow, as it could help inform a better interface for these sorts of joining/patching tools.

9 Likes

Thank you. I especially liked what you did with the Shell goal in Kangaroo, this helps to blend two pieces very elegantly.

As you said, your C# component is working well if we have circular loops of points. Another case is when we want to connect only some edges together.

I tried my best to clearly present some use cases and what can go wrong. Let me know if it is not descriptive enough or there are some doubts.

Rhino file: triremesh use case 1.3dm (3.2 MB)


Screenshot is pretty huge, but the same is inside the Rhino file

2 Likes

Hi @Czaja
Thanks for taking the time to make these examples and descriptions - it makes sense and will be helpful for developing the next stage of these tools. I can see that a few different types of new edge joining and remeshing functions could be helpful here.

I struggle with remeshing this big and “ugly” Delaunay mesh - perhaps it is too ugly? Are there some rules of thumb one should follow at the moment?

Although I think I did a correct job with providing polyline segments as Features input I cant receive consistent results.

Is there a way to force some edges as welded or unwelded? What I expected to be continuous unwelded edge breaks into pieces in places that are not that different from each other. This broken white line was fully unwelded in my previous tests, where mesh input was just slightly different.

Probably you don’t need my test file to answer those questions, but I attach it just in case.
Sorry that it is big, but hey, it’s a real-life scenario :wink:

Triremesh - big mesh.gh (1.4 MB)

1 Like

Have you tired Unweld with 10 degrees?

1 Like

Hi @Czaja

I think the issue here is related to the gaps between the vertices of the input mesh and the input feature curves.

When the ‘Sharp’ option is set to True, the remeshing detects ‘creased’ edges where the angle between the normals of the adjacent faces is above a threshold and keeps them as features.

Low quality input triangulations might have relatively large angles between faces in places you don’t really want to be features though, like the region between the curves near the right of your second image.
You might also have parts which you do want to be features, yet which have quite small angles between faces, like the middle of the top ridge in that image.
So automatic detection of features from this sort of input won’t always work.

When ‘Sharp’ is set to False though, it does not do this automated feature detection based on face angles, and feature edges are only those close within a tolerance to the curves in the ‘Features’ input. I’ll look at ways of adding more control over this tolerance. It can get a bit tricky though if the gaps between the vertices you want to snap to the features are bigger than the lengths of the short edges.

Where is the input coming from?
I’m wondering if there might be a way to get the exact curves you want to input as features(or do your initial meshing so the gaps are smaller) to get around this tolerance issue.

1 Like

@Holo
Thanks, for the suggestion. That may work, but may also bring some unwanted results and I consider it more as a „post-process” solution. As I know exactly where I need unwelded edges I would rather like to point them out before remeshing. Also, I can imagine a scenario where I want some parts to be unwelded on the completely flat mesh so unwelding by angle would not work there.

Hi, @DanielPiker

Eh, those gaps, I will investigate how it could happen that they are there.

Input mesh is created by me… I have a couple millions of XYZ points as a representation of the terrain. Depends on the quality of the scan, point clouds can be noisy and also some not-important terrain features bring unwanted data.

I tried to interpolate some areas of the river bank and useless points in areas which I don’t mind to be flatter than in the reality.

After that, I used all points to create Delaunay mesh and then tried to triremesh it featuring some polylines (this should eventually help me to split the mesh into pieces, excluding the bottom of the water canal, canal banks, etc. But have good continuity between all parts).

I don’t like those very thin and sharp triangles I receive from Delaunay mesh and I imagine they might bring some problems. Maybe I should try different 3D meshing algorithms to start with?

Then try the add crease command in V7, it’s called just _Crease

You can try my TerrainMesh plugin if you like, but if you use points as input it should give about the same result as it is a delaunay mesher.

You can also try to reduceMesh the result a bit to get rid of small edges etc. (Reducemesh to 90% so you only remove 10% can be worth a go)

Just a little update with the last Rhino 7 Service Release Candidate - the issue with input of points as features is now fixed
image

Also, for the Geometry input, as well as Breps and Meshes, it will now accept direct input of SubDs, polylines, and planar NURBS curves.
Furthermore, MultiPipe also now accepts meshes as input, and will pipe the edges, or if the mesh has ngons (such as the Dual D output of TriRemesh) it will pipe the ngon boundaries.

15 Likes

Thanks for adding the point feature input, i was hoping for that, looks like it also works on edges of a mesh too…

@DanielPiker I’m not sure if this has been asked yet, but I am having a bit of trouble with the ngon mesh structure. When I decompose the mesh to do some kind of other operations (maybe some relaxation with kangaroo) then rebuild the mesh, I will get a triangulated mesh. Is there an easy way to understand the face groups that make up the original ngon mesh? In the end I would like the mesh edges of the ngon when I rebuild the mesh.

Thanks!

Hi @porterfield.aaron

The dual output uses the standard Rhino Ngon class, where they are stored as groupings of triangles.

You can get the ngon boundaries as polylines using the FaceBoundaries component, and if you want just the edges you can explode and remove duplicates.

Mesh ngons are preserved by Kangaroo if passed through the ‘Show’ component.

If you want other topological data about the ngons you can access it from these classes
https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_Collections_MeshNgonList.htm
https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_MeshNgon.htm

Does that help?

3 Likes

For user interface I did quite some work to make NGons usable from rhinocommon to grasshopper components, including polygon extraction to conversion back to ngon data structure, adjacency of vertex, edge and faces that are currently missing in standard Rhinocommon methods. For sure you can code them up, but there are some parts that will take some time to figure it out due to mapping between triangles and triangles groups. So you can use super nice Daniel Piker Remesh algorithm in combination with this tool-set.

To answer your question about converting polygons to mesh data structure without triangulation you can simply use NGon components - a) fromPolylines (equivalent to FaceBoundaries component) and b) toPolylines.

4 Likes

Just to clarify - that conversion also happens automatically without additional components.
The D output is already a Rhino Ngon mesh, and passing this to the standard Face Boundaries component gives you the polygons which are the boundaries of each Ngon.

2 Likes