Color Mesh Faces (No Bleeding) - Best Practice?

Hi All,

I’m revisiting some old code for coloring mesh faces (without them bleeding into each other!), and feel like I might be missing something here. The basic approach I’ve been using is to:

  1. Unweld the mesh, or, make a new mesh and append the faces onto this.
  2. Color the face corners of this now unwelded mesh.

Now this approach works just fine.

But both unwelding and setting the colors are pretty heavy processes (at about 280 and 140 ms respetivley in this case). So I am looking to speed this up a bit, and wondering if there might be better/faster overall approaches that I am missing?

Leading me to: At least sitting setting the colors can be sped up by calling MeshVertexColorList.SetColor, however this only appears to set one corner on fully unwelded meshes (but is substantially faster than setting each corner individually):

While it works as expected on a welded mesh (but of course with colors bleeding across faces):

And yes, I do realize that writing a compiled C# component (or, eww, a C++ plugin), or threading etc. can speed things up. But I’m asking what I might be missing in terms of the base logics here, and perhaps, also pointing out a bug (i.e. MeshVertexColorList.SetColor) and/or features that might be missing in RhinoCommon.

Best,

Anders

Hi @AndersDeleuran,

i do use the unweld trick too. To set the colors faster i built them threaded and the thread writes to a preallocated list using indices. The colors can be set in one go using MeshVertexColorList.SetColors. It is faster than doing it one by one.

_
c.

3 Likes

Cheers Clement, setting the colors in one go is a really good idea.

I ended up going with a slightly different approach than the ones above (basically: make an empty mesh, iterate the input mesh faces and add the vertices of these faces to the empty mesh, while also adding the colors at this index, and finally the face). This appears to be almost twice as fast the initial method above:

With the cost of adding the colors being quite small (about 20 ms out a total 120 ms, which is roughly the same as doing the Unweld):

Anywho, I wonder though if MeshVertexColorList.SetColor Method (MeshFace, Color) should be considered broken here (i.e. it only sets one vertex corner when the input is unwelded as par the second example in my original post).

I agree this is broken based on the apparently intended functionality. @Dale is this something you can confirm?
MeshVertexColorList.SetColor Method will set only one vertex’s color resulting in this outcome for an unwelded mesh: (only each lower-right corner is colored)

-Willem

Indeed, also this does not appear to be exclusive to unwelded meshes (also the mesh vertices must already have colors, otherwise you get an IndexOutOfRangeException back), just did a more minimal test:

180416_MeshVertexColorListSetColor_00.gh (15.1 KB)

Hi @Willem, @AndersDeleuran,

For mesh vertex colors, which are optional, either Mesh.VertexColors.Count is zero or it has the same count as Mesh.Vertices.Count, in which case Mesh.VertexColors{i] reports the color assigned to Mesh.Vertices[i].

Does this help?

– Dale

Hi @dale,

i think what @AndersDeleuran and @Willem report is that it does not work for all 4 vertices when a mesh face is used to assign a color, even after all colors have been set using CreateMonotoneMesh. An error is probably in this method. I have not tested it yet.

_
c.

That’s exactly right @clement. I attached the minimal example demonstrating this above in the Grasshopper definition.

@AndersDeleuran,

This:

m.VertexColors.SetColor(f,c)

should produce the same result as this:

m.VertexColors.SetColor(f.A, c)
m.VertexColors.SetColor(f.B, c)
m.VertexColors.SetColor(f.C, c)
m.VertexColors.SetColor(f.D, c)

I’ll dig into this more…

https://mcneel.myjetbrains.com/youtrack/issue/RH-45553

– Dale

2 Likes

This is great @dale!

While we’re at it: I wonder if a simple workaround to all this might be to add the option that Mesh.Unweld takes no angleToleranceRadians input, and thereby makes an absolute/hard unweld without checking the difference of normals (which I assume is what makes it quite heavy to call on large meshes)?

Hi @AndersDeleuran,

I believe passing an angle tolerance of zero to Mesh.Unweld should do the trick. Also, you could just run through each of the faces, make a copy of the vertex and set the face.vi to the new index. Run compact when it’s done to get rid of the no longer referenced vertexes and then run compute vertex normals to cook up new normals from the face normals.

– Dale

It does indeed (as per my original post), but is still quite heavy/slow on large meshes, due to the normal checking that is going under the hood I assume (which isn’t needed as we know we want to unweld everything in this case). So my point is that if one gives the method an angle tolerance of zero (or nothing), the method should skip the normal checking, which should severely speed things up (again, I assume).

That is the other method I’ve been going with in the posts above, where the last one is a bit faster, but still these large loops are inherently costly (especially in Python), and again, it feels a bit like a dodgy workaround (to something unweld should be capable of doing faster).

Thanks again.

Edit: Also, being able set all face colors in one go (ala MeshVertexColorList.SetColors) would be great, in case you guys will be fiddling with any of this.

1 Like

Hi @AndersDeleuran,

I followed your discussion regarding mesh coloring.

I would like to ask if it is possible to display shading using unwelded meshes?
If I turn off mesh edges it is hardly possible to understand the geometry.

I tried rebuildnormals() but it does not change anything.
meshunwelded.3dm (54.1 KB)

You can set up your Rhino display like this:

That said, I usually grab the hard and/or naked edges and render those directly in Grasshopper (i.e. not using vertex color shading, as this makes the data visualisation “incorrect” and hard to read).

1 Like

I see what you mean and thank you for an answer, it helps a lot.

But is it possible to shade vertex colors as you did in rhino likewise in Grasshopper?

In my case only rhino preview changes (right not left):

1 Like

Hi Petras, sorry I missed your last post. I’m sure it’s possible through the display pipeline using code. I tend to simply explode my mesh into sub-meshes, and then render those using different materials:

210107_MeshRendering_00.gh (11.1 KB)

6 Likes

Thank you Anders :wink:

1 Like