Colour gradient number remapping

The Mesh.VertexColors.SetColor method edits the input mesh M in place. So we just pass it in, manipulate it, and output it again. If one wanted to get super terse with things, you could even do a one-liner using list comprehension:


230922_ColorMeshFaces_Native_01.gh (848.5 KB)

Though I certainly prefer the more readable for loop :slight_smile:

Me too.

The main thing I’ve learned from your Python is that colors are set at vertices, not faces?

for i in range(M.Faces.Count):
    M.VertexColors.SetColor(M.Faces[i],C[i])

And from the API doc:

Description:

Sets a color at the three or four vertex indices of a specified face.

So with that in mind, I tried again to make MCol (Mesh Colors) work, but failed because I didn’t account for vertices being shared by adjacent faces. (teal group below)

So I looked again at your code using native components, copying it into my cmesh_demo code (cyan group below). The first thing I noticed is the flattened inputs on Sort, which makes it unsuitable for data trees, eh? So I added the yellow group to switch between ‘One’ mesh or ‘Three’ in a branched data tree, looking only at the ‘One’ mesh / branch. But the result is not what I expect?

CMesh result (correct):

cmesh_demo_2023Sep23b2

ConMesh result (incorrect):

cmesh_demo_2023Sep23b3

So two questions:

  1. What is going on here and how is this done with native components?

  2. How is MCol (Mesh Colors) used?


cmesh_demo_2023Sep23b.gh (42.4 KB)

P.S. Your elegant, simple Python solution also fails this test: :cry:

Runtime error (IndexOutOfRangeException): Index was outside the bounds of the array.

Traceback:
line 3, in script

The number of colors matches the number of faces.

@AndersDeleuran, btw how did you simplify the appearance of your GH components??? You seem to be a true GH hacker …

I think I finally figured out the answer to this question :exclamation:
MCol ‘C’ (Colors) input is expected to have one color per vertex.


cmesh_demo_2023Sep23c.gh (20.6 KB)

The original subject of this thread has one color per face, with 15918 faces and 62077 vertices.

OH!
… what is the usefulness of having a color associated to a vertex instead of a face? that is very counter-intuitive.

1 Like

For the uninitiated (including me), that makes sense. Faces seem like the most important feature of meshes, including the ability to color them separately. But I’m guessing there are good reasons, such as the ability to make meshes look smooth by color gradients across their faces?

Look what happens when you apply Weld Mesh to the crisp edges from my CMesh cluster:

cmesh_demo_2023Sep23a2

The .gif file makes it look pixelated due to limited colors; this image shows how smooth it really is:

3 Likes

Using the CapsuleRenderer plugin from the package manager. The only must-have plugin for me. It’s great to see Grasshopper 2 adopting a similar design.

1 Like

Sorry missed this reply. As I said above, I don’t suspect this is simple to solve using native components (if you exclude scripting). Or, it certainly isn’t for me, with all the indirect data tree hoop jumping involved! So I can’t really help further.

I believe it colors the vertices. Which makes sense, since the Mesh.VertexColors.SetColor overload I’m using above that colors the faces wasn’t added till Rhino 5. And was broken well into Rhino 6. I think it is reasonable to update the Mesh Colour (MCol) component with a Mode input parameter, letting the user decide whether to color:

  1. Vertices = Input a list of colors, one per vertex.
  2. Faces = Input a list of colors, one per face.
  3. Monotone = Input one color that calls this method.

Or at the very least, update its documentation to more explicitly describe what’s actually going on. As this is clearly causing confusion.

I guess my CMesh cluster nailed it then. Not bad for being clueless about meshes. :slight_smile:

Weld Mesh can be applied afterwards to smooth / blend colors, if desired.

Hehe, that’s a nice workaround. But it’s not exactly efficient:

If you’re okay with the inefficiency of generating individual meshes per face, something like this performs better:


230924_ColorMeshFaces_Comparison_00.gh (1.2 MB)

But again, it’s an inefficient hacky workaround to something you can solve directly/simpler with code :man_shrugging:

I tried something like that but missed this detail for the ‘F’ input of ConMesh: (odd since it is the default, must have been a different mistake)

230924_ColorMeshFaces_Comparison_00

This cluster doesn’t work for three meshes, one per branch. Adding PShift after ConMesh instead of flattening its output doesn’t fix it.

  1. Supplied index too high.

By the way, you can significantly reduce the size of that GH file by having only one copy of the mesh and colors params - 434 KB instead of 1.24 MB.

230924_ColorMeshFaces_Comparison_003

As noted yesterday in the P.S. to this post, the Python code fails when using only one mesh in my cmesh_demo GH file. So don’t know if it would handle three meshes, one per branch?
cmesh_demo_2023Sep24aa.gh (30.0 KB)

Runtime error (IndexOutOfRangeException): Index was outside the bounds of the array.

Traceback:
line 3, in script

The high performance of API solutions is great but not the most important thing.

As noted in the other thread I’ve linked to, and in the colorMeshFaces function in my first post, the Mesh.VertexColors.SetColor method prerequisites the input mesh to have vertex colors:


cmesh_demo_2023Sep24aa_fix.gh (20.7 KB)

Which I’d probably consider a bug, or at least unexpected.

I read a post you referred to, not the whole thread. So this unexpected bug has been “well-known” at McNeel for at least 7.5 years (since April 2016) and not fixed yet. So typical.