Dynamic remeshing - now with feature preservation, curvature adaptivity, and minimal surfaces

This will be incorporated into future releases of Kangaroo, but because it is so much fun to play with (not to mention useful!), I was excited to share this as a standalone component right now.

This is a tool for remeshing, as I first wrote about and demonstrated here.

However, since those first videos over a year ago, this has been improved upon and developed a lot. 

One of the most significant changes under the hood is that it now uses the custom half-edge mesh class Plankton developed as an open-source collaboration by myself and Will Pearson (to whom I owe great thanks for all his fantastic work on this). Big thanks also to Giulio Piacentino for sharing his great work on Turtle, and to Dave Stasiuk, Mathias Gmachl, Harri Lewis, Jonathan Rabagliati and Richard Maddock for helpful mesh discussions.

High quality triangular meshes have many applications, including physical simulation and analysis.

Since I shared some examples of remeshing scripts here, I have also added a few more features in response to discussions and requests:

Feature preservation

This allows the user to set curves and points to be preserved during the remeshing. These can be boundaries or internal curves, and can be useful for keeping sharp creases, or separate regions. (One of the major applications of this tool is creating high quality meshes for input into analysis programs.)

These features can now even be moved while the remeshing is running, and the mesh will stay attached.

Curvature Adaptivity

When a mesh contains features with tighter curvature, smaller edge lengths are needed to faithfully represent the geometry. However, applying these reduced mesh lengths across the whole surface, even in flat areas where they are not needed can be impractical, and slow everything down. A solution is to refine the mesh according to local curvature.

'Fertility' model from AIM shape repository, remeshed with curvature adaptivity. Here the edge flipping option is also set to valence based, which causes the mesh to become anisotropic in the direction of curvature.

Minimal surfaces

Relaxation based purely on 1d elements will not give accurate minimal surfaces, we need to use proper 2d elements.

However, when relaxing meshes to produce minimal surfaces, generating a high quality initial mesh can be problematic and tedious. Uneven meshing can cause the relaxation to fail or give incorrect results, especially when the relaxed geometry changes significantly from the input, causing the triangle quality to degrade even further.
By continuously updating the connectivity of the mesh to maintain even sized and nearly equilateral triangles, even very large changes to the boundaries become possible, and the surface still minimizes mean curvature.

This allows exploration of sculptural forms in a more dynamic and flexible way than I think has ever been possible before (seriously - try it out, I think you'll enjoy it).

Surfaces may 'pop' if the boundaries are moved suddenly or too far apart - as sometimes no minimal surface solution exists with the given boundary conditions.

Any plugin claiming to produce minimal surfaces which lets you move the end rings of a catenoid arbitrarily far apart and still gives a tubular solution is lying! The only proper behaviour in this case is to collapse into 2 flat disks. (As it is currently, the disks will remain connected by an infinitely thin strand, as I have not yet implemented anything to allow genus change, but maybe in the future.)

Here is the component and a basic example file. Feel free to ask any questions about its use, report bugs, or request changes or additions. This is still a work in progress.

MeshMachine.gha

Plankton.gha

Plankton.dll

Remesh_new_examples.gh

To install, unzip and place the dll and 2 gha files in your Grasshopper libraries folder (replacing any previous versions of these you may have installed - these are more recent than other releases). Make sure they are all unblocked, and restart Rhino.

  • Christian Schmidts

    Outstanding work! Unfortunately the "MeshMachine" can't be downloaded neighter by left nor right click. Seems like somethings get blocked.. 

  • Nick Tyrer

    This is a game changer! Love the curvature adaptivity.

  • Daniel Piker

    Thanks, I've updated the files now, hopefully that works

  • nick belomatis

    Object: MeshMachineComponent (level 1)
    {
    Exception has been thrown by the target of an invocation.
    TargetInvocationException
    }

    Object: MeshMachineComponent (level 2)
    {
    Could not load file or assembly 'Plankton, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
    FileNotFoundException
    }

  • Christian Schmidts

    Thank you - half edge meshes really rock :)

    I wanted to ask if the version with interpolation between multiple target lengths will be also incorporated into kangaroo? Hope so because it is really perfect for making gradual changes in the tessellation of a structures.

    I just saw you posted a version without a timer in the original thread. Would it be possible to post something similar for the interpolation between multiple target lengths example?

    Because I would like to incorporate it in a automated generation process.     

  • shima sn

    This is really awesome!

    Can you share the grasshopper file that you are using in the first video?

    Thanks

  • I_M_F [Iker Mugarra Flores]

    it feels like it is Christmas! great stuff, super exited....

    Thanks for sharing, fantastic research Daniel!!!!!!!!

    best 

    Iker

  • Daniel Piker

    Hi Christian,

    Yes, I'll add a version with the interpolated edge lengths - Maybe as another component, as I think this one already has a lot of inputs.

    One question I had here for users is about useful ways to control these edge lengths. Is interpolating between values given at a few sample points a good way to do it?

    Another option might be to use mesh colours - so you could paint on regions of density using UTO's MeshPaint3d.

    and yes - I'll do a timer free version too. I'm also working on a dedicated timer free version of the main Kangaroo component that keeps all the iteration internal and outputs only once final equilibrium is reached (As this is no longer the 'live' interactive physics as usual, but it's not really 'dead' I'm thinking maybe zombie kangaroo for the name!)

  • Daniel Piker

    Shima - The file used in the first video is the bottom group in the example definition. Just bake the curves into Rhino and reference them back in, then you can move them while it is running.

  • shima sn

    Thanks Daniel, well the problem that I'm having is that the grasshopper can't load the MeshMachineComponent! I downloaded the above file and copied in my library, do you have an idea why it is not loading? It also doesn't recognize the PlanktonMesh component!

  • David Stasiuk

    So awesome! 

  • Daniel Piker

    Has anyone successfully loaded this from the files above? I'm trying to figure out what could have gone wrong here, and it would help to know if it is broken for all or just some of you.

  • Maurizio Barberio

    Amazing job!

  • ng5 Alex

    Amazing.!

    all working ok with gh 09.0070 and the files you provided

  • Daniel Piker

    Thanks ng5.

    Anyone who it is not loading for please double check - all 3 files (Plankton.gha, Plankton.dll, and MeshMachine.gha) are in the libraries folder, and each one has been checked to see it is unblocked. The version of the Plankton libraries posted above is a special build, and it will not work with the 0.3.0 release found on the Plankton group page. Also fully close Rhino and re-open.

    If it is still not loading please let me know.

  • Christian Schmidts

    Hello Daniel,

    also working for me on 0.9.0075

    Great news and a bunch of good ideas. I would definitely vote for controlling the edge lengths with vertex colors. It is a little bit more complicated but you can control them much preciser. You don't even have to use uto's mesh paint categorically - with components like mesh spray or mesh or mesh blur you could really create well defined transitions.

    And you can also quite easily color a mesh according to the distance to some points if you want it that way..

    A "jumping dead" kangaroo would be great in that sense that you could integrate it tighter in other processes. Could this also have a slider input (from 0 to 1) where you can iterate throught the steps like on a kind of timeline?

  • Esteban Pacheco

    Not Working in here!!!

  • Daniel Piker

    Hi Esteban, I'll need a bit more info than that to be able to help!
  • Esteban Pacheco

    Hey Daniel! First Many Thanks for sharing your Awesome Plugins...

    I did all As descripted:

    1) copy all the above posted files to the libraries file, overwriting the old ones

    2) I have checked if they're blocked (by opening the attributes tabs, and checking if they can be written)

    I still have the problem that Meshmachine cannot load, because Plankton.dll is ALSO unable to load...

    Im running in the last version of grasshopper...

    i've tried this so far:

    i copied the plankton.dll from Kangaroo in (overwriting the One ABOVE) and it runs, BUT the Kangaroo doesnt want to Jump :)

    many thanks for your answer

  • panhao

    Great job.It works well.But there are two Plankton.dll.The old one is from Kangaroo 0096.Can I delete the old one?

  • Dragos Naicu

    Amazing work, Daniel! 

  • nardo chai

    Fantastic!Thank you. Thank you for letting me know so many things.

  • Nick Tyrer

    I agree mesh colour would be a great control. So much flexibility. 

  • Vicente Soler

    More than making the components work without a timer (you can already do this Kangaroo by increasing the subiterations and inputting a true and a false value to the start input. You can also do it with the remesher using a list of true, false, false, false... values but has the added lag of solveinstance on every iteration) it would be great if you could have parallel simulations running in the same component.

    In the case of the remesher, if you connect a list of objects it will have a different simulation for each object (right now you can join a list of meshes into a single one but its not the same, it might screw up the object order after disjoining them and it's slower and so on).

    In the case of Kangaroo, one simulation per branch of forces and anchor points. The tricky part would be the geometry input. Maybe if you have two simulations, all branches of geometry starting with {0;*} will be mapped to the first simulation, all starting with {1;*} mapped to the second and so on.

  • Robert Vier

    GREAT tool!

    love the zombie physics as well

  • Duncan W

    Daniel, I'm only beginning to venture into the possibilities Kangaroo allows, yet I already feel an urge to join the choir of people who express their gratitude. Grasshopper itself is already super exciting. The videos you post are even more shocking. I'll wait for the future stable release as I need to understand the Kangaroo basics first, but I already know for which projects of mine I will want to use these new features and I totally can't wait.

    Thank you!

  • Nick Tyrer

    Daniel, would you be able to tell me a little more about the 'flip' input. valence or angle based. 

    Does the valence option prioritise keeping the valence variation to a minimum?

    Anything like described here: http://www.grasshopper3d.com/profiles/blogs/mesh-optimization

  • Daniel Piker

    Thanks everyone for the encouragement!

    Panhao - yes, this Plankton dll can replace the old one from Kangaroo 0096

    Vicente - I think making a non-timer version should also automatically solve the issue of allowing different meshes on different data branches, because all iterations on one mesh item would be happening within a single solveinstance.

    It is a bit more complex with the non-timer Kangaroo, because I want to also allow people to use forces which change their parameters from one iteration to the next (such as hinges with a rest angle which varies over the course of the simulation).

    Nick - in both cases the flipping is based on the 4 vertices of a pair of triangles:

    The angle based option decides whether to flip each internal edge depending on the sum of the marked angles (choosing the one which gives the smaller value).

    The valence based option chooses whether to flip the edge depending on the total valence error over these 4 vertices.

    The valence error is how much each valence differs from the ideal (6 for internal vertices, and 4 for boundary vertices). So in the picture above the left version has valences of 5,7,6,7 giving a total error of 1+1+0+1=3, while the right version is better with 6,6,7,6 giving 0+0+1+0=1

  • shalom buberman

    Hi Daniel,

    I installed the files, replacing the old ones and got a loading errors message:

    Object: MeshMachineComponent (level 1)
    {
    Exception has been thrown by the target of an invocation.
    TargetInvocationException
    }

    Object: MeshMachineComponent (level 2)
    {
    Could not load file or assembly 'Plankton, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
    FileNotFoundException
    }

    how can I fix it?

    Thanx!

  • Nick Tyrer

    Thanks for explanation Daniel, that makes sense, i was playing around creating a mesh that rapidly changed from huge faces to tiny faces, and inevitably i was producing faces with very high valence. I was trying both options with similar results, but obviously thats just an issue with high contrast face size.

  • Ioanna Symeonidou

    Hello Daniel !

    Great tool, thanks for sharing, it works perfect !!! I am playing with it the whole day.

    Just one question. Is the mesh machine acting as a particle-spring system ? Could we set the restlength and stiffness here? Or are those parameters somehow included in the "pull" ?

    It seems that if we set pull to 0 we obtain something like a minimal surface, similar to what we get with Kangaroo physics if set spring length is 0. Is that right ?

    FixC or FixV looks like setting the anchorpoints. Are these two equivalent methods for dynamic relaxation? 

    Does it make sense to use a combination of the two, remeshing first and then feeding the new mesh into Kangaroo physics?

    It works great and i experimented with minimal surfaces, using the fourth one of your examples and moving the two circles afterwards.But the moment I tried to change the length on the slider it throws an exception

    Problem is, that even if I go one step back, it will not work and I would need to extract new boundaries from the initial surface, if I use the existing ones, as they are already moved, they are not attached on the surface, and it will create a mesh without holes.

    I tried the same example several times. Sometimes it works (as in the first pic) sometimes not, and it starts to peel off from the corners towards the center before it throws an exception. Any suggestions?

    I just want to understand how to avoid this problem from happening, cause it does NOT happen all the times.

    If it does happen, some seconds before it throws an exception it starts to peel like this, from the corners inwards:

    As I did the same experiment many times I noticed that the failure does not relate to the value in length... but to something else that I cannot figure out. It only occurs when I change the value in the slider, but NOT always

    Thanks in advance,

    ioanna

  • loc nguyen

    Hi all,

    I got the same trouble as shalom buberman. As I've just started in grasshopper so have no clue to solve this, really need your advises.

    Here is the error: 

    Object: MeshMachineComponent (level 1)
    {
    Exception has been thrown by the target of an invocation.
    TargetInvocationException
    }

    Object: MeshMachineComponent (level 2)
    {
    Could not load file or assembly 'Plankton, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
    FileNotFoundException
    }

    Thanks and regards!

    Loc.

  • Daniel Piker

    For those having loading errors, please double check that all the .dll and .gha files are unblocked.

    Hi Ioanna, I'll try and answer your questions-

    -It is working in a similar way to dynamic relaxation of spring networks in the main Kangaroo engine, but not exactly the same. I've not included any momentum effects in MeshMachine, and the forces come not from springs, but from Laplacian smoothing (There are also 3 different types of smoothing included - tangential only, uniform weighted, and cotan weighted. The latter allows more accurate minimal surface generation than with springs. I'm planning to add more user control over which combinations of these are used, but also want to keep the interface simple.)

    In later versions of Kangaroo I do plan to make it possible to combine all the usual forces with the remeshing, but because vertices get added and removed, this involves changes in the way particles are indexed. In the meantime - yes it does make sense to use the remesher then perform further optimization in Kangaroo.

    -Your problem with the mesh peeling away from the corners might be fixed by including the corners as fixed vertices, and also splitting the fixed boundary curves at the corners (so the rectangle would be 4 line segments). I think what is happening is that boundary vertices near the corner are jumping from one side to the other, and separating the sides should prevent that from happening.

  • Ioanna Symeonidou

    Thank you Daniel !

    What you explain makes perfect sense. I am mainly interested in form-finding of tensile structures. So I suppose that using either remesher or springs will lead to good approximations of a membrane.

    One last clarification, in case I remesh and then otpimize in Kangaroo. If points are in an unstable condition during the remeshing, I would need to bake the geometry after remesher and feed it back to Kangaroo to perform other simulations, right ? Or is there a way to fix some state of the simulation and use it as output for further optimization?

    Thanks again and congrats for the great work you are doing ! Kangaroo rocks !

  • Daniel Piker

    yes - if you are remeshing and then want to optimize the shape further in Kangaroo, you need to stop the remeshing first, and bake or internalize the mesh.

  • Nick Tyrer

    Dr. Piker,

    I have a question about webbed toes.... They are not meant to be webbed, mesh machine is giving me them... What would you recommend? The edge of the form is a fixC curve, but the mesh grows past boundary.

  • Wieland Schmidt

    Hi Daniel,

    thanks a lot for this amazing tool!

    Is it possible that at each vertex six faces meet (like in the majority if cases) and not sometimes four, five or seven?

    Wieland

  • Nick Tyrer

    Daniel, Have you tried switching the 'flip' input to Valence? Instead of the default angle based remeshing.

    copied from previous comment by Daniel:

    The angle based option decides whether to flip each internal edge depending on the sum of the marked angles (choosing the one which gives the smaller value).

    The valence based option chooses whether to flip the edge depending on the total valence error over these 4 vertices.

    The valence error is how much each valence differs from the ideal (6 for internal vertices, and 4 for boundary vertices). So in the picture above the left version has valences of 5,7,6,7 giving a total error of 1+1+0+1=3, while the right version is better with 6,6,7,6 giving 0+0+1+0=1

  • Mathias Gmachl

    First of all a big thank you, Daniel!

    I think the Mesh Machine performs amazingly well. I have worked with it a lot over the last month and its been incredibly useful and reliable.

    Purely from a workflow perspective I wanted to make two suggestions to make it work even better (for me and hopefully also others).

    1) Option for an input/start mesh:

    The BREP input is great as you get the highest possible resolution in the target geometry, which is then converted to a mesh internally.

    It would be great to be able to input a optional starting mesh, too. This would protect us from potentially running out of memory at a reset (due to a combination of large geometry and small edge length setting), but also allow to further optimise an existing mesh (I often start from meshes, which I heavily subdivide to achieve smoothness, which can make the reset very slow).

    2) Dual support:

    You already mentioned in your email that it would be possible to re-mesh with a focus on the edge-lengths of the dual, while flipping edges in the triangular mesh.

    It would be great to have a such DUAL mode that also gives the options to output as a pmesh.

    Thanks, again!

  • Balázs Hegedus

    Hi Daniel,  

    Can you plaese help me with the installation. Actually I followed what is written here, I copied the 3 files into the libraries, but after restarting Grashopper I got erros messages as can seen ont aattached image...

    Thanks in advance!

  • Oliver Tessin

    Hi Daniel,

    is there a possibility to make this work for 3d "mesh", e.x. take "Populate 3D" Component and generate connections between like you do it here.

  • Daniel Piker

    Hi Oliver,
    Volumetric remeshing like you are talking about would involve a volumetric mesh data structure, containing definition of tetrahedra and the connections between them. The Plankton half-edge structure used in the script above for the triangle connectivity is for surfaces only.
    Appropriate data structures do exist, and we have talked about such a development, as tetrahedral meshes are useful for several things...
  • Oliver Tessin

    Hi Daniel,

    thanks for the quick reply. I searched the forum for what you mentioned at the end, but couldnt find the conversation you refered to. Could you drop the link?

    Basically... I would like to create a structure as effiecient as 2D Delaunay, so basically a 3D Delaunay. I tried with Proximity (not good as it fails to make connections) and Voronoi 3D (posted below). I am planning to create a structure like this with almost 50.000 edges and trying to find a better way to do it.

    Many thanks,

    Oliver

    I found a good reference for what I'm trying to achieve, I guess.

    http://raweb.inria.fr/rapportsactivite/RA2009/geometrica/uid16.html

  • Robert Vier

    Hi,

    I dont know if it is of any use - but a while ago I used the MiConvexHull to generate 3D delaunay meshes = tetrahedrons.

    here you are:

    https://www.dropbox.com/sh/738oqu01bjivkg5/AACHj6C6d-JK3THv9ACmb6Um...

    best

    Robert

  • Oliver Tessin

    Hi Robert,

    thanks for the quick reply. Your def requires "StarMath.dll" and "MIConvexHullPlugin.dll", which it seems I'm not able to find as public download.

    Many thanks for your help,

    Oliver

  • Robert Vier

    You cant see the subfolder on my dropbox?

    They're in there..

  • Oliver Tessin

    Works great. Many thanks!

  • Oliver Tessin

    Would it be possible to use Roberts 3D Delaunay  as a dynamic mesh which's density can be controlled?