algorithmic modeling for Rhino
"Carve is a fast, robust constructive solid geometry library. (fork from https://code.google.com/p/carve/)"
"CarveSharp is a .NET wrapper for the fast and robust constructive solid geometry (CSG) library Carve. Using CarveSharp, you could easily pass triangular meshes and perform boolean operations on them (such as union, intersect, etc.). CarveSharp is targeted for .NET v4 and above (due to the use of parallel for loops for increased performance). It can be easily integrated into Unity by rewriting all Parallel.For loops as regular C# for loops (note that the performance may significantly decrease)."
CarveRhino and CarveGH are an adaptation of the two wonderful pieces of software described above, allowing the usage of the Carve library in Rhino and Grasshopper, respectively. At the moment, just the basic operation of Carve is exposed, and outputs a triangulated mesh. Although Carve supports N-gons, Rhino doesn't, so these are instead triangulated. Hopefully this will change in the future with N-gon support in Rhino. There seems to be a lot of functionality in Carve that is not being exploited, so hopefully this can provide a good enough starting point to have good, solid mesh booleans in Rhino.
The libs are provided as-is, with no guarantee of support for now, as I use them internally and do not intend to develop this into a shiny, polished plug-in. If there is enough interest, I can tidy up the code-base and upload it somewhere if someone more savvy than me wants to improve on it (and there is a LOT of room for that!).
CarveLibWrapper.dll - The actual wrapper for the Carve library.
CarveSharp.dll - The dotNET assembly which exposes Carve, using only basic types.
CarveRC.dll - CarveRhinoCommon, which provides basic conversion from Rhino types (Mesh) to Carve types.
CarveGH.gha - Grasshopper assembly which adds the 'Carve' component to Mesh -> Util.
CarveRhino.rhp - Rhino plug-in which adds the 'Carve' command to Rhino.
This is currently structured in this way to keep it modular and allow people to use any particular part of the wrapper, with or without RhinoCommon or GH, etc.
This would not have been possible without the work of Mehran Maghoumi who created the original CarveSharp wrapper (https://github.com/Maghoumi). I have basically just removed dependencies to OpenTK and CodeFullToolkit, slightly re-organized the code, exposed some more functionality, and provided interfaces to Rhino and GH.
UPDATE: Link to blog post is here.
The conversion between Rhino Mesh and Carve Mesh happens in CarveRC.dll. There are just two extension methods that do the conversion back and forth. They basically only take faces with 3 or 4 verts and ignore the rest. If you made extension methods for Rhino 6 meshes, you could probably see if N-gons work.
Is there documentation of Rhino 6 meshes with N-gons anywhere? I could update this relatively easily...
The new SDK is updated with the Ngons property.
Also, this is a total CITA party. Where's Matoosh?
I need to wait until my Rhino account is unlocked (???) so I can get the newest Rhino 6 version and try it out... Might be a bit of a faff to compile against both 5 and 6... or can I compile with RhinoCommon 6 and still use it with Rhino 5? Much confuse.
Yap, you need to compile for rhino 6 wip and rhino 5 separately because rhino 5 does not have ngons.
For now I am just using Rhino 6 Wip and can try to apply carve to ngons.
Also David Rutten does not want to implement rhino 6 wip meshes in grasshopper, so that you could open grasshopper definition on rhino 6 from rhino 5 and vice versa. But this results in issues that it is impossible internalize mesh with ngons. However they are very useful for adjacency and etc.
N-gons are the proverbial bee's knees, so having max support for them would be super helpful.
Try something like this:
CarveSharp.CarveMesh NgonsToCarveMesh(Mesh m)
double verts = new double[m.Vertices.Count * 3];
int facesizes = new int[m.Ngons.Count];
List<int> faces = new List<int>();
int j = 0;
for (int i = 0; i < m.Vertices.Count; ++i)
verts[j] = m.Vertices[i].X; ++j;
verts[j] = m.Vertices[i].Y; ++j;
verts[j] = m.Vertices[i].Z; ++j;
for (int i = 0; i < m.Ngons.Count; ++i)
MeshNgon mngon = m.Ngons.GetNgon(i);
facesizes[i] = mngon.BoundaryVertexCount;
for (int j = 0; j < mngon.BoundaryVertexCount; ++j)
CarveSharp.CarveMesh cm = new CarveSharp.CarveMesh();
cm.Vertices = verts;
cm.FaceIndices = faces.ToArray();
cm.FaceSizes = facesizes;
Going the other way should be similar, though I don't know if you need to define Mesh faces and then N-gons, or if you can just define N-gons right away and it'll take care of the Faces list for you... Haven't tried the Rhino 6 API... Not sure if you can just use the index operator on MeshNgon directly or you have to go mngon.Item[i] or whatever.
And then instead of
Rhino.Geometry.Mesh res = CarveRC.CarveOps.PerformCSG(...)
CarveSharp.CarveMesh res = CarveSharp.PerformCSG(CarveMeshA, CarveMeshB, CarveSharp.CSGOperations.Union);
Mesh m = res.ToRhinoMesh();
or your own CarveMesh-to-RhinoMesh function which preserves N-gons.
Actually it will still triangulate it in the core Carve function... it's hard-coded at the moment to enforce triangulated output so you can easily convert it to a Rhino Mesh... I'll try to think of a way around this, maybe just a static flag to turn that on or off...
Thanks for sharing! It'd be great if you also made this a blog post, so it doesn't get lost in the discussion shuffle.
@David, I'm a bit of a noob... Do you mean create a new group for it on here?
Nevermind, Anders sorted me out :) Link to blog post updated.
Might be nice to post it to Mateusz's Milkbox group - good place for it to not get lost. Nice add! http://www.grasshopper3d.com/group/milkbox