I am developing a custom c# component in Visual Studio with a series of “buttons” that can be turned on/off and depending on their status the component will show some items (a mix of points, lines, meshes, text, etc.).
While debugging, I have noticed that the methods DrawViewportWires and DrawViewportMeshes are called several times and I am afraid this may affect the performance of the component in case of large models. I don’t have very expensive computations in these two methods, but there are some basic operations that get executed.
I would like to better understand how these two methods work and what I can do to improve the efficiency of the component. I have seen that there are some attributes (Display.DrawingGrips, Display.DrawingSurfaces, Display.DrawingWires), but I couldn’t really understand what they do and how to take advantage of them.
I am imagining, IF text, lines and meshes are drawn on different calls of the methods, is there a way to avoid creating items that won’t be displayed in that particular call? To better explain, say that on the first call only the text is displayed, on the second the lines and on the third the meshes. In the DrawViewportWires I compute some lines, but I would want that to be done only on the second call - if this make sense?
Hopefully the above is clear. Thanks in advance.
When you override those methods or a DisplayConduit, you are putting your code into a stack that will be processed when Rhino is asked to redraw its viewports. Using these methods, you usually don’t need to ask Rhino to redraw, Rhino or GH takes care of that. They do this when necessary, but you can also ask the views to be drawn if you need to.
To improve performance, you usually create caches of your geometry, that is, you store a reference (inside the class used to draw) to the created geometry to be draw, and only recompute the process that creates it when you need to update the cache, for example when the inputs have changed.
if(_cache == null)
_cache = CreateMeshesToDraw();
// draw cache
Once you no longer run more code than necessary, there is little else you can do. I suppose that some overload of the methods to draw that receive a collection of elements instead of a single element are more efficient, but this depends on if you want to draw them all with the same appearance. The resolution of the meshes should be low enough to draw quickly and high enough to look good. There are more technical details but before you worry about that you should solve all this first, and surely it is enough.
It should be called once per redraw per viewport.
Correct, I have double checked now and it is called once per redraw. I guess I was mistaken for the fact that they are called 5 times at the beginning of the debugging process - I suppose once for each viewport that is created at first.
Thanks for this, I think it is helpful.
My question now would be, wouldn’t it be better to recompute the geometry outside of the DrawViewport methods? Given that this methods are called every time the viewport has to be updated.
I mean, I guess I should recompute, recreate and store the geometry that I need every time the input changes, while keeping in the DrawViewport methods only the Display.Draw methods.
Yes, you should do as little as possible during the drawing methods. You usually compute your geometry during
ComputeData() depending on whether you’re doing this inside a component or a parameter.
If that’s not possible then you should calculate your shapes once during the first draw call and cache the results.