Override OnDraw of CustomBrepObject with caching?

Hi all,

I have a custom brep object inherited from CustomBrepObject, and I override its OnDraw with custom DisplayMaterial.

I noticed that e.Display.DrawMeshShaded(mesh, material) is invoked in every frame when I rotate the view. However it seems there is a caching mechanism within base.OnDraw(e) that prevent Rhino “redraw” meshes for every frames.

I am testing an architectural model with more than 10,000 objects , and Rhino gets slow with following code.

        protected override void OnDraw(DrawEventArgs e)
        {
            if (e.Display.DrawingSurfaces)
            {
                var material = new DisplayMaterial(Color.FromArgb(120, 75, 190));
                var mesh = this.GetMeshes(MeshType.Default);
                foreach (var item in mesh)
                {
                    e.Display.DrawMeshShaded(item, material);
                }
            }
        }

With Rhino’s "caching mechanism"
FPS is much better with following code. Rhino keeps e.Display.DrawingSurfaces false which prevents it redraw meshes every frame when I replace my code with base.OnDraw(e). It is only involved when object is modified.

        protected override void OnDraw(DrawEventArgs e)
        {
            if (e.Display.DrawingSurfaces)
            {
                //var material = new DisplayMaterial(Color.FromArgb(120, 75, 190));
                //var mesh = this.GetMeshes(MeshType.Default);
                //foreach (var item in mesh)
                //{
                //    e.Display.DrawMeshShaded(item, material);
                //}
                base.OnDraw(e);
            }
        }

So my question is how can I enable this “caching mechanism” for my custom object to improve the FPS for a larger model?

Thanks in advance.

cc @dale

I would imagine a good part of your performance hit is coming from GetMeshes sitting inside each frame redraw.

Hi Mingbo,
We don’t really have a decent caching mechanism for custom objects as we don’t know what the draw routine is going to do. One of the areas where we work on improving performance is by minimizing the number of times we change the material setup on the GPU for drawing. This is done by internally computing a hash of the display material and then checking to see if that has matches what is already set up. We might be able to make some improvements in this area if your material information rarely changes.

You should also move all calls to create new instances of classes outside of your draw routine if possible. In this sample, you should make the material a field on your conduit and new it up only once. This may also improve internal caching for the material.

Thanks @Trav @stevebaer,

Thanks for your info.
Yes my display materials will never change. We have a standard color (display material) set for energy/daylight analytical model. Above code (a new instance of material) is just for demonstrating the problem.

Hi @stevebaer, when you get a chance to improve this, would it be possible to include the transparency check for display materials? So that it draws transparent object in a correct order.

If it is hard to do on your side without knowing the display material, would it possible to expose a property for custom objects for me to set them as transparent, or anything to let Rhino know this is a transparent object when deciding the drawing order internally? I tried to reorder transparent objects in PostDrawObjects, but Rhino gets super slow with a large model I mentioned above.