DrawMeshFalseColors but with shading

Hi @dale, @stevebaer, @jeff

i have a Rhino.Display.DisplayConduit in which i want to display my mesh with vertex colors. So far this works using below :

def PostDrawObjects(self, e):
    e.Display.DrawMeshFalseColors(self.m_mesh)

The mesh is displayed, but constant colored, so there is no shading or lighting. Is there a way to draw in the my conduit with shading / lighting and vertex colors ?

I’ve tried all combinations of DisplayPipelineAttributes:

def PostDrawObjects(self, e):
    e.Display.DisplayPipelineAttributes.ShadingEnabled = True
    e.Display.DisplayPipelineAttributes.ShadeVertexColors = True
    e.Display.EnableLighting(True)
    e.Display.DrawMeshFalseColors(self.m_mesh)

but the mesh is only constant colored. No shade (left image below)

If i add my mesh to the document, it is displayed with vertex colors and shading (right image). I have “shade vertex colors” checked in the display panel. So it seems possible in a regular display mode but not in a conduit ?

thanks,
c.

Why are you using DrawFalseColorMesh? I believe that routine is used for analysis modes and specifically and purposely turns off lighting and shading.

Just draw the mesh as you would any mesh…if it has vertex colors Rhino will use them…according to the display attributes set…which it looks like you are setting correctly.

-J

Hi @jeff, because it is the only way to draw a mesh with vertex colors.

that was the first thing i tried. It does not draw any vertex colors if i draw it like this:

# setup on init
self.m_material = Rhino.Display.DisplayMaterial()

def PostDrawObjects(self, e):
    e.Display.DrawMeshShaded(self.m_mesh, self.m_material)

Also tried above mentioned DisplayPipelineAttributes, no dice. Is there a different method to draw it i don’t know about ?

thanks,
c.

Hmmmm…ok. Sounds like a bug in Common then (i.e. vertex colors getting stripped before calling into the core draw routine)… I’ll see if I can reproduce it here in a bit…but a simple example would help speed the process.

-J

Thanks for the info, then i can stop trying. Below is an example script with comments:

Sample_DrawMeshShaded.py (1.6 KB)

To run it, either use _EditPythonScript or _ScriptEditor then open the script and press F5

thanks,
c.

Thanks for the example… found the reason immediately…

The color count on the vertex color array is purposely getting set to 0 (temporarily) just before calling into the core… There is a comment in the Common function:

// don’t permit false color drawing in this function.

… I’m not sure why this was/is done… I’ll see if Steve knows why. The concept of “false color” is not the same as “vertex coloring” IMO… but it seems like the two are being conflated across the mesh drawing API.

I’ll let you know what we find/decide…and if there is another way you can do this from within a script.

Thanks,
-Jeff

Thank you @jeff, maybe we’ll just need another flag to let users control this in the attributes of the DisplayPipeline. I’d prefer to have a toggle between lit and unlit mesh vertex coloring.

_
c.

It looks like if you use the other DrawMeshShaded (the one that takes a face list), then the vertex color list won’t get zeroed out…

        # Just draw all faces for the given mesh...
        face_list = list(range(0, self.m_mesh.Faces.Count - 1))
        e.Display.DrawMeshShaded(self.m_mesh, self.m_material, face_list)

That seems to be working here.

Haven’t had a chance to discuss the other issue with Steve yet.

-J

1 Like

@jeff, thank you. That works here too. Have a nice weekend !

_
c.

You too!

You probably have already done this by now :slight_smile: … But I thought I’d share it anyways…based on your last comments…

You could write your own DrawShadedMesh method to handle the lighting results…

    def DrawShadedMesh(self, e, lit):
        if lit:
            e.Display.DisplayPipelineAttributes.ShadingEnabled = True
            e.Display.DisplayPipelineAttributes.ShadeVertexColors = True
            e.Display.EnableLighting(True)
            face_list = list(range(0, self.m_mesh.Faces.Count))
            e.Display.DrawMeshShaded(self.m_mesh, self.m_material, face_list)
        else:
            e.Display.DrawMeshFalseColors(self.m_mesh)   

    def PostDrawObjects(self, e):
        useLighting = True;
        self.DrawShadedMesh(e, useLighting)
        

…and tie useLighting to some other configurable setting… Just a thought for now, until we figure out a better way to handle this in scripting.

-J

3 Likes

Thank you @jeff. That’s close to what i did, i just build the indices once on init.

you seem to have fun with Python too :slight_smile:

_
c.

LOL… I figured as much… Tried to clean things up before you saw my hackery :slight_smile:

Anyways…looks like you’ve got things sorted for now.

-J

Hi, I’m trying to achieve the same result inside a GetPoint.DynamicDraw.

The shaded mesh with vertex colors looks good with the trick @jeff suggested.
But what if I want to add also mesh wires?

I tried to set

e.Display.DisplayPipelineAttributes.MeshSpecificAttributes.ShowMeshWires = true;

but it doesn’t seem to work.

NOTE: manually calling e.Display.DrawMeshWires(m_mesh, Color.Black); obviously adds wires, but they are drawn back/front facing without any depth test (even if depth test flags are set) and I do not want my preview mesh to look “see-through”.

Any work around that pops to your mind?
Thanks :slight_smile:

1 Like

Yes, stop drawing depth tested, depth writing, shaded meshes in Rhino’s display overlay channel :wink:

That’s basically what the DynamicDraw routine does…it turns off all depth testing/writing, and executes any/all pending (queued up) dynamic draws…and it does this post-everything-else. It’s primary function/design was for feedback processing for commands…which usually only involves wires and annotative type objects, and it is assumed to always draw everything on top of the current frame buffer.

The usual way to implement this type of thing, where you’ve got your own GetPoint, and you want to draw depth-buffered, shaded meshes, is that you do so in a Display Conduit, and your GetPoint invocation enables/disables the conduit. Then in your conduit, you can determine in which channel you want to draw your geometry (usually in the Pre/Post draw channels), and you make the appropriate calls to do so… This way your geometry will interact (and play nice) with all of the other objects in the scene.

A simple example of what you’re doing and what you want to achieve will go a long way here… and I’ll be glad to modify or add to it to show you what I mean.

-J

Thank you @jeff I created a separate post, to avoid getting off-topic.
Here it is → brush-like-mesh-faces-selection-during-getpoint

Cheers